/**
 * @popperjs/core v2.11.8 - MIT License
 */

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

    function getWindow(node) {
        if (node == null) {
            return window;
        }

        if (node.toString() !== '[object Window]') {
            var ownerDocument = node.ownerDocument;
            return ownerDocument ? ownerDocument.defaultView || window : window;
        }

        return node;
    }

    function isElement(node) {
        var OwnElement = getWindow(node).Element;
        return node instanceof OwnElement || node instanceof Element;
    }

    function isHTMLElement(node) {
        var OwnElement = getWindow(node).HTMLElement;
        return node instanceof OwnElement || node instanceof HTMLElement;
    }

    function isShadowRoot(node) {
        // IE 11 has no ShadowRoot
        if (typeof ShadowRoot === 'undefined') {
            return false;
        }

        var OwnElement = getWindow(node).ShadowRoot;
        return node instanceof OwnElement || node instanceof ShadowRoot;
    }

    var max = Math.max;
    var min = Math.min;
    var round = Math.round;

    function getUAString() {
        var uaData = navigator.userAgentData;

        if (uaData != null && uaData.brands && Array.isArray(uaData.brands)) {
            return uaData.brands.map(function(item) {
                return item.brand + "/" + item.version;
            }).join(' ');
        }

        return navigator.userAgent;
    }

    function isLayoutViewport() {
        return !/^((?!chrome|android).)*safari/i.test(getUAString());
    }

    function getBoundingClientRect(element, includeScale, isFixedStrategy) {
        if (includeScale === void 0) {
            includeScale = false;
        }

        if (isFixedStrategy === void 0) {
            isFixedStrategy = false;
        }

        var clientRect = element.getBoundingClientRect();
        var scaleX = 1;
        var scaleY = 1;

        if (includeScale && isHTMLElement(element)) {
            scaleX = element.offsetWidth > 0 ? round(clientRect.width) / element.offsetWidth || 1 : 1;
            scaleY = element.offsetHeight > 0 ? round(clientRect.height) / element.offsetHeight || 1 : 1;
        }

        var _ref = isElement(element) ? getWindow(element) : window,
            visualViewport = _ref.visualViewport;

        var addVisualOffsets = !isLayoutViewport() && isFixedStrategy;
        var x = (clientRect.left + (addVisualOffsets && visualViewport ? visualViewport.offsetLeft : 0)) / scaleX;
        var y = (clientRect.top + (addVisualOffsets && visualViewport ? visualViewport.offsetTop : 0)) / scaleY;
        var width = clientRect.width / scaleX;
        var height = clientRect.height / scaleY;
        return {
            width: width,
            height: height,
            top: y,
            right: x + width,
            bottom: y + height,
            left: x,
            x: x,
            y: y
        };
    }

    function getWindowScroll(node) {
        var win = getWindow(node);
        var scrollLeft = win.pageXOffset;
        var scrollTop = win.pageYOffset;
        return {
            scrollLeft: scrollLeft,
            scrollTop: scrollTop
        };
    }

    function getHTMLElementScroll(element) {
        return {
            scrollLeft: element.scrollLeft,
            scrollTop: element.scrollTop
        };
    }

    function getNodeScroll(node) {
        if (node === getWindow(node) || !isHTMLElement(node)) {
            return getWindowScroll(node);
        } else {
            return getHTMLElementScroll(node);
        }
    }

    function getNodeName(element) {
        return element ? (element.nodeName || '').toLowerCase() : null;
    }

    function getDocumentElement(element) {
        // $FlowFixMe[incompatible-return]: assume body is always available
        return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing]
            element.document) || window.document).documentElement;
    }

    function getWindowScrollBarX(element) {
        // If <html> has a CSS width greater than the viewport, then this will be
        // incorrect for RTL.
        // Popper 1 is broken in this case and never had a bug report so let's assume
        // it's not an issue. I don't think anyone ever specifies width on <html>
        // anyway.
        // Browsers where the left scrollbar doesn't cause an issue report `0` for
        // this (e.g. Edge 2019, IE11, Safari)
        return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft;
    }

    function getComputedStyle(element) {
        return getWindow(element).getComputedStyle(element);
    }

    function isScrollParent(element) {
        // Firefox wants us to check `-x` and `-y` variations as well
        var _getComputedStyle = getComputedStyle(element),
            overflow = _getComputedStyle.overflow,
            overflowX = _getComputedStyle.overflowX,
            overflowY = _getComputedStyle.overflowY;

        return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX);
    }

    function isElementScaled(element) {
        var rect = element.getBoundingClientRect();
        var scaleX = round(rect.width) / element.offsetWidth || 1;
        var scaleY = round(rect.height) / element.offsetHeight || 1;
        return scaleX !== 1 || scaleY !== 1;
    } // Returns the composite rect of an element relative to its offsetParent.
    // Composite means it takes into account transforms as well as layout.


    function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) {
        if (isFixed === void 0) {
            isFixed = false;
        }

        var isOffsetParentAnElement = isHTMLElement(offsetParent);
        var offsetParentIsScaled = isHTMLElement(offsetParent) && isElementScaled(offsetParent);
        var documentElement = getDocumentElement(offsetParent);
        var rect = getBoundingClientRect(elementOrVirtualElement, offsetParentIsScaled, isFixed);
        var scroll = {
            scrollLeft: 0,
            scrollTop: 0
        };
        var offsets = {
            x: 0,
            y: 0
        };

        if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
            if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078
                isScrollParent(documentElement)) {
                scroll = getNodeScroll(offsetParent);
            }

            if (isHTMLElement(offsetParent)) {
                offsets = getBoundingClientRect(offsetParent, true);
                offsets.x += offsetParent.clientLeft;
                offsets.y += offsetParent.clientTop;
            } else if (documentElement) {
                offsets.x = getWindowScrollBarX(documentElement);
            }
        }

        return {
            x: rect.left + scroll.scrollLeft - offsets.x,
            y: rect.top + scroll.scrollTop - offsets.y,
            width: rect.width,
            height: rect.height
        };
    }

    // means it doesn't take into account transforms.

    function getLayoutRect(element) {
        var clientRect = getBoundingClientRect(element); // Use the clientRect sizes if it's not been transformed.
        // Fixes https://github.com/popperjs/popper-core/issues/1223

        var width = element.offsetWidth;
        var height = element.offsetHeight;

        if (Math.abs(clientRect.width - width) <= 1) {
            width = clientRect.width;
        }

        if (Math.abs(clientRect.height - height) <= 1) {
            height = clientRect.height;
        }

        return {
            x: element.offsetLeft,
            y: element.offsetTop,
            width: width,
            height: height
        };
    }

    function getParentNode(element) {
        if (getNodeName(element) === 'html') {
            return element;
        }

        return ( // this is a quicker (but less type safe) way to save quite some bytes from the bundle
            // $FlowFixMe[incompatible-return]
            // $FlowFixMe[prop-missing]
            element.assignedSlot || // step into the shadow DOM of the parent of a slotted node
            element.parentNode || ( // DOM Element detected
                isShadowRoot(element) ? element.host : null) || // ShadowRoot detected
            // $FlowFixMe[incompatible-call]: HTMLElement is a Node
            getDocumentElement(element) // fallback

        );
    }

    function getScrollParent(node) {
        if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) {
            // $FlowFixMe[incompatible-return]: assume body is always available
            return node.ownerDocument.body;
        }

        if (isHTMLElement(node) && isScrollParent(node)) {
            return node;
        }

        return getScrollParent(getParentNode(node));
    }

    /*
    given a DOM element, return the list of all scroll parents, up the list of ancesors
    until we get to the top window object. This list is what we attach scroll listeners
    to, because if any of these parent elements scroll, we'll need to re-calculate the
    reference element's position.
    */

    function listScrollParents(element, list) {
        var _element$ownerDocumen;

        if (list === void 0) {
            list = [];
        }

        var scrollParent = getScrollParent(element);
        var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body);
        var win = getWindow(scrollParent);
        var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent;
        var updatedList = list.concat(target);
        return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here
            updatedList.concat(listScrollParents(getParentNode(target)));
    }

    function isTableElement(element) {
        return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0;
    }

    function getTrueOffsetParent(element) {
        if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837
            getComputedStyle(element).position === 'fixed') {
            return null;
        }

        return element.offsetParent;
    } // `.offsetParent` reports `null` for fixed elements, while absolute elements
    // return the containing block


    function getContainingBlock(element) {
        var isFirefox = /firefox/i.test(getUAString());
        var isIE = /Trident/i.test(getUAString());

        if (isIE && isHTMLElement(element)) {
            // In IE 9, 10 and 11 fixed elements containing block is always established by the viewport
            var elementCss = getComputedStyle(element);

            if (elementCss.position === 'fixed') {
                return null;
            }
        }

        var currentNode = getParentNode(element);

        if (isShadowRoot(currentNode)) {
            currentNode = currentNode.host;
        }

        while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) {
            var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that
            // create a containing block.
            // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block

            if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].indexOf(css.willChange) !== -1 || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') {
                return currentNode;
            } else {
                currentNode = currentNode.parentNode;
            }
        }

        return null;
    } // Gets the closest ancestor positioned element. Handles some edge cases,
    // such as table ancestors and cross browser bugs.


    function getOffsetParent(element) {
        var window = getWindow(element);
        var offsetParent = getTrueOffsetParent(element);

        while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') {
            offsetParent = getTrueOffsetParent(offsetParent);
        }

        if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) {
            return window;
        }

        return offsetParent || getContainingBlock(element) || window;
    }

    var top = 'top';
    var bottom = 'bottom';
    var right = 'right';
    var left = 'left';
    var auto = 'auto';
    var basePlacements = [top, bottom, right, left];
    var start = 'start';
    var end = 'end';
    var clippingParents = 'clippingParents';
    var viewport = 'viewport';
    var popper = 'popper';
    var reference = 'reference';
    var variationPlacements = /*#__PURE__*/ basePlacements.reduce(function(acc, placement) {
        return acc.concat([placement + "-" + start, placement + "-" + end]);
    }, []);
    var placements = /*#__PURE__*/ [].concat(basePlacements, [auto]).reduce(function(acc, placement) {
        return acc.concat([placement, placement + "-" + start, placement + "-" + end]);
    }, []); // modifiers that need to read the DOM

    var beforeRead = 'beforeRead';
    var read = 'read';
    var afterRead = 'afterRead'; // pure-logic modifiers

    var beforeMain = 'beforeMain';
    var main = 'main';
    var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state)

    var beforeWrite = 'beforeWrite';
    var write = 'write';
    var afterWrite = 'afterWrite';
    var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite];

    function order(modifiers) {
        var map = new Map();
        var visited = new Set();
        var result = [];
        modifiers.forEach(function(modifier) {
            map.set(modifier.name, modifier);
        }); // On visiting object, check for its dependencies and visit them recursively

        function sort(modifier) {
            visited.add(modifier.name);
            var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []);
            requires.forEach(function(dep) {
                if (!visited.has(dep)) {
                    var depModifier = map.get(dep);

                    if (depModifier) {
                        sort(depModifier);
                    }
                }
            });
            result.push(modifier);
        }

        modifiers.forEach(function(modifier) {
            if (!visited.has(modifier.name)) {
                // check for visited object
                sort(modifier);
            }
        });
        return result;
    }

    function orderModifiers(modifiers) {
        // order based on dependencies
        var orderedModifiers = order(modifiers); // order based on phase

        return modifierPhases.reduce(function(acc, phase) {
            return acc.concat(orderedModifiers.filter(function(modifier) {
                return modifier.phase === phase;
            }));
        }, []);
    }

    function debounce(fn) {
        var pending;
        return function() {
            if (!pending) {
                pending = new Promise(function(resolve) {
                    Promise.resolve().then(function() {
                        pending = undefined;
                        resolve(fn());
                    });
                });
            }

            return pending;
        };
    }

    function mergeByName(modifiers) {
        var merged = modifiers.reduce(function(merged, current) {
            var existing = merged[current.name];
            merged[current.name] = existing ? Object.assign({}, existing, current, {
                options: Object.assign({}, existing.options, current.options),
                data: Object.assign({}, existing.data, current.data)
            }) : current;
            return merged;
        }, {}); // IE11 does not support Object.values

        return Object.keys(merged).map(function(key) {
            return merged[key];
        });
    }

    function getViewportRect(element, strategy) {
        var win = getWindow(element);
        var html = getDocumentElement(element);
        var visualViewport = win.visualViewport;
        var width = html.clientWidth;
        var height = html.clientHeight;
        var x = 0;
        var y = 0;

        if (visualViewport) {
            width = visualViewport.width;
            height = visualViewport.height;
            var layoutViewport = isLayoutViewport();

            if (layoutViewport || !layoutViewport && strategy === 'fixed') {
                x = visualViewport.offsetLeft;
                y = visualViewport.offsetTop;
            }
        }

        return {
            width: width,
            height: height,
            x: x + getWindowScrollBarX(element),
            y: y
        };
    }

    // of the `<html>` and `<body>` rect bounds if horizontally scrollable

    function getDocumentRect(element) {
        var _element$ownerDocumen;

        var html = getDocumentElement(element);
        var winScroll = getWindowScroll(element);
        var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body;
        var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0);
        var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0);
        var x = -winScroll.scrollLeft + getWindowScrollBarX(element);
        var y = -winScroll.scrollTop;

        if (getComputedStyle(body || html).direction === 'rtl') {
            x += max(html.clientWidth, body ? body.clientWidth : 0) - width;
        }

        return {
            width: width,
            height: height,
            x: x,
            y: y
        };
    }

    function contains(parent, child) {
        var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method

        if (parent.contains(child)) {
            return true;
        } // then fallback to custom implementation with Shadow DOM support
        else if (rootNode && isShadowRoot(rootNode)) {
            var next = child;

            do {
                if (next && parent.isSameNode(next)) {
                    return true;
                } // $FlowFixMe[prop-missing]: need a better way to handle this...


                next = next.parentNode || next.host;
            } while (next);
        } // Give up, the result is false


        return false;
    }

    function rectToClientRect(rect) {
        return Object.assign({}, rect, {
            left: rect.x,
            top: rect.y,
            right: rect.x + rect.width,
            bottom: rect.y + rect.height
        });
    }

    function getInnerBoundingClientRect(element, strategy) {
        var rect = getBoundingClientRect(element, false, strategy === 'fixed');
        rect.top = rect.top + element.clientTop;
        rect.left = rect.left + element.clientLeft;
        rect.bottom = rect.top + element.clientHeight;
        rect.right = rect.left + element.clientWidth;
        rect.width = element.clientWidth;
        rect.height = element.clientHeight;
        rect.x = rect.left;
        rect.y = rect.top;
        return rect;
    }

    function getClientRectFromMixedType(element, clippingParent, strategy) {
        return clippingParent === viewport ? rectToClientRect(getViewportRect(element, strategy)) : isElement(clippingParent) ? getInnerBoundingClientRect(clippingParent, strategy) : rectToClientRect(getDocumentRect(getDocumentElement(element)));
    } // A "clipping parent" is an overflowable container with the characteristic of
    // clipping (or hiding) overflowing elements with a position different from
    // `initial`


    function getClippingParents(element) {
        var clippingParents = listScrollParents(getParentNode(element));
        var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0;
        var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element;

        if (!isElement(clipperElement)) {
            return [];
        } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414


        return clippingParents.filter(function(clippingParent) {
            return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body';
        });
    } // Gets the maximum area that the element is visible in due to any number of
    // clipping parents


    function getClippingRect(element, boundary, rootBoundary, strategy) {
        var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary);
        var clippingParents = [].concat(mainClippingParents, [rootBoundary]);
        var firstClippingParent = clippingParents[0];
        var clippingRect = clippingParents.reduce(function(accRect, clippingParent) {
            var rect = getClientRectFromMixedType(element, clippingParent, strategy);
            accRect.top = max(rect.top, accRect.top);
            accRect.right = min(rect.right, accRect.right);
            accRect.bottom = min(rect.bottom, accRect.bottom);
            accRect.left = max(rect.left, accRect.left);
            return accRect;
        }, getClientRectFromMixedType(element, firstClippingParent, strategy));
        clippingRect.width = clippingRect.right - clippingRect.left;
        clippingRect.height = clippingRect.bottom - clippingRect.top;
        clippingRect.x = clippingRect.left;
        clippingRect.y = clippingRect.top;
        return clippingRect;
    }

    function getBasePlacement(placement) {
        return placement.split('-')[0];
    }

    function getVariation(placement) {
        return placement.split('-')[1];
    }

    function getMainAxisFromPlacement(placement) {
        return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y';
    }

    function computeOffsets(_ref) {
        var reference = _ref.reference,
            element = _ref.element,
            placement = _ref.placement;
        var basePlacement = placement ? getBasePlacement(placement) : null;
        var variation = placement ? getVariation(placement) : null;
        var commonX = reference.x + reference.width / 2 - element.width / 2;
        var commonY = reference.y + reference.height / 2 - element.height / 2;
        var offsets;

        switch (basePlacement) {
            case top:
                offsets = {
                    x: commonX,
                    y: reference.y - element.height
                };
                break;

            case bottom:
                offsets = {
                    x: commonX,
                    y: reference.y + reference.height
                };
                break;

            case right:
                offsets = {
                    x: reference.x + reference.width,
                    y: commonY
                };
                break;

            case left:
                offsets = {
                    x: reference.x - element.width,
                    y: commonY
                };
                break;

            default:
                offsets = {
                    x: reference.x,
                    y: reference.y
                };
        }

        var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null;

        if (mainAxis != null) {
            var len = mainAxis === 'y' ? 'height' : 'width';

            switch (variation) {
                case start:
                    offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2);
                    break;

                case end:
                    offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2);
                    break;
            }
        }

        return offsets;
    }

    function getFreshSideObject() {
        return {
            top: 0,
            right: 0,
            bottom: 0,
            left: 0
        };
    }

    function mergePaddingObject(paddingObject) {
        return Object.assign({}, getFreshSideObject(), paddingObject);
    }

    function expandToHashMap(value, keys) {
        return keys.reduce(function(hashMap, key) {
            hashMap[key] = value;
            return hashMap;
        }, {});
    }

    function detectOverflow(state, options) {
        if (options === void 0) {
            options = {};
        }

        var _options = options,
            _options$placement = _options.placement,
            placement = _options$placement === void 0 ? state.placement : _options$placement,
            _options$strategy = _options.strategy,
            strategy = _options$strategy === void 0 ? state.strategy : _options$strategy,
            _options$boundary = _options.boundary,
            boundary = _options$boundary === void 0 ? clippingParents : _options$boundary,
            _options$rootBoundary = _options.rootBoundary,
            rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary,
            _options$elementConte = _options.elementContext,
            elementContext = _options$elementConte === void 0 ? popper : _options$elementConte,
            _options$altBoundary = _options.altBoundary,
            altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary,
            _options$padding = _options.padding,
            padding = _options$padding === void 0 ? 0 : _options$padding;
        var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
        var altContext = elementContext === popper ? reference : popper;
        var popperRect = state.rects.popper;
        var element = state.elements[altBoundary ? altContext : elementContext];
        var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary, strategy);
        var referenceClientRect = getBoundingClientRect(state.elements.reference);
        var popperOffsets = computeOffsets({
            reference: referenceClientRect,
            element: popperRect,
            strategy: 'absolute',
            placement: placement
        });
        var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets));
        var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect
        // 0 or negative = within the clipping rect

        var overflowOffsets = {
            top: clippingClientRect.top - elementClientRect.top + paddingObject.top,
            bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom,
            left: clippingClientRect.left - elementClientRect.left + paddingObject.left,
            right: elementClientRect.right - clippingClientRect.right + paddingObject.right
        };
        var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element

        if (elementContext === popper && offsetData) {
            var offset = offsetData[placement];
            Object.keys(overflowOffsets).forEach(function(key) {
                var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1;
                var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x';
                overflowOffsets[key] += offset[axis] * multiply;
            });
        }

        return overflowOffsets;
    }

    var DEFAULT_OPTIONS = {
        placement: 'bottom',
        modifiers: [],
        strategy: 'absolute'
    };

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

        return !args.some(function(element) {
            return !(element && typeof element.getBoundingClientRect === 'function');
        });
    }

    function popperGenerator(generatorOptions) {
        if (generatorOptions === void 0) {
            generatorOptions = {};
        }

        var _generatorOptions = generatorOptions,
            _generatorOptions$def = _generatorOptions.defaultModifiers,
            defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def,
            _generatorOptions$def2 = _generatorOptions.defaultOptions,
            defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2;
        return function createPopper(reference, popper, options) {
            if (options === void 0) {
                options = defaultOptions;
            }

            var state = {
                placement: 'bottom',
                orderedModifiers: [],
                options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions),
                modifiersData: {},
                elements: {
                    reference: reference,
                    popper: popper
                },
                attributes: {},
                styles: {}
            };
            var effectCleanupFns = [];
            var isDestroyed = false;
            var instance = {
                state: state,
                setOptions: function setOptions(setOptionsAction) {
                    var options = typeof setOptionsAction === 'function' ? setOptionsAction(state.options) : setOptionsAction;
                    cleanupModifierEffects();
                    state.options = Object.assign({}, defaultOptions, state.options, options);
                    state.scrollParents = {
                        reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [],
                        popper: listScrollParents(popper)
                    }; // Orders the modifiers based on their dependencies and `phase`
                    // properties

                    var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers

                    state.orderedModifiers = orderedModifiers.filter(function(m) {
                        return m.enabled;
                    });
                    runModifierEffects();
                    return instance.update();
                },
                // Sync update – it will always be executed, even if not necessary. This
                // is useful for low frequency updates where sync behavior simplifies the
                // logic.
                // For high frequency updates (e.g. `resize` and `scroll` events), always
                // prefer the async Popper#update method
                forceUpdate: function forceUpdate() {
                    if (isDestroyed) {
                        return;
                    }

                    var _state$elements = state.elements,
                        reference = _state$elements.reference,
                        popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements
                    // anymore

                    if (!areValidElements(reference, popper)) {
                        return;
                    } // Store the reference and popper rects to be read by modifiers


                    state.rects = {
                        reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'),
                        popper: getLayoutRect(popper)
                    }; // Modifiers have the ability to reset the current update cycle. The
                    // most common use case for this is the `flip` modifier changing the
                    // placement, which then needs to re-run all the modifiers, because the
                    // logic was previously ran for the previous placement and is therefore
                    // stale/incorrect

                    state.reset = false;
                    state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier
                    // is filled with the initial data specified by the modifier. This means
                    // it doesn't persist and is fresh on each update.
                    // To ensure persistent data, use `${name}#persistent`

                    state.orderedModifiers.forEach(function(modifier) {
                        return state.modifiersData[modifier.name] = Object.assign({}, modifier.data);
                    });

                    for (var index = 0; index < state.orderedModifiers.length; index++) {
                        if (state.reset === true) {
                            state.reset = false;
                            index = -1;
                            continue;
                        }

                        var _state$orderedModifie = state.orderedModifiers[index],
                            fn = _state$orderedModifie.fn,
                            _state$orderedModifie2 = _state$orderedModifie.options,
                            _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2,
                            name = _state$orderedModifie.name;

                        if (typeof fn === 'function') {
                            state = fn({
                                state: state,
                                options: _options,
                                name: name,
                                instance: instance
                            }) || state;
                        }
                    }
                },
                // Async and optimistically optimized update – it will not be executed if
                // not necessary (debounced to run at most once-per-tick)
                update: debounce(function() {
                    return new Promise(function(resolve) {
                        instance.forceUpdate();
                        resolve(state);
                    });
                }),
                destroy: function destroy() {
                    cleanupModifierEffects();
                    isDestroyed = true;
                }
            };

            if (!areValidElements(reference, popper)) {
                return instance;
            }

            instance.setOptions(options).then(function(state) {
                if (!isDestroyed && options.onFirstUpdate) {
                    options.onFirstUpdate(state);
                }
            }); // Modifiers have the ability to execute arbitrary code before the first
            // update cycle runs. They will be executed in the same order as the update
            // cycle. This is useful when a modifier adds some persistent data that
            // other modifiers need to use, but the modifier is run after the dependent
            // one.

            function runModifierEffects() {
                state.orderedModifiers.forEach(function(_ref) {
                    var name = _ref.name,
                        _ref$options = _ref.options,
                        options = _ref$options === void 0 ? {} : _ref$options,
                        effect = _ref.effect;

                    if (typeof effect === 'function') {
                        var cleanupFn = effect({
                            state: state,
                            name: name,
                            instance: instance,
                            options: options
                        });

                        var noopFn = function noopFn() {};

                        effectCleanupFns.push(cleanupFn || noopFn);
                    }
                });
            }

            function cleanupModifierEffects() {
                effectCleanupFns.forEach(function(fn) {
                    return fn();
                });
                effectCleanupFns = [];
            }

            return instance;
        };
    }

    var passive = {
        passive: true
    };

    function effect$2(_ref) {
        var state = _ref.state,
            instance = _ref.instance,
            options = _ref.options;
        var _options$scroll = options.scroll,
            scroll = _options$scroll === void 0 ? true : _options$scroll,
            _options$resize = options.resize,
            resize = _options$resize === void 0 ? true : _options$resize;
        var window = getWindow(state.elements.popper);
        var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper);

        if (scroll) {
            scrollParents.forEach(function(scrollParent) {
                scrollParent.addEventListener('scroll', instance.update, passive);
            });
        }

        if (resize) {
            window.addEventListener('resize', instance.update, passive);
        }

        return function() {
            if (scroll) {
                scrollParents.forEach(function(scrollParent) {
                    scrollParent.removeEventListener('scroll', instance.update, passive);
                });
            }

            if (resize) {
                window.removeEventListener('resize', instance.update, passive);
            }
        };
    } // eslint-disable-next-line import/no-unused-modules


    var eventListeners = {
        name: 'eventListeners',
        enabled: true,
        phase: 'write',
        fn: function fn() {},
        effect: effect$2,
        data: {}
    };

    function popperOffsets(_ref) {
        var state = _ref.state,
            name = _ref.name;
        // Offsets are the actual position the popper needs to have to be
        // properly positioned near its reference element
        // This is the most basic placement, and will be adjusted by
        // the modifiers in the next step
        state.modifiersData[name] = computeOffsets({
            reference: state.rects.reference,
            element: state.rects.popper,
            strategy: 'absolute',
            placement: state.placement
        });
    } // eslint-disable-next-line import/no-unused-modules


    var popperOffsets$1 = {
        name: 'popperOffsets',
        enabled: true,
        phase: 'read',
        fn: popperOffsets,
        data: {}
    };

    var unsetSides = {
        top: 'auto',
        right: 'auto',
        bottom: 'auto',
        left: 'auto'
    }; // Round the offsets to the nearest suitable subpixel based on the DPR.
    // Zooming can change the DPR, but it seems to report a value that will
    // cleanly divide the values into the appropriate subpixels.

    function roundOffsetsByDPR(_ref, win) {
        var x = _ref.x,
            y = _ref.y;
        var dpr = win.devicePixelRatio || 1;
        return {
            x: round(x * dpr) / dpr || 0,
            y: round(y * dpr) / dpr || 0
        };
    }

    function mapToStyles(_ref2) {
        var _Object$assign2;

        var popper = _ref2.popper,
            popperRect = _ref2.popperRect,
            placement = _ref2.placement,
            variation = _ref2.variation,
            offsets = _ref2.offsets,
            position = _ref2.position,
            gpuAcceleration = _ref2.gpuAcceleration,
            adaptive = _ref2.adaptive,
            roundOffsets = _ref2.roundOffsets,
            isFixed = _ref2.isFixed;
        var _offsets$x = offsets.x,
            x = _offsets$x === void 0 ? 0 : _offsets$x,
            _offsets$y = offsets.y,
            y = _offsets$y === void 0 ? 0 : _offsets$y;

        var _ref3 = typeof roundOffsets === 'function' ? roundOffsets({
            x: x,
            y: y
        }) : {
            x: x,
            y: y
        };

        x = _ref3.x;
        y = _ref3.y;
        var hasX = offsets.hasOwnProperty('x');
        var hasY = offsets.hasOwnProperty('y');
        var sideX = left;
        var sideY = top;
        var win = window;

        if (adaptive) {
            var offsetParent = getOffsetParent(popper);
            var heightProp = 'clientHeight';
            var widthProp = 'clientWidth';

            if (offsetParent === getWindow(popper)) {
                offsetParent = getDocumentElement(popper);

                if (getComputedStyle(offsetParent).position !== 'static' && position === 'absolute') {
                    heightProp = 'scrollHeight';
                    widthProp = 'scrollWidth';
                }
            } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it


            offsetParent = offsetParent;

            if (placement === top || (placement === left || placement === right) && variation === end) {
                sideY = bottom;
                var offsetY = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.height : // $FlowFixMe[prop-missing]
                    offsetParent[heightProp];
                y -= offsetY - popperRect.height;
                y *= gpuAcceleration ? 1 : -1;
            }

            if (placement === left || (placement === top || placement === bottom) && variation === end) {
                sideX = right;
                var offsetX = isFixed && offsetParent === win && win.visualViewport ? win.visualViewport.width : // $FlowFixMe[prop-missing]
                    offsetParent[widthProp];
                x -= offsetX - popperRect.width;
                x *= gpuAcceleration ? 1 : -1;
            }
        }

        var commonStyles = Object.assign({
            position: position
        }, adaptive && unsetSides);

        var _ref4 = roundOffsets === true ? roundOffsetsByDPR({
            x: x,
            y: y
        }, getWindow(popper)) : {
            x: x,
            y: y
        };

        x = _ref4.x;
        y = _ref4.y;

        if (gpuAcceleration) {
            var _Object$assign;

            return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) <= 1 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign));
        }

        return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2));
    }

    function computeStyles(_ref5) {
        var state = _ref5.state,
            options = _ref5.options;
        var _options$gpuAccelerat = options.gpuAcceleration,
            gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat,
            _options$adaptive = options.adaptive,
            adaptive = _options$adaptive === void 0 ? true : _options$adaptive,
            _options$roundOffsets = options.roundOffsets,
            roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets;
        var commonStyles = {
            placement: getBasePlacement(state.placement),
            variation: getVariation(state.placement),
            popper: state.elements.popper,
            popperRect: state.rects.popper,
            gpuAcceleration: gpuAcceleration,
            isFixed: state.options.strategy === 'fixed'
        };

        if (state.modifiersData.popperOffsets != null) {
            state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, {
                offsets: state.modifiersData.popperOffsets,
                position: state.options.strategy,
                adaptive: adaptive,
                roundOffsets: roundOffsets
            })));
        }

        if (state.modifiersData.arrow != null) {
            state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, {
                offsets: state.modifiersData.arrow,
                position: 'absolute',
                adaptive: false,
                roundOffsets: roundOffsets
            })));
        }

        state.attributes.popper = Object.assign({}, state.attributes.popper, {
            'data-popper-placement': state.placement
        });
    } // eslint-disable-next-line import/no-unused-modules


    var computeStyles$1 = {
        name: 'computeStyles',
        enabled: true,
        phase: 'beforeWrite',
        fn: computeStyles,
        data: {}
    };

    // and applies them to the HTMLElements such as popper and arrow

    function applyStyles(_ref) {
        var state = _ref.state;
        Object.keys(state.elements).forEach(function(name) {
            var style = state.styles[name] || {};
            var attributes = state.attributes[name] || {};
            var element = state.elements[name]; // arrow is optional + virtual elements

            if (!isHTMLElement(element) || !getNodeName(element)) {
                return;
            } // Flow doesn't support to extend this property, but it's the most
            // effective way to apply styles to an HTMLElement
            // $FlowFixMe[cannot-write]


            Object.assign(element.style, style);
            Object.keys(attributes).forEach(function(name) {
                var value = attributes[name];

                if (value === false) {
                    element.removeAttribute(name);
                } else {
                    element.setAttribute(name, value === true ? '' : value);
                }
            });
        });
    }

    function effect$1(_ref2) {
        var state = _ref2.state;
        var initialStyles = {
            popper: {
                position: state.options.strategy,
                left: '0',
                top: '0',
                margin: '0'
            },
            arrow: {
                position: 'absolute'
            },
            reference: {}
        };
        Object.assign(state.elements.popper.style, initialStyles.popper);
        state.styles = initialStyles;

        if (state.elements.arrow) {
            Object.assign(state.elements.arrow.style, initialStyles.arrow);
        }

        return function() {
            Object.keys(state.elements).forEach(function(name) {
                var element = state.elements[name];
                var attributes = state.attributes[name] || {};
                var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them

                var style = styleProperties.reduce(function(style, property) {
                    style[property] = '';
                    return style;
                }, {}); // arrow is optional + virtual elements

                if (!isHTMLElement(element) || !getNodeName(element)) {
                    return;
                }

                Object.assign(element.style, style);
                Object.keys(attributes).forEach(function(attribute) {
                    element.removeAttribute(attribute);
                });
            });
        };
    } // eslint-disable-next-line import/no-unused-modules


    var applyStyles$1 = {
        name: 'applyStyles',
        enabled: true,
        phase: 'write',
        fn: applyStyles,
        effect: effect$1,
        requires: ['computeStyles']
    };

    function distanceAndSkiddingToXY(placement, rects, offset) {
        var basePlacement = getBasePlacement(placement);
        var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1;

        var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, {
                placement: placement
            })) : offset,
            skidding = _ref[0],
            distance = _ref[1];

        skidding = skidding || 0;
        distance = (distance || 0) * invertDistance;
        return [left, right].indexOf(basePlacement) >= 0 ? {
            x: distance,
            y: skidding
        } : {
            x: skidding,
            y: distance
        };
    }

    function offset(_ref2) {
        var state = _ref2.state,
            options = _ref2.options,
            name = _ref2.name;
        var _options$offset = options.offset,
            offset = _options$offset === void 0 ? [0, 0] : _options$offset;
        var data = placements.reduce(function(acc, placement) {
            acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset);
            return acc;
        }, {});
        var _data$state$placement = data[state.placement],
            x = _data$state$placement.x,
            y = _data$state$placement.y;

        if (state.modifiersData.popperOffsets != null) {
            state.modifiersData.popperOffsets.x += x;
            state.modifiersData.popperOffsets.y += y;
        }

        state.modifiersData[name] = data;
    } // eslint-disable-next-line import/no-unused-modules


    var offset$1 = {
        name: 'offset',
        enabled: true,
        phase: 'main',
        requires: ['popperOffsets'],
        fn: offset
    };

    var hash$1 = {
        left: 'right',
        right: 'left',
        bottom: 'top',
        top: 'bottom'
    };

    function getOppositePlacement(placement) {
        return placement.replace(/left|right|bottom|top/g, function(matched) {
            return hash$1[matched];
        });
    }

    var hash = {
        start: 'end',
        end: 'start'
    };

    function getOppositeVariationPlacement(placement) {
        return placement.replace(/start|end/g, function(matched) {
            return hash[matched];
        });
    }

    function computeAutoPlacement(state, options) {
        if (options === void 0) {
            options = {};
        }

        var _options = options,
            placement = _options.placement,
            boundary = _options.boundary,
            rootBoundary = _options.rootBoundary,
            padding = _options.padding,
            flipVariations = _options.flipVariations,
            _options$allowedAutoP = _options.allowedAutoPlacements,
            allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP;
        var variation = getVariation(placement);
        var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function(placement) {
            return getVariation(placement) === variation;
        }) : basePlacements;
        var allowedPlacements = placements$1.filter(function(placement) {
            return allowedAutoPlacements.indexOf(placement) >= 0;
        });

        if (allowedPlacements.length === 0) {
            allowedPlacements = placements$1;
        } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions...


        var overflows = allowedPlacements.reduce(function(acc, placement) {
            acc[placement] = detectOverflow(state, {
                placement: placement,
                boundary: boundary,
                rootBoundary: rootBoundary,
                padding: padding
            })[getBasePlacement(placement)];
            return acc;
        }, {});
        return Object.keys(overflows).sort(function(a, b) {
            return overflows[a] - overflows[b];
        });
    }

    function getExpandedFallbackPlacements(placement) {
        if (getBasePlacement(placement) === auto) {
            return [];
        }

        var oppositePlacement = getOppositePlacement(placement);
        return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)];
    }

    function flip(_ref) {
        var state = _ref.state,
            options = _ref.options,
            name = _ref.name;

        if (state.modifiersData[name]._skip) {
            return;
        }

        var _options$mainAxis = options.mainAxis,
            checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
            _options$altAxis = options.altAxis,
            checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis,
            specifiedFallbackPlacements = options.fallbackPlacements,
            padding = options.padding,
            boundary = options.boundary,
            rootBoundary = options.rootBoundary,
            altBoundary = options.altBoundary,
            _options$flipVariatio = options.flipVariations,
            flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio,
            allowedAutoPlacements = options.allowedAutoPlacements;
        var preferredPlacement = state.options.placement;
        var basePlacement = getBasePlacement(preferredPlacement);
        var isBasePlacement = basePlacement === preferredPlacement;
        var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement));
        var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function(acc, placement) {
            return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, {
                placement: placement,
                boundary: boundary,
                rootBoundary: rootBoundary,
                padding: padding,
                flipVariations: flipVariations,
                allowedAutoPlacements: allowedAutoPlacements
            }) : placement);
        }, []);
        var referenceRect = state.rects.reference;
        var popperRect = state.rects.popper;
        var checksMap = new Map();
        var makeFallbackChecks = true;
        var firstFittingPlacement = placements[0];

        for (var i = 0; i < placements.length; i++) {
            var placement = placements[i];

            var _basePlacement = getBasePlacement(placement);

            var isStartVariation = getVariation(placement) === start;
            var isVertical = [top, bottom].indexOf(_basePlacement) >= 0;
            var len = isVertical ? 'width' : 'height';
            var overflow = detectOverflow(state, {
                placement: placement,
                boundary: boundary,
                rootBoundary: rootBoundary,
                altBoundary: altBoundary,
                padding: padding
            });
            var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top;

            if (referenceRect[len] > popperRect[len]) {
                mainVariationSide = getOppositePlacement(mainVariationSide);
            }

            var altVariationSide = getOppositePlacement(mainVariationSide);
            var checks = [];

            if (checkMainAxis) {
                checks.push(overflow[_basePlacement] <= 0);
            }

            if (checkAltAxis) {
                checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0);
            }

            if (checks.every(function(check) {
                    return check;
                })) {
                firstFittingPlacement = placement;
                makeFallbackChecks = false;
                break;
            }

            checksMap.set(placement, checks);
        }

        if (makeFallbackChecks) {
            // `2` may be desired in some cases – research later
            var numberOfChecks = flipVariations ? 3 : 1;

            var _loop = function _loop(_i) {
                var fittingPlacement = placements.find(function(placement) {
                    var checks = checksMap.get(placement);

                    if (checks) {
                        return checks.slice(0, _i).every(function(check) {
                            return check;
                        });
                    }
                });

                if (fittingPlacement) {
                    firstFittingPlacement = fittingPlacement;
                    return "break";
                }
            };

            for (var _i = numberOfChecks; _i > 0; _i--) {
                var _ret = _loop(_i);

                if (_ret === "break") break;
            }
        }

        if (state.placement !== firstFittingPlacement) {
            state.modifiersData[name]._skip = true;
            state.placement = firstFittingPlacement;
            state.reset = true;
        }
    } // eslint-disable-next-line import/no-unused-modules


    var flip$1 = {
        name: 'flip',
        enabled: true,
        phase: 'main',
        fn: flip,
        requiresIfExists: ['offset'],
        data: {
            _skip: false
        }
    };

    function getAltAxis(axis) {
        return axis === 'x' ? 'y' : 'x';
    }

    function within(min$1, value, max$1) {
        return max(min$1, min(value, max$1));
    }

    function withinMaxClamp(min, value, max) {
        var v = within(min, value, max);
        return v > max ? max : v;
    }

    function preventOverflow(_ref) {
        var state = _ref.state,
            options = _ref.options,
            name = _ref.name;
        var _options$mainAxis = options.mainAxis,
            checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis,
            _options$altAxis = options.altAxis,
            checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis,
            boundary = options.boundary,
            rootBoundary = options.rootBoundary,
            altBoundary = options.altBoundary,
            padding = options.padding,
            _options$tether = options.tether,
            tether = _options$tether === void 0 ? true : _options$tether,
            _options$tetherOffset = options.tetherOffset,
            tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset;
        var overflow = detectOverflow(state, {
            boundary: boundary,
            rootBoundary: rootBoundary,
            padding: padding,
            altBoundary: altBoundary
        });
        var basePlacement = getBasePlacement(state.placement);
        var variation = getVariation(state.placement);
        var isBasePlacement = !variation;
        var mainAxis = getMainAxisFromPlacement(basePlacement);
        var altAxis = getAltAxis(mainAxis);
        var popperOffsets = state.modifiersData.popperOffsets;
        var referenceRect = state.rects.reference;
        var popperRect = state.rects.popper;
        var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, {
            placement: state.placement
        })) : tetherOffset;
        var normalizedTetherOffsetValue = typeof tetherOffsetValue === 'number' ? {
            mainAxis: tetherOffsetValue,
            altAxis: tetherOffsetValue
        } : Object.assign({
            mainAxis: 0,
            altAxis: 0
        }, tetherOffsetValue);
        var offsetModifierState = state.modifiersData.offset ? state.modifiersData.offset[state.placement] : null;
        var data = {
            x: 0,
            y: 0
        };

        if (!popperOffsets) {
            return;
        }

        if (checkMainAxis) {
            var _offsetModifierState$;

            var mainSide = mainAxis === 'y' ? top : left;
            var altSide = mainAxis === 'y' ? bottom : right;
            var len = mainAxis === 'y' ? 'height' : 'width';
            var offset = popperOffsets[mainAxis];
            var min$1 = offset + overflow[mainSide];
            var max$1 = offset - overflow[altSide];
            var additive = tether ? -popperRect[len] / 2 : 0;
            var minLen = variation === start ? referenceRect[len] : popperRect[len];
            var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go
            // outside the reference bounds

            var arrowElement = state.elements.arrow;
            var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : {
                width: 0,
                height: 0
            };
            var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject();
            var arrowPaddingMin = arrowPaddingObject[mainSide];
            var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want
            // to include its full size in the calculation. If the reference is small
            // and near the edge of a boundary, the popper can overflow even if the
            // reference is not overflowing as well (e.g. virtual elements with no
            // width or height)

            var arrowLen = within(0, referenceRect[len], arrowRect[len]);
            var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis : minLen - arrowLen - arrowPaddingMin - normalizedTetherOffsetValue.mainAxis;
            var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis : maxLen + arrowLen + arrowPaddingMax + normalizedTetherOffsetValue.mainAxis;
            var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow);
            var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0;
            var offsetModifierValue = (_offsetModifierState$ = offsetModifierState == null ? void 0 : offsetModifierState[mainAxis]) != null ? _offsetModifierState$ : 0;
            var tetherMin = offset + minOffset - offsetModifierValue - clientOffset;
            var tetherMax = offset + maxOffset - offsetModifierValue;
            var preventedOffset = within(tether ? min(min$1, tetherMin) : min$1, offset, tether ? max(max$1, tetherMax) : max$1);
            popperOffsets[mainAxis] = preventedOffset;
            data[mainAxis] = preventedOffset - offset;
        }

        if (checkAltAxis) {
            var _offsetModifierState$2;

            var _mainSide = mainAxis === 'x' ? top : left;

            var _altSide = mainAxis === 'x' ? bottom : right;

            var _offset = popperOffsets[altAxis];

            var _len = altAxis === 'y' ? 'height' : 'width';

            var _min = _offset + overflow[_mainSide];

            var _max = _offset - overflow[_altSide];

            var isOriginSide = [top, left].indexOf(basePlacement) !== -1;

            var _offsetModifierValue = (_offsetModifierState$2 = offsetModifierState == null ? void 0 : offsetModifierState[altAxis]) != null ? _offsetModifierState$2 : 0;

            var _tetherMin = isOriginSide ? _min : _offset - referenceRect[_len] - popperRect[_len] - _offsetModifierValue + normalizedTetherOffsetValue.altAxis;

            var _tetherMax = isOriginSide ? _offset + referenceRect[_len] + popperRect[_len] - _offsetModifierValue - normalizedTetherOffsetValue.altAxis : _max;

            var _preventedOffset = tether && isOriginSide ? withinMaxClamp(_tetherMin, _offset, _tetherMax) : within(tether ? _tetherMin : _min, _offset, tether ? _tetherMax : _max);

            popperOffsets[altAxis] = _preventedOffset;
            data[altAxis] = _preventedOffset - _offset;
        }

        state.modifiersData[name] = data;
    } // eslint-disable-next-line import/no-unused-modules


    var preventOverflow$1 = {
        name: 'preventOverflow',
        enabled: true,
        phase: 'main',
        fn: preventOverflow,
        requiresIfExists: ['offset']
    };

    var toPaddingObject = function toPaddingObject(padding, state) {
        padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, {
            placement: state.placement
        })) : padding;
        return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements));
    };

    function arrow(_ref) {
        var _state$modifiersData$;

        var state = _ref.state,
            name = _ref.name,
            options = _ref.options;
        var arrowElement = state.elements.arrow;
        var popperOffsets = state.modifiersData.popperOffsets;
        var basePlacement = getBasePlacement(state.placement);
        var axis = getMainAxisFromPlacement(basePlacement);
        var isVertical = [left, right].indexOf(basePlacement) >= 0;
        var len = isVertical ? 'height' : 'width';

        if (!arrowElement || !popperOffsets) {
            return;
        }

        var paddingObject = toPaddingObject(options.padding, state);
        var arrowRect = getLayoutRect(arrowElement);
        var minProp = axis === 'y' ? top : left;
        var maxProp = axis === 'y' ? bottom : right;
        var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len];
        var startDiff = popperOffsets[axis] - state.rects.reference[axis];
        var arrowOffsetParent = getOffsetParent(arrowElement);
        var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0;
        var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is
        // outside of the popper bounds

        var min = paddingObject[minProp];
        var max = clientSize - arrowRect[len] - paddingObject[maxProp];
        var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference;
        var offset = within(min, center, max); // Prevents breaking syntax highlighting...

        var axisProp = axis;
        state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$);
    }

    function effect(_ref2) {
        var state = _ref2.state,
            options = _ref2.options;
        var _options$element = options.element,
            arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element;

        if (arrowElement == null) {
            return;
        } // CSS selector


        if (typeof arrowElement === 'string') {
            arrowElement = state.elements.popper.querySelector(arrowElement);

            if (!arrowElement) {
                return;
            }
        }

        if (!contains(state.elements.popper, arrowElement)) {
            return;
        }

        state.elements.arrow = arrowElement;
    } // eslint-disable-next-line import/no-unused-modules


    var arrow$1 = {
        name: 'arrow',
        enabled: true,
        phase: 'main',
        fn: arrow,
        effect: effect,
        requires: ['popperOffsets'],
        requiresIfExists: ['preventOverflow']
    };

    function getSideOffsets(overflow, rect, preventedOffsets) {
        if (preventedOffsets === void 0) {
            preventedOffsets = {
                x: 0,
                y: 0
            };
        }

        return {
            top: overflow.top - rect.height - preventedOffsets.y,
            right: overflow.right - rect.width + preventedOffsets.x,
            bottom: overflow.bottom - rect.height + preventedOffsets.y,
            left: overflow.left - rect.width - preventedOffsets.x
        };
    }

    function isAnySideFullyClipped(overflow) {
        return [top, right, bottom, left].some(function(side) {
            return overflow[side] >= 0;
        });
    }

    function hide(_ref) {
        var state = _ref.state,
            name = _ref.name;
        var referenceRect = state.rects.reference;
        var popperRect = state.rects.popper;
        var preventedOffsets = state.modifiersData.preventOverflow;
        var referenceOverflow = detectOverflow(state, {
            elementContext: 'reference'
        });
        var popperAltOverflow = detectOverflow(state, {
            altBoundary: true
        });
        var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect);
        var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets);
        var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets);
        var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets);
        state.modifiersData[name] = {
            referenceClippingOffsets: referenceClippingOffsets,
            popperEscapeOffsets: popperEscapeOffsets,
            isReferenceHidden: isReferenceHidden,
            hasPopperEscaped: hasPopperEscaped
        };
        state.attributes.popper = Object.assign({}, state.attributes.popper, {
            'data-popper-reference-hidden': isReferenceHidden,
            'data-popper-escaped': hasPopperEscaped
        });
    } // eslint-disable-next-line import/no-unused-modules


    var hide$1 = {
        name: 'hide',
        enabled: true,
        phase: 'main',
        requiresIfExists: ['preventOverflow'],
        fn: hide
    };

    var defaultModifiers$1 = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1];
    var createPopper$1 = /*#__PURE__*/ popperGenerator({
        defaultModifiers: defaultModifiers$1
    }); // eslint-disable-next-line import/no-unused-modules

    var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1];
    var createPopper = /*#__PURE__*/ popperGenerator({
        defaultModifiers: defaultModifiers
    }); // eslint-disable-next-line import/no-unused-modules

    exports.applyStyles = applyStyles$1;
    exports.arrow = arrow$1;
    exports.computeStyles = computeStyles$1;
    exports.createPopper = createPopper;
    exports.createPopperLite = createPopper$1;
    exports.defaultModifiers = defaultModifiers;
    exports.detectOverflow = detectOverflow;
    exports.eventListeners = eventListeners;
    exports.flip = flip$1;
    exports.hide = hide$1;
    exports.offset = offset$1;
    exports.popperGenerator = popperGenerator;
    exports.popperOffsets = popperOffsets$1;
    exports.preventOverflow = preventOverflow$1;

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

})));
//# sourceMappingURL=popper.js.map
/*!
 * Bootstrap v5.3.8 (https://getbootstrap.com/)
 * Copyright 2011-2025 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
 */
(function(global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@popperjs/core')) :
        typeof define === 'function' && define.amd ? define(['@popperjs/core'], factory) :
        (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.bootstrap = factory(global.Popper));
})(this, (function(Popper) {
    'use strict';

    function _interopNamespaceDefault(e) {
        const n = Object.create(null, {
            [Symbol.toStringTag]: {
                value: 'Module'
            }
        });
        if (e) {
            for (const k in e) {
                if (k !== 'default') {
                    const d = Object.getOwnPropertyDescriptor(e, k);
                    Object.defineProperty(n, k, d.get ? d : {
                        enumerable: true,
                        get: () => e[k]
                    });
                }
            }
        }
        n.default = e;
        return Object.freeze(n);
    }

    const Popper__namespace = /*#__PURE__*/ _interopNamespaceDefault(Popper);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap dom/data.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */

    /**
     * Constants
     */

    const elementMap = new Map();
    const Data = {
        set(element, key, instance) {
            if (!elementMap.has(element)) {
                elementMap.set(element, new Map());
            }
            const instanceMap = elementMap.get(element);

            // make it clear we only want one instance per element
            // can be removed later when multiple key/instances are fine to be used
            if (!instanceMap.has(key) && instanceMap.size !== 0) {
                // eslint-disable-next-line no-console
                console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(instanceMap.keys())[0]}.`);
                return;
            }
            instanceMap.set(key, instance);
        },
        get(element, key) {
            if (elementMap.has(element)) {
                return elementMap.get(element).get(key) || null;
            }
            return null;
        },
        remove(element, key) {
            if (!elementMap.has(element)) {
                return;
            }
            const instanceMap = elementMap.get(element);
            instanceMap.delete(key);

            // free up element references if there are no instances left for an element
            if (instanceMap.size === 0) {
                elementMap.delete(element);
            }
        }
    };

    /**
     * --------------------------------------------------------------------------
     * Bootstrap util/index.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */

    const MAX_UID = 1000000;
    const MILLISECONDS_MULTIPLIER = 1000;
    const TRANSITION_END = 'transitionend';

    /**
     * Properly escape IDs selectors to handle weird IDs
     * @param {string} selector
     * @returns {string}
     */
    const parseSelector = selector => {
        if (selector && window.CSS && window.CSS.escape) {
            // document.querySelector needs escaping to handle IDs (html5+) containing for instance /
            selector = selector.replace(/#([^\s"#']+)/g, (match, id) => `#${CSS.escape(id)}`);
        }
        return selector;
    };

    // Shout-out Angus Croll (https://goo.gl/pxwQGp)
    const toType = object => {
        if (object === null || object === undefined) {
            return `${object}`;
        }
        return Object.prototype.toString.call(object).match(/\s([a-z]+)/i)[1].toLowerCase();
    };

    /**
     * Public Util API
     */

    const getUID = prefix => {
        do {
            prefix += Math.floor(Math.random() * MAX_UID);
        } while (document.getElementById(prefix));
        return prefix;
    };
    const getTransitionDurationFromElement = element => {
        if (!element) {
            return 0;
        }

        // Get transition-duration of the element
        let {
            transitionDuration,
            transitionDelay
        } = window.getComputedStyle(element);
        const floatTransitionDuration = Number.parseFloat(transitionDuration);
        const floatTransitionDelay = Number.parseFloat(transitionDelay);

        // Return 0 if element or transition duration is not found
        if (!floatTransitionDuration && !floatTransitionDelay) {
            return 0;
        }

        // If multiple durations are defined, take the first
        transitionDuration = transitionDuration.split(',')[0];
        transitionDelay = transitionDelay.split(',')[0];
        return (Number.parseFloat(transitionDuration) + Number.parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER;
    };
    const triggerTransitionEnd = element => {
        element.dispatchEvent(new Event(TRANSITION_END));
    };
    const isElement = object => {
        if (!object || typeof object !== 'object') {
            return false;
        }
        if (typeof object.jquery !== 'undefined') {
            object = object[0];
        }
        return typeof object.nodeType !== 'undefined';
    };
    const getElement = object => {
        // it's a jQuery object or a node element
        if (isElement(object)) {
            return object.jquery ? object[0] : object;
        }
        if (typeof object === 'string' && object.length > 0) {
            return document.querySelector(parseSelector(object));
        }
        return null;
    };
    const isVisible = element => {
        if (!isElement(element) || element.getClientRects().length === 0) {
            return false;
        }
        const elementIsVisible = getComputedStyle(element).getPropertyValue('visibility') === 'visible';
        // Handle `details` element as its content may falsie appear visible when it is closed
        const closedDetails = element.closest('details:not([open])');
        if (!closedDetails) {
            return elementIsVisible;
        }
        if (closedDetails !== element) {
            const summary = element.closest('summary');
            if (summary && summary.parentNode !== closedDetails) {
                return false;
            }
            if (summary === null) {
                return false;
            }
        }
        return elementIsVisible;
    };
    const isDisabled = element => {
        if (!element || element.nodeType !== Node.ELEMENT_NODE) {
            return true;
        }
        if (element.classList.contains('disabled')) {
            return true;
        }
        if (typeof element.disabled !== 'undefined') {
            return element.disabled;
        }
        return element.hasAttribute('disabled') && element.getAttribute('disabled') !== 'false';
    };
    const findShadowRoot = element => {
        if (!document.documentElement.attachShadow) {
            return null;
        }

        // Can find the shadow root otherwise it'll return the document
        if (typeof element.getRootNode === 'function') {
            const root = element.getRootNode();
            return root instanceof ShadowRoot ? root : null;
        }
        if (element instanceof ShadowRoot) {
            return element;
        }

        // when we don't find a shadow root
        if (!element.parentNode) {
            return null;
        }
        return findShadowRoot(element.parentNode);
    };
    const noop = () => {};

    /**
     * Trick to restart an element's animation
     *
     * @param {HTMLElement} element
     * @return void
     *
     * @see https://www.harrytheo.com/blog/2021/02/restart-a-css-animation-with-javascript/#restarting-a-css-animation
     */
    const reflow = element => {
        element.offsetHeight; // eslint-disable-line no-unused-expressions
    };
    const getjQuery = () => {
        if (window.jQuery && !document.body.hasAttribute('data-bs-no-jquery')) {
            return window.jQuery;
        }
        return null;
    };
    const DOMContentLoadedCallbacks = [];
    const onDOMContentLoaded = callback => {
        if (document.readyState === 'loading') {
            // add listener on the first call when the document is in loading state
            if (!DOMContentLoadedCallbacks.length) {
                document.addEventListener('DOMContentLoaded', () => {
                    for (const callback of DOMContentLoadedCallbacks) {
                        callback();
                    }
                });
            }
            DOMContentLoadedCallbacks.push(callback);
        } else {
            callback();
        }
    };
    const isRTL = () => document.documentElement.dir === 'rtl';
    const defineJQueryPlugin = plugin => {
        onDOMContentLoaded(() => {
            const $ = getjQuery();
            /* istanbul ignore if */
            if ($) {
                const name = plugin.NAME;
                const JQUERY_NO_CONFLICT = $.fn[name];
                $.fn[name] = plugin.jQueryInterface;
                $.fn[name].Constructor = plugin;
                $.fn[name].noConflict = () => {
                    $.fn[name] = JQUERY_NO_CONFLICT;
                    return plugin.jQueryInterface;
                };
            }
        });
    };
    const execute = (possibleCallback, args = [], defaultValue = possibleCallback) => {
        return typeof possibleCallback === 'function' ? possibleCallback.call(...args) : defaultValue;
    };
    const executeAfterTransition = (callback, transitionElement, waitForTransition = true) => {
        if (!waitForTransition) {
            execute(callback);
            return;
        }
        const durationPadding = 5;
        const emulatedDuration = getTransitionDurationFromElement(transitionElement) + durationPadding;
        let called = false;
        const handler = ({
            target
        }) => {
            if (target !== transitionElement) {
                return;
            }
            called = true;
            transitionElement.removeEventListener(TRANSITION_END, handler);
            execute(callback);
        };
        transitionElement.addEventListener(TRANSITION_END, handler);
        setTimeout(() => {
            if (!called) {
                triggerTransitionEnd(transitionElement);
            }
        }, emulatedDuration);
    };

    /**
     * Return the previous/next element of a list.
     *
     * @param {array} list    The list of elements
     * @param activeElement   The active element
     * @param shouldGetNext   Choose to get next or previous element
     * @param isCycleAllowed
     * @return {Element|elem} The proper element
     */
    const getNextActiveElement = (list, activeElement, shouldGetNext, isCycleAllowed) => {
        const listLength = list.length;
        let index = list.indexOf(activeElement);

        // if the element does not exist in the list return an element
        // depending on the direction and if cycle is allowed
        if (index === -1) {
            return !shouldGetNext && isCycleAllowed ? list[listLength - 1] : list[0];
        }
        index += shouldGetNext ? 1 : -1;
        if (isCycleAllowed) {
            index = (index + listLength) % listLength;
        }
        return list[Math.max(0, Math.min(index, listLength - 1))];
    };

    /**
     * --------------------------------------------------------------------------
     * Bootstrap dom/event-handler.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const namespaceRegex = /[^.]*(?=\..*)\.|.*/;
    const stripNameRegex = /\..*/;
    const stripUidRegex = /::\d+$/;
    const eventRegistry = {}; // Events storage
    let uidEvent = 1;
    const customEvents = {
        mouseenter: 'mouseover',
        mouseleave: 'mouseout'
    };
    const nativeEvents = new Set(['click', 'dblclick', 'mouseup', 'mousedown', 'contextmenu', 'mousewheel', 'DOMMouseScroll', 'mouseover', 'mouseout', 'mousemove', 'selectstart', 'selectend', 'keydown', 'keypress', 'keyup', 'orientationchange', 'touchstart', 'touchmove', 'touchend', 'touchcancel', 'pointerdown', 'pointermove', 'pointerup', 'pointerleave', 'pointercancel', 'gesturestart', 'gesturechange', 'gestureend', 'focus', 'blur', 'change', 'reset', 'select', 'submit', 'focusin', 'focusout', 'load', 'unload', 'beforeunload', 'resize', 'move', 'DOMContentLoaded', 'readystatechange', 'error', 'abort', 'scroll']);

    /**
     * Private methods
     */

    function makeEventUid(element, uid) {
        return uid && `${uid}::${uidEvent++}` || element.uidEvent || uidEvent++;
    }

    function getElementEvents(element) {
        const uid = makeEventUid(element);
        element.uidEvent = uid;
        eventRegistry[uid] = eventRegistry[uid] || {};
        return eventRegistry[uid];
    }

    function bootstrapHandler(element, fn) {
        return function handler(event) {
            hydrateObj(event, {
                delegateTarget: element
            });
            if (handler.oneOff) {
                EventHandler.off(element, event.type, fn);
            }
            return fn.apply(element, [event]);
        };
    }

    function bootstrapDelegationHandler(element, selector, fn) {
        return function handler(event) {
            const domElements = element.querySelectorAll(selector);
            for (let {
                    target
                } = event; target && target !== this; target = target.parentNode) {
                for (const domElement of domElements) {
                    if (domElement !== target) {
                        continue;
                    }
                    hydrateObj(event, {
                        delegateTarget: target
                    });
                    if (handler.oneOff) {
                        EventHandler.off(element, event.type, selector, fn);
                    }
                    return fn.apply(target, [event]);
                }
            }
        };
    }

    function findHandler(events, callable, delegationSelector = null) {
        return Object.values(events).find(event => event.callable === callable && event.delegationSelector === delegationSelector);
    }

    function normalizeParameters(originalTypeEvent, handler, delegationFunction) {
        const isDelegated = typeof handler === 'string';
        // TODO: tooltip passes `false` instead of selector, so we need to check
        const callable = isDelegated ? delegationFunction : handler || delegationFunction;
        let typeEvent = getTypeEvent(originalTypeEvent);
        if (!nativeEvents.has(typeEvent)) {
            typeEvent = originalTypeEvent;
        }
        return [isDelegated, callable, typeEvent];
    }

    function addHandler(element, originalTypeEvent, handler, delegationFunction, oneOff) {
        if (typeof originalTypeEvent !== 'string' || !element) {
            return;
        }
        let [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction);

        // in case of mouseenter or mouseleave wrap the handler within a function that checks for its DOM position
        // this prevents the handler from being dispatched the same way as mouseover or mouseout does
        if (originalTypeEvent in customEvents) {
            const wrapFunction = fn => {
                return function(event) {
                    if (!event.relatedTarget || event.relatedTarget !== event.delegateTarget && !event.delegateTarget.contains(event.relatedTarget)) {
                        return fn.call(this, event);
                    }
                };
            };
            callable = wrapFunction(callable);
        }
        const events = getElementEvents(element);
        const handlers = events[typeEvent] || (events[typeEvent] = {});
        const previousFunction = findHandler(handlers, callable, isDelegated ? handler : null);
        if (previousFunction) {
            previousFunction.oneOff = previousFunction.oneOff && oneOff;
            return;
        }
        const uid = makeEventUid(callable, originalTypeEvent.replace(namespaceRegex, ''));
        const fn = isDelegated ? bootstrapDelegationHandler(element, handler, callable) : bootstrapHandler(element, callable);
        fn.delegationSelector = isDelegated ? handler : null;
        fn.callable = callable;
        fn.oneOff = oneOff;
        fn.uidEvent = uid;
        handlers[uid] = fn;
        element.addEventListener(typeEvent, fn, isDelegated);
    }

    function removeHandler(element, events, typeEvent, handler, delegationSelector) {
        const fn = findHandler(events[typeEvent], handler, delegationSelector);
        if (!fn) {
            return;
        }
        element.removeEventListener(typeEvent, fn, Boolean(delegationSelector));
        delete events[typeEvent][fn.uidEvent];
    }

    function removeNamespacedHandlers(element, events, typeEvent, namespace) {
        const storeElementEvent = events[typeEvent] || {};
        for (const [handlerKey, event] of Object.entries(storeElementEvent)) {
            if (handlerKey.includes(namespace)) {
                removeHandler(element, events, typeEvent, event.callable, event.delegationSelector);
            }
        }
    }

    function getTypeEvent(event) {
        // allow to get the native events from namespaced events ('click.bs.button' --> 'click')
        event = event.replace(stripNameRegex, '');
        return customEvents[event] || event;
    }
    const EventHandler = {
        on(element, event, handler, delegationFunction) {
            addHandler(element, event, handler, delegationFunction, false);
        },
        one(element, event, handler, delegationFunction) {
            addHandler(element, event, handler, delegationFunction, true);
        },
        off(element, originalTypeEvent, handler, delegationFunction) {
            if (typeof originalTypeEvent !== 'string' || !element) {
                return;
            }
            const [isDelegated, callable, typeEvent] = normalizeParameters(originalTypeEvent, handler, delegationFunction);
            const inNamespace = typeEvent !== originalTypeEvent;
            const events = getElementEvents(element);
            const storeElementEvent = events[typeEvent] || {};
            const isNamespace = originalTypeEvent.startsWith('.');
            if (typeof callable !== 'undefined') {
                // Simplest case: handler is passed, remove that listener ONLY.
                if (!Object.keys(storeElementEvent).length) {
                    return;
                }
                removeHandler(element, events, typeEvent, callable, isDelegated ? handler : null);
                return;
            }
            if (isNamespace) {
                for (const elementEvent of Object.keys(events)) {
                    removeNamespacedHandlers(element, events, elementEvent, originalTypeEvent.slice(1));
                }
            }
            for (const [keyHandlers, event] of Object.entries(storeElementEvent)) {
                const handlerKey = keyHandlers.replace(stripUidRegex, '');
                if (!inNamespace || originalTypeEvent.includes(handlerKey)) {
                    removeHandler(element, events, typeEvent, event.callable, event.delegationSelector);
                }
            }
        },
        trigger(element, event, args) {
            if (typeof event !== 'string' || !element) {
                return null;
            }
            const $ = getjQuery();
            const typeEvent = getTypeEvent(event);
            const inNamespace = event !== typeEvent;
            let jQueryEvent = null;
            let bubbles = true;
            let nativeDispatch = true;
            let defaultPrevented = false;
            if (inNamespace && $) {
                jQueryEvent = $.Event(event, args);
                $(element).trigger(jQueryEvent);
                bubbles = !jQueryEvent.isPropagationStopped();
                nativeDispatch = !jQueryEvent.isImmediatePropagationStopped();
                defaultPrevented = jQueryEvent.isDefaultPrevented();
            }
            const evt = hydrateObj(new Event(event, {
                bubbles,
                cancelable: true
            }), args);
            if (defaultPrevented) {
                evt.preventDefault();
            }
            if (nativeDispatch) {
                element.dispatchEvent(evt);
            }
            if (evt.defaultPrevented && jQueryEvent) {
                jQueryEvent.preventDefault();
            }
            return evt;
        }
    };

    function hydrateObj(obj, meta = {}) {
        for (const [key, value] of Object.entries(meta)) {
            try {
                obj[key] = value;
            } catch (_unused) {
                Object.defineProperty(obj, key, {
                    configurable: true,
                    get() {
                        return value;
                    }
                });
            }
        }
        return obj;
    }

    /**
     * --------------------------------------------------------------------------
     * Bootstrap dom/manipulator.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */

    function normalizeData(value) {
        if (value === 'true') {
            return true;
        }
        if (value === 'false') {
            return false;
        }
        if (value === Number(value).toString()) {
            return Number(value);
        }
        if (value === '' || value === 'null') {
            return null;
        }
        if (typeof value !== 'string') {
            return value;
        }
        try {
            return JSON.parse(decodeURIComponent(value));
        } catch (_unused) {
            return value;
        }
    }

    function normalizeDataKey(key) {
        return key.replace(/[A-Z]/g, chr => `-${chr.toLowerCase()}`);
    }
    const Manipulator = {
        setDataAttribute(element, key, value) {
            element.setAttribute(`data-bs-${normalizeDataKey(key)}`, value);
        },
        removeDataAttribute(element, key) {
            element.removeAttribute(`data-bs-${normalizeDataKey(key)}`);
        },
        getDataAttributes(element) {
            if (!element) {
                return {};
            }
            const attributes = {};
            const bsKeys = Object.keys(element.dataset).filter(key => key.startsWith('bs') && !key.startsWith('bsConfig'));
            for (const key of bsKeys) {
                let pureKey = key.replace(/^bs/, '');
                pureKey = pureKey.charAt(0).toLowerCase() + pureKey.slice(1);
                attributes[pureKey] = normalizeData(element.dataset[key]);
            }
            return attributes;
        },
        getDataAttribute(element, key) {
            return normalizeData(element.getAttribute(`data-bs-${normalizeDataKey(key)}`));
        }
    };

    /**
     * --------------------------------------------------------------------------
     * Bootstrap util/config.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Class definition
     */

    class Config {
        // Getters
        static get Default() {
            return {};
        }
        static get DefaultType() {
            return {};
        }
        static get NAME() {
            throw new Error('You have to implement the static method "NAME", for each component!');
        }
        _getConfig(config) {
            config = this._mergeConfigObj(config);
            config = this._configAfterMerge(config);
            this._typeCheckConfig(config);
            return config;
        }
        _configAfterMerge(config) {
            return config;
        }
        _mergeConfigObj(config, element) {
            const jsonConfig = isElement(element) ? Manipulator.getDataAttribute(element, 'config') : {}; // try to parse

            return {
                ...this.constructor.Default,
                ...(typeof jsonConfig === 'object' ? jsonConfig : {}),
                ...(isElement(element) ? Manipulator.getDataAttributes(element) : {}),
                ...(typeof config === 'object' ? config : {})
            };
        }
        _typeCheckConfig(config, configTypes = this.constructor.DefaultType) {
            for (const [property, expectedTypes] of Object.entries(configTypes)) {
                const value = config[property];
                const valueType = isElement(value) ? 'element' : toType(value);
                if (!new RegExp(expectedTypes).test(valueType)) {
                    throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${property}" provided type "${valueType}" but expected type "${expectedTypes}".`);
                }
            }
        }
    }

    /**
     * --------------------------------------------------------------------------
     * Bootstrap base-component.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const VERSION = '5.3.8';

    /**
     * Class definition
     */

    class BaseComponent extends Config {
        constructor(element, config) {
            super();
            element = getElement(element);
            if (!element) {
                return;
            }
            this._element = element;
            this._config = this._getConfig(config);
            Data.set(this._element, this.constructor.DATA_KEY, this);
        }

        // Public
        dispose() {
            Data.remove(this._element, this.constructor.DATA_KEY);
            EventHandler.off(this._element, this.constructor.EVENT_KEY);
            for (const propertyName of Object.getOwnPropertyNames(this)) {
                this[propertyName] = null;
            }
        }

        // Private
        _queueCallback(callback, element, isAnimated = true) {
            executeAfterTransition(callback, element, isAnimated);
        }
        _getConfig(config) {
            config = this._mergeConfigObj(config, this._element);
            config = this._configAfterMerge(config);
            this._typeCheckConfig(config);
            return config;
        }

        // Static
        static getInstance(element) {
            return Data.get(getElement(element), this.DATA_KEY);
        }
        static getOrCreateInstance(element, config = {}) {
            return this.getInstance(element) || new this(element, typeof config === 'object' ? config : null);
        }
        static get VERSION() {
            return VERSION;
        }
        static get DATA_KEY() {
            return `bs.${this.NAME}`;
        }
        static get EVENT_KEY() {
            return `.${this.DATA_KEY}`;
        }
        static eventName(name) {
            return `${name}${this.EVENT_KEY}`;
        }
    }

    /**
     * --------------------------------------------------------------------------
     * Bootstrap dom/selector-engine.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */

    const getSelector = element => {
        let selector = element.getAttribute('data-bs-target');
        if (!selector || selector === '#') {
            let hrefAttribute = element.getAttribute('href');

            // The only valid content that could double as a selector are IDs or classes,
            // so everything starting with `#` or `.`. If a "real" URL is used as the selector,
            // `document.querySelector` will rightfully complain it is invalid.
            // See https://github.com/twbs/bootstrap/issues/32273
            if (!hrefAttribute || !hrefAttribute.includes('#') && !hrefAttribute.startsWith('.')) {
                return null;
            }

            // Just in case some CMS puts out a full URL with the anchor appended
            if (hrefAttribute.includes('#') && !hrefAttribute.startsWith('#')) {
                hrefAttribute = `#${hrefAttribute.split('#')[1]}`;
            }
            selector = hrefAttribute && hrefAttribute !== '#' ? hrefAttribute.trim() : null;
        }
        return selector ? selector.split(',').map(sel => parseSelector(sel)).join(',') : null;
    };
    const SelectorEngine = {
        find(selector, element = document.documentElement) {
            return [].concat(...Element.prototype.querySelectorAll.call(element, selector));
        },
        findOne(selector, element = document.documentElement) {
            return Element.prototype.querySelector.call(element, selector);
        },
        children(element, selector) {
            return [].concat(...element.children).filter(child => child.matches(selector));
        },
        parents(element, selector) {
            const parents = [];
            let ancestor = element.parentNode.closest(selector);
            while (ancestor) {
                parents.push(ancestor);
                ancestor = ancestor.parentNode.closest(selector);
            }
            return parents;
        },
        prev(element, selector) {
            let previous = element.previousElementSibling;
            while (previous) {
                if (previous.matches(selector)) {
                    return [previous];
                }
                previous = previous.previousElementSibling;
            }
            return [];
        },
        // TODO: this is now unused; remove later along with prev()
        next(element, selector) {
            let next = element.nextElementSibling;
            while (next) {
                if (next.matches(selector)) {
                    return [next];
                }
                next = next.nextElementSibling;
            }
            return [];
        },
        focusableChildren(element) {
            const focusables = ['a', 'button', 'input', 'textarea', 'select', 'details', '[tabindex]', '[contenteditable="true"]'].map(selector => `${selector}:not([tabindex^="-"])`).join(',');
            return this.find(focusables, element).filter(el => !isDisabled(el) && isVisible(el));
        },
        getSelectorFromElement(element) {
            const selector = getSelector(element);
            if (selector) {
                return SelectorEngine.findOne(selector) ? selector : null;
            }
            return null;
        },
        getElementFromSelector(element) {
            const selector = getSelector(element);
            return selector ? SelectorEngine.findOne(selector) : null;
        },
        getMultipleElementsFromSelector(element) {
            const selector = getSelector(element);
            return selector ? SelectorEngine.find(selector) : [];
        }
    };

    /**
     * --------------------------------------------------------------------------
     * Bootstrap util/component-functions.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */

    const enableDismissTrigger = (component, method = 'hide') => {
        const clickEvent = `click.dismiss${component.EVENT_KEY}`;
        const name = component.NAME;
        EventHandler.on(document, clickEvent, `[data-bs-dismiss="${name}"]`, function(event) {
            if (['A', 'AREA'].includes(this.tagName)) {
                event.preventDefault();
            }
            if (isDisabled(this)) {
                return;
            }
            const target = SelectorEngine.getElementFromSelector(this) || this.closest(`.${name}`);
            const instance = component.getOrCreateInstance(target);

            // Method argument is left, for Alert and only, as it doesn't implement the 'hide' method
            instance[method]();
        });
    };

    /**
     * --------------------------------------------------------------------------
     * Bootstrap alert.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$f = 'alert';
    const DATA_KEY$a = 'bs.alert';
    const EVENT_KEY$b = `.${DATA_KEY$a}`;
    const EVENT_CLOSE = `close${EVENT_KEY$b}`;
    const EVENT_CLOSED = `closed${EVENT_KEY$b}`;
    const CLASS_NAME_FADE$5 = 'fade';
    const CLASS_NAME_SHOW$8 = 'show';

    /**
     * Class definition
     */

    class Alert extends BaseComponent {
        // Getters
        static get NAME() {
            return NAME$f;
        }

        // Public
        close() {
            const closeEvent = EventHandler.trigger(this._element, EVENT_CLOSE);
            if (closeEvent.defaultPrevented) {
                return;
            }
            this._element.classList.remove(CLASS_NAME_SHOW$8);
            const isAnimated = this._element.classList.contains(CLASS_NAME_FADE$5);
            this._queueCallback(() => this._destroyElement(), this._element, isAnimated);
        }

        // Private
        _destroyElement() {
            this._element.remove();
            EventHandler.trigger(this._element, EVENT_CLOSED);
            this.dispose();
        }

        // Static
        static jQueryInterface(config) {
            return this.each(function() {
                const data = Alert.getOrCreateInstance(this);
                if (typeof config !== 'string') {
                    return;
                }
                if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
                    throw new TypeError(`No method named "${config}"`);
                }
                data[config](this);
            });
        }
    }

    /**
     * Data API implementation
     */

    enableDismissTrigger(Alert, 'close');

    /**
     * jQuery
     */

    defineJQueryPlugin(Alert);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap button.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$e = 'button';
    const DATA_KEY$9 = 'bs.button';
    const EVENT_KEY$a = `.${DATA_KEY$9}`;
    const DATA_API_KEY$6 = '.data-api';
    const CLASS_NAME_ACTIVE$3 = 'active';
    const SELECTOR_DATA_TOGGLE$5 = '[data-bs-toggle="button"]';
    const EVENT_CLICK_DATA_API$6 = `click${EVENT_KEY$a}${DATA_API_KEY$6}`;

    /**
     * Class definition
     */

    class Button extends BaseComponent {
        // Getters
        static get NAME() {
            return NAME$e;
        }

        // Public
        toggle() {
            // Toggle class and sync the `aria-pressed` attribute with the return value of the `.toggle()` method
            this._element.setAttribute('aria-pressed', this._element.classList.toggle(CLASS_NAME_ACTIVE$3));
        }

        // Static
        static jQueryInterface(config) {
            return this.each(function() {
                const data = Button.getOrCreateInstance(this);
                if (config === 'toggle') {
                    data[config]();
                }
            });
        }
    }

    /**
     * Data API implementation
     */

    EventHandler.on(document, EVENT_CLICK_DATA_API$6, SELECTOR_DATA_TOGGLE$5, event => {
        event.preventDefault();
        const button = event.target.closest(SELECTOR_DATA_TOGGLE$5);
        const data = Button.getOrCreateInstance(button);
        data.toggle();
    });

    /**
     * jQuery
     */

    defineJQueryPlugin(Button);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap util/swipe.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$d = 'swipe';
    const EVENT_KEY$9 = '.bs.swipe';
    const EVENT_TOUCHSTART = `touchstart${EVENT_KEY$9}`;
    const EVENT_TOUCHMOVE = `touchmove${EVENT_KEY$9}`;
    const EVENT_TOUCHEND = `touchend${EVENT_KEY$9}`;
    const EVENT_POINTERDOWN = `pointerdown${EVENT_KEY$9}`;
    const EVENT_POINTERUP = `pointerup${EVENT_KEY$9}`;
    const POINTER_TYPE_TOUCH = 'touch';
    const POINTER_TYPE_PEN = 'pen';
    const CLASS_NAME_POINTER_EVENT = 'pointer-event';
    const SWIPE_THRESHOLD = 40;
    const Default$c = {
        endCallback: null,
        leftCallback: null,
        rightCallback: null
    };
    const DefaultType$c = {
        endCallback: '(function|null)',
        leftCallback: '(function|null)',
        rightCallback: '(function|null)'
    };

    /**
     * Class definition
     */

    class Swipe extends Config {
        constructor(element, config) {
            super();
            this._element = element;
            if (!element || !Swipe.isSupported()) {
                return;
            }
            this._config = this._getConfig(config);
            this._deltaX = 0;
            this._supportPointerEvents = Boolean(window.PointerEvent);
            this._initEvents();
        }

        // Getters
        static get Default() {
            return Default$c;
        }
        static get DefaultType() {
            return DefaultType$c;
        }
        static get NAME() {
            return NAME$d;
        }

        // Public
        dispose() {
            EventHandler.off(this._element, EVENT_KEY$9);
        }

        // Private
        _start(event) {
            if (!this._supportPointerEvents) {
                this._deltaX = event.touches[0].clientX;
                return;
            }
            if (this._eventIsPointerPenTouch(event)) {
                this._deltaX = event.clientX;
            }
        }
        _end(event) {
            if (this._eventIsPointerPenTouch(event)) {
                this._deltaX = event.clientX - this._deltaX;
            }
            this._handleSwipe();
            execute(this._config.endCallback);
        }
        _move(event) {
            this._deltaX = event.touches && event.touches.length > 1 ? 0 : event.touches[0].clientX - this._deltaX;
        }
        _handleSwipe() {
            const absDeltaX = Math.abs(this._deltaX);
            if (absDeltaX <= SWIPE_THRESHOLD) {
                return;
            }
            const direction = absDeltaX / this._deltaX;
            this._deltaX = 0;
            if (!direction) {
                return;
            }
            execute(direction > 0 ? this._config.rightCallback : this._config.leftCallback);
        }
        _initEvents() {
            if (this._supportPointerEvents) {
                EventHandler.on(this._element, EVENT_POINTERDOWN, event => this._start(event));
                EventHandler.on(this._element, EVENT_POINTERUP, event => this._end(event));
                this._element.classList.add(CLASS_NAME_POINTER_EVENT);
            } else {
                EventHandler.on(this._element, EVENT_TOUCHSTART, event => this._start(event));
                EventHandler.on(this._element, EVENT_TOUCHMOVE, event => this._move(event));
                EventHandler.on(this._element, EVENT_TOUCHEND, event => this._end(event));
            }
        }
        _eventIsPointerPenTouch(event) {
            return this._supportPointerEvents && (event.pointerType === POINTER_TYPE_PEN || event.pointerType === POINTER_TYPE_TOUCH);
        }

        // Static
        static isSupported() {
            return 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0;
        }
    }

    /**
     * --------------------------------------------------------------------------
     * Bootstrap carousel.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$c = 'carousel';
    const DATA_KEY$8 = 'bs.carousel';
    const EVENT_KEY$8 = `.${DATA_KEY$8}`;
    const DATA_API_KEY$5 = '.data-api';
    const ARROW_LEFT_KEY$1 = 'ArrowLeft';
    const ARROW_RIGHT_KEY$1 = 'ArrowRight';
    const TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch

    const ORDER_NEXT = 'next';
    const ORDER_PREV = 'prev';
    const DIRECTION_LEFT = 'left';
    const DIRECTION_RIGHT = 'right';
    const EVENT_SLIDE = `slide${EVENT_KEY$8}`;
    const EVENT_SLID = `slid${EVENT_KEY$8}`;
    const EVENT_KEYDOWN$1 = `keydown${EVENT_KEY$8}`;
    const EVENT_MOUSEENTER$1 = `mouseenter${EVENT_KEY$8}`;
    const EVENT_MOUSELEAVE$1 = `mouseleave${EVENT_KEY$8}`;
    const EVENT_DRAG_START = `dragstart${EVENT_KEY$8}`;
    const EVENT_LOAD_DATA_API$3 = `load${EVENT_KEY$8}${DATA_API_KEY$5}`;
    const EVENT_CLICK_DATA_API$5 = `click${EVENT_KEY$8}${DATA_API_KEY$5}`;
    const CLASS_NAME_CAROUSEL = 'carousel';
    const CLASS_NAME_ACTIVE$2 = 'active';
    const CLASS_NAME_SLIDE = 'slide';
    const CLASS_NAME_END = 'carousel-item-end';
    const CLASS_NAME_START = 'carousel-item-start';
    const CLASS_NAME_NEXT = 'carousel-item-next';
    const CLASS_NAME_PREV = 'carousel-item-prev';
    const SELECTOR_ACTIVE = '.active';
    const SELECTOR_ITEM = '.carousel-item';
    const SELECTOR_ACTIVE_ITEM = SELECTOR_ACTIVE + SELECTOR_ITEM;
    const SELECTOR_ITEM_IMG = '.carousel-item img';
    const SELECTOR_INDICATORS = '.carousel-indicators';
    const SELECTOR_DATA_SLIDE = '[data-bs-slide], [data-bs-slide-to]';
    const SELECTOR_DATA_RIDE = '[data-bs-ride="carousel"]';
    const KEY_TO_DIRECTION = {
        [ARROW_LEFT_KEY$1]: DIRECTION_RIGHT,
        [ARROW_RIGHT_KEY$1]: DIRECTION_LEFT
    };
    const Default$b = {
        interval: 5000,
        keyboard: true,
        pause: 'hover',
        ride: false,
        touch: true,
        wrap: true
    };
    const DefaultType$b = {
        interval: '(number|boolean)',
        // TODO:v6 remove boolean support
        keyboard: 'boolean',
        pause: '(string|boolean)',
        ride: '(boolean|string)',
        touch: 'boolean',
        wrap: 'boolean'
    };

    /**
     * Class definition
     */

    class Carousel extends BaseComponent {
        constructor(element, config) {
            super(element, config);
            this._interval = null;
            this._activeElement = null;
            this._isSliding = false;
            this.touchTimeout = null;
            this._swipeHelper = null;
            this._indicatorsElement = SelectorEngine.findOne(SELECTOR_INDICATORS, this._element);
            this._addEventListeners();
            if (this._config.ride === CLASS_NAME_CAROUSEL) {
                this.cycle();
            }
        }

        // Getters
        static get Default() {
            return Default$b;
        }
        static get DefaultType() {
            return DefaultType$b;
        }
        static get NAME() {
            return NAME$c;
        }

        // Public
        next() {
            this._slide(ORDER_NEXT);
        }
        nextWhenVisible() {
            // FIXME TODO use `document.visibilityState`
            // Don't call next when the page isn't visible
            // or the carousel or its parent isn't visible
            if (!document.hidden && isVisible(this._element)) {
                this.next();
            }
        }
        prev() {
            this._slide(ORDER_PREV);
        }
        pause() {
            if (this._isSliding) {
                triggerTransitionEnd(this._element);
            }
            this._clearInterval();
        }
        cycle() {
            this._clearInterval();
            this._updateInterval();
            this._interval = setInterval(() => this.nextWhenVisible(), this._config.interval);
        }
        _maybeEnableCycle() {
            if (!this._config.ride) {
                return;
            }
            if (this._isSliding) {
                EventHandler.one(this._element, EVENT_SLID, () => this.cycle());
                return;
            }
            this.cycle();
        }
        to(index) {
            const items = this._getItems();
            if (index > items.length - 1 || index < 0) {
                return;
            }
            if (this._isSliding) {
                EventHandler.one(this._element, EVENT_SLID, () => this.to(index));
                return;
            }
            const activeIndex = this._getItemIndex(this._getActive());
            if (activeIndex === index) {
                return;
            }
            const order = index > activeIndex ? ORDER_NEXT : ORDER_PREV;
            this._slide(order, items[index]);
        }
        dispose() {
            if (this._swipeHelper) {
                this._swipeHelper.dispose();
            }
            super.dispose();
        }

        // Private
        _configAfterMerge(config) {
            config.defaultInterval = config.interval;
            return config;
        }
        _addEventListeners() {
            if (this._config.keyboard) {
                EventHandler.on(this._element, EVENT_KEYDOWN$1, event => this._keydown(event));
            }
            if (this._config.pause === 'hover') {
                EventHandler.on(this._element, EVENT_MOUSEENTER$1, () => this.pause());
                EventHandler.on(this._element, EVENT_MOUSELEAVE$1, () => this._maybeEnableCycle());
            }
            if (this._config.touch && Swipe.isSupported()) {
                this._addTouchEventListeners();
            }
        }
        _addTouchEventListeners() {
            for (const img of SelectorEngine.find(SELECTOR_ITEM_IMG, this._element)) {
                EventHandler.on(img, EVENT_DRAG_START, event => event.preventDefault());
            }
            const endCallBack = () => {
                if (this._config.pause !== 'hover') {
                    return;
                }

                // If it's a touch-enabled device, mouseenter/leave are fired as
                // part of the mouse compatibility events on first tap - the carousel
                // would stop cycling until user tapped out of it;
                // here, we listen for touchend, explicitly pause the carousel
                // (as if it's the second time we tap on it, mouseenter compat event
                // is NOT fired) and after a timeout (to allow for mouse compatibility
                // events to fire) we explicitly restart cycling

                this.pause();
                if (this.touchTimeout) {
                    clearTimeout(this.touchTimeout);
                }
                this.touchTimeout = setTimeout(() => this._maybeEnableCycle(), TOUCHEVENT_COMPAT_WAIT + this._config.interval);
            };
            const swipeConfig = {
                leftCallback: () => this._slide(this._directionToOrder(DIRECTION_LEFT)),
                rightCallback: () => this._slide(this._directionToOrder(DIRECTION_RIGHT)),
                endCallback: endCallBack
            };
            this._swipeHelper = new Swipe(this._element, swipeConfig);
        }
        _keydown(event) {
            if (/input|textarea/i.test(event.target.tagName)) {
                return;
            }
            const direction = KEY_TO_DIRECTION[event.key];
            if (direction) {
                event.preventDefault();
                this._slide(this._directionToOrder(direction));
            }
        }
        _getItemIndex(element) {
            return this._getItems().indexOf(element);
        }
        _setActiveIndicatorElement(index) {
            if (!this._indicatorsElement) {
                return;
            }
            const activeIndicator = SelectorEngine.findOne(SELECTOR_ACTIVE, this._indicatorsElement);
            activeIndicator.classList.remove(CLASS_NAME_ACTIVE$2);
            activeIndicator.removeAttribute('aria-current');
            const newActiveIndicator = SelectorEngine.findOne(`[data-bs-slide-to="${index}"]`, this._indicatorsElement);
            if (newActiveIndicator) {
                newActiveIndicator.classList.add(CLASS_NAME_ACTIVE$2);
                newActiveIndicator.setAttribute('aria-current', 'true');
            }
        }
        _updateInterval() {
            const element = this._activeElement || this._getActive();
            if (!element) {
                return;
            }
            const elementInterval = Number.parseInt(element.getAttribute('data-bs-interval'), 10);
            this._config.interval = elementInterval || this._config.defaultInterval;
        }
        _slide(order, element = null) {
            if (this._isSliding) {
                return;
            }
            const activeElement = this._getActive();
            const isNext = order === ORDER_NEXT;
            const nextElement = element || getNextActiveElement(this._getItems(), activeElement, isNext, this._config.wrap);
            if (nextElement === activeElement) {
                return;
            }
            const nextElementIndex = this._getItemIndex(nextElement);
            const triggerEvent = eventName => {
                return EventHandler.trigger(this._element, eventName, {
                    relatedTarget: nextElement,
                    direction: this._orderToDirection(order),
                    from: this._getItemIndex(activeElement),
                    to: nextElementIndex
                });
            };
            const slideEvent = triggerEvent(EVENT_SLIDE);
            if (slideEvent.defaultPrevented) {
                return;
            }
            if (!activeElement || !nextElement) {
                // Some weirdness is happening, so we bail
                // TODO: change tests that use empty divs to avoid this check
                return;
            }
            const isCycling = Boolean(this._interval);
            this.pause();
            this._isSliding = true;
            this._setActiveIndicatorElement(nextElementIndex);
            this._activeElement = nextElement;
            const directionalClassName = isNext ? CLASS_NAME_START : CLASS_NAME_END;
            const orderClassName = isNext ? CLASS_NAME_NEXT : CLASS_NAME_PREV;
            nextElement.classList.add(orderClassName);
            reflow(nextElement);
            activeElement.classList.add(directionalClassName);
            nextElement.classList.add(directionalClassName);
            const completeCallBack = () => {
                nextElement.classList.remove(directionalClassName, orderClassName);
                nextElement.classList.add(CLASS_NAME_ACTIVE$2);
                activeElement.classList.remove(CLASS_NAME_ACTIVE$2, orderClassName, directionalClassName);
                this._isSliding = false;
                triggerEvent(EVENT_SLID);
            };
            this._queueCallback(completeCallBack, activeElement, this._isAnimated());
            if (isCycling) {
                this.cycle();
            }
        }
        _isAnimated() {
            return this._element.classList.contains(CLASS_NAME_SLIDE);
        }
        _getActive() {
            return SelectorEngine.findOne(SELECTOR_ACTIVE_ITEM, this._element);
        }
        _getItems() {
            return SelectorEngine.find(SELECTOR_ITEM, this._element);
        }
        _clearInterval() {
            if (this._interval) {
                clearInterval(this._interval);
                this._interval = null;
            }
        }
        _directionToOrder(direction) {
            if (isRTL()) {
                return direction === DIRECTION_LEFT ? ORDER_PREV : ORDER_NEXT;
            }
            return direction === DIRECTION_LEFT ? ORDER_NEXT : ORDER_PREV;
        }
        _orderToDirection(order) {
            if (isRTL()) {
                return order === ORDER_PREV ? DIRECTION_LEFT : DIRECTION_RIGHT;
            }
            return order === ORDER_PREV ? DIRECTION_RIGHT : DIRECTION_LEFT;
        }

        // Static
        static jQueryInterface(config) {
            return this.each(function() {
                const data = Carousel.getOrCreateInstance(this, config);
                if (typeof config === 'number') {
                    data.to(config);
                    return;
                }
                if (typeof config === 'string') {
                    if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
                        throw new TypeError(`No method named "${config}"`);
                    }
                    data[config]();
                }
            });
        }
    }

    /**
     * Data API implementation
     */

    EventHandler.on(document, EVENT_CLICK_DATA_API$5, SELECTOR_DATA_SLIDE, function(event) {
        const target = SelectorEngine.getElementFromSelector(this);
        if (!target || !target.classList.contains(CLASS_NAME_CAROUSEL)) {
            return;
        }
        event.preventDefault();
        const carousel = Carousel.getOrCreateInstance(target);
        const slideIndex = this.getAttribute('data-bs-slide-to');
        if (slideIndex) {
            carousel.to(slideIndex);
            carousel._maybeEnableCycle();
            return;
        }
        if (Manipulator.getDataAttribute(this, 'slide') === 'next') {
            carousel.next();
            carousel._maybeEnableCycle();
            return;
        }
        carousel.prev();
        carousel._maybeEnableCycle();
    });
    EventHandler.on(window, EVENT_LOAD_DATA_API$3, () => {
        const carousels = SelectorEngine.find(SELECTOR_DATA_RIDE);
        for (const carousel of carousels) {
            Carousel.getOrCreateInstance(carousel);
        }
    });

    /**
     * jQuery
     */

    defineJQueryPlugin(Carousel);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap collapse.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$b = 'collapse';
    const DATA_KEY$7 = 'bs.collapse';
    const EVENT_KEY$7 = `.${DATA_KEY$7}`;
    const DATA_API_KEY$4 = '.data-api';
    const EVENT_SHOW$6 = `show${EVENT_KEY$7}`;
    const EVENT_SHOWN$6 = `shown${EVENT_KEY$7}`;
    const EVENT_HIDE$6 = `hide${EVENT_KEY$7}`;
    const EVENT_HIDDEN$6 = `hidden${EVENT_KEY$7}`;
    const EVENT_CLICK_DATA_API$4 = `click${EVENT_KEY$7}${DATA_API_KEY$4}`;
    const CLASS_NAME_SHOW$7 = 'show';
    const CLASS_NAME_COLLAPSE = 'collapse';
    const CLASS_NAME_COLLAPSING = 'collapsing';
    const CLASS_NAME_COLLAPSED = 'collapsed';
    const CLASS_NAME_DEEPER_CHILDREN = `:scope .${CLASS_NAME_COLLAPSE} .${CLASS_NAME_COLLAPSE}`;
    const CLASS_NAME_HORIZONTAL = 'collapse-horizontal';
    const WIDTH = 'width';
    const HEIGHT = 'height';
    const SELECTOR_ACTIVES = '.collapse.show, .collapse.collapsing';
    const SELECTOR_DATA_TOGGLE$4 = '[data-bs-toggle="collapse"]';
    const Default$a = {
        parent: null,
        toggle: true
    };
    const DefaultType$a = {
        parent: '(null|element)',
        toggle: 'boolean'
    };

    /**
     * Class definition
     */

    class Collapse extends BaseComponent {
        constructor(element, config) {
            super(element, config);
            this._isTransitioning = false;
            this._triggerArray = [];
            const toggleList = SelectorEngine.find(SELECTOR_DATA_TOGGLE$4);
            for (const elem of toggleList) {
                const selector = SelectorEngine.getSelectorFromElement(elem);
                const filterElement = SelectorEngine.find(selector).filter(foundElement => foundElement === this._element);
                if (selector !== null && filterElement.length) {
                    this._triggerArray.push(elem);
                }
            }
            this._initializeChildren();
            if (!this._config.parent) {
                this._addAriaAndCollapsedClass(this._triggerArray, this._isShown());
            }
            if (this._config.toggle) {
                this.toggle();
            }
        }

        // Getters
        static get Default() {
            return Default$a;
        }
        static get DefaultType() {
            return DefaultType$a;
        }
        static get NAME() {
            return NAME$b;
        }

        // Public
        toggle() {
            if (this._isShown()) {
                this.hide();
            } else {
                this.show();
            }
        }
        show() {
            if (this._isTransitioning || this._isShown()) {
                return;
            }
            let activeChildren = [];

            // find active children
            if (this._config.parent) {
                activeChildren = this._getFirstLevelChildren(SELECTOR_ACTIVES).filter(element => element !== this._element).map(element => Collapse.getOrCreateInstance(element, {
                    toggle: false
                }));
            }
            if (activeChildren.length && activeChildren[0]._isTransitioning) {
                return;
            }
            const startEvent = EventHandler.trigger(this._element, EVENT_SHOW$6);
            if (startEvent.defaultPrevented) {
                return;
            }
            for (const activeInstance of activeChildren) {
                activeInstance.hide();
            }
            const dimension = this._getDimension();
            this._element.classList.remove(CLASS_NAME_COLLAPSE);
            this._element.classList.add(CLASS_NAME_COLLAPSING);
            this._element.style[dimension] = 0;
            this._addAriaAndCollapsedClass(this._triggerArray, true);
            this._isTransitioning = true;
            const complete = () => {
                this._isTransitioning = false;
                this._element.classList.remove(CLASS_NAME_COLLAPSING);
                this._element.classList.add(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7);
                this._element.style[dimension] = '';
                EventHandler.trigger(this._element, EVENT_SHOWN$6);
            };
            const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
            const scrollSize = `scroll${capitalizedDimension}`;
            this._queueCallback(complete, this._element, true);
            this._element.style[dimension] = `${this._element[scrollSize]}px`;
        }
        hide() {
            if (this._isTransitioning || !this._isShown()) {
                return;
            }
            const startEvent = EventHandler.trigger(this._element, EVENT_HIDE$6);
            if (startEvent.defaultPrevented) {
                return;
            }
            const dimension = this._getDimension();
            this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`;
            reflow(this._element);
            this._element.classList.add(CLASS_NAME_COLLAPSING);
            this._element.classList.remove(CLASS_NAME_COLLAPSE, CLASS_NAME_SHOW$7);
            for (const trigger of this._triggerArray) {
                const element = SelectorEngine.getElementFromSelector(trigger);
                if (element && !this._isShown(element)) {
                    this._addAriaAndCollapsedClass([trigger], false);
                }
            }
            this._isTransitioning = true;
            const complete = () => {
                this._isTransitioning = false;
                this._element.classList.remove(CLASS_NAME_COLLAPSING);
                this._element.classList.add(CLASS_NAME_COLLAPSE);
                EventHandler.trigger(this._element, EVENT_HIDDEN$6);
            };
            this._element.style[dimension] = '';
            this._queueCallback(complete, this._element, true);
        }

        // Private
        _isShown(element = this._element) {
            return element.classList.contains(CLASS_NAME_SHOW$7);
        }
        _configAfterMerge(config) {
            config.toggle = Boolean(config.toggle); // Coerce string values
            config.parent = getElement(config.parent);
            return config;
        }
        _getDimension() {
            return this._element.classList.contains(CLASS_NAME_HORIZONTAL) ? WIDTH : HEIGHT;
        }
        _initializeChildren() {
            if (!this._config.parent) {
                return;
            }
            const children = this._getFirstLevelChildren(SELECTOR_DATA_TOGGLE$4);
            for (const element of children) {
                const selected = SelectorEngine.getElementFromSelector(element);
                if (selected) {
                    this._addAriaAndCollapsedClass([element], this._isShown(selected));
                }
            }
        }
        _getFirstLevelChildren(selector) {
            const children = SelectorEngine.find(CLASS_NAME_DEEPER_CHILDREN, this._config.parent);
            // remove children if greater depth
            return SelectorEngine.find(selector, this._config.parent).filter(element => !children.includes(element));
        }
        _addAriaAndCollapsedClass(triggerArray, isOpen) {
            if (!triggerArray.length) {
                return;
            }
            for (const element of triggerArray) {
                element.classList.toggle(CLASS_NAME_COLLAPSED, !isOpen);
                element.setAttribute('aria-expanded', isOpen);
            }
        }

        // Static
        static jQueryInterface(config) {
            const _config = {};
            if (typeof config === 'string' && /show|hide/.test(config)) {
                _config.toggle = false;
            }
            return this.each(function() {
                const data = Collapse.getOrCreateInstance(this, _config);
                if (typeof config === 'string') {
                    if (typeof data[config] === 'undefined') {
                        throw new TypeError(`No method named "${config}"`);
                    }
                    data[config]();
                }
            });
        }
    }

    /**
     * Data API implementation
     */

    EventHandler.on(document, EVENT_CLICK_DATA_API$4, SELECTOR_DATA_TOGGLE$4, function(event) {
        // preventDefault only for <a> elements (which change the URL) not inside the collapsible element
        if (event.target.tagName === 'A' || event.delegateTarget && event.delegateTarget.tagName === 'A') {
            event.preventDefault();
        }
        for (const element of SelectorEngine.getMultipleElementsFromSelector(this)) {
            Collapse.getOrCreateInstance(element, {
                toggle: false
            }).toggle();
        }
    });

    /**
     * jQuery
     */

    defineJQueryPlugin(Collapse);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap dropdown.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$a = 'dropdown';
    const DATA_KEY$6 = 'bs.dropdown';
    const EVENT_KEY$6 = `.${DATA_KEY$6}`;
    const DATA_API_KEY$3 = '.data-api';
    const ESCAPE_KEY$2 = 'Escape';
    const TAB_KEY$1 = 'Tab';
    const ARROW_UP_KEY$1 = 'ArrowUp';
    const ARROW_DOWN_KEY$1 = 'ArrowDown';
    const RIGHT_MOUSE_BUTTON = 2; // MouseEvent.button value for the secondary button, usually the right button

    const EVENT_HIDE$5 = `hide${EVENT_KEY$6}`;
    const EVENT_HIDDEN$5 = `hidden${EVENT_KEY$6}`;
    const EVENT_SHOW$5 = `show${EVENT_KEY$6}`;
    const EVENT_SHOWN$5 = `shown${EVENT_KEY$6}`;
    const EVENT_CLICK_DATA_API$3 = `click${EVENT_KEY$6}${DATA_API_KEY$3}`;
    const EVENT_KEYDOWN_DATA_API = `keydown${EVENT_KEY$6}${DATA_API_KEY$3}`;
    const EVENT_KEYUP_DATA_API = `keyup${EVENT_KEY$6}${DATA_API_KEY$3}`;
    const CLASS_NAME_SHOW$6 = 'show';
    const CLASS_NAME_DROPUP = 'dropup';
    const CLASS_NAME_DROPEND = 'dropend';
    const CLASS_NAME_DROPSTART = 'dropstart';
    const CLASS_NAME_DROPUP_CENTER = 'dropup-center';
    const CLASS_NAME_DROPDOWN_CENTER = 'dropdown-center';
    const SELECTOR_DATA_TOGGLE$3 = '[data-bs-toggle="dropdown"]:not(.disabled):not(:disabled)';
    const SELECTOR_DATA_TOGGLE_SHOWN = `${SELECTOR_DATA_TOGGLE$3}.${CLASS_NAME_SHOW$6}`;
    const SELECTOR_MENU = '.dropdown-menu';
    const SELECTOR_NAVBAR = '.navbar';
    const SELECTOR_NAVBAR_NAV = '.navbar-nav';
    const SELECTOR_VISIBLE_ITEMS = '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)';
    const PLACEMENT_TOP = isRTL() ? 'top-end' : 'top-start';
    const PLACEMENT_TOPEND = isRTL() ? 'top-start' : 'top-end';
    const PLACEMENT_BOTTOM = isRTL() ? 'bottom-end' : 'bottom-start';
    const PLACEMENT_BOTTOMEND = isRTL() ? 'bottom-start' : 'bottom-end';
    const PLACEMENT_RIGHT = isRTL() ? 'left-start' : 'right-start';
    const PLACEMENT_LEFT = isRTL() ? 'right-start' : 'left-start';
    const PLACEMENT_TOPCENTER = 'top';
    const PLACEMENT_BOTTOMCENTER = 'bottom';
    const Default$9 = {
        autoClose: true,
        boundary: 'clippingParents',
        display: 'dynamic',
        offset: [0, 2],
        popperConfig: null,
        reference: 'toggle'
    };
    const DefaultType$9 = {
        autoClose: '(boolean|string)',
        boundary: '(string|element)',
        display: 'string',
        offset: '(array|string|function)',
        popperConfig: '(null|object|function)',
        reference: '(string|element|object)'
    };

    /**
     * Class definition
     */

    class Dropdown extends BaseComponent {
        constructor(element, config) {
            super(element, config);
            this._popper = null;
            this._parent = this._element.parentNode; // dropdown wrapper
            // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
            this._menu = SelectorEngine.next(this._element, SELECTOR_MENU)[0] || SelectorEngine.prev(this._element, SELECTOR_MENU)[0] || SelectorEngine.findOne(SELECTOR_MENU, this._parent);
            this._inNavbar = this._detectNavbar();
        }

        // Getters
        static get Default() {
            return Default$9;
        }
        static get DefaultType() {
            return DefaultType$9;
        }
        static get NAME() {
            return NAME$a;
        }

        // Public
        toggle() {
            return this._isShown() ? this.hide() : this.show();
        }
        show() {
            if (isDisabled(this._element) || this._isShown()) {
                return;
            }
            const relatedTarget = {
                relatedTarget: this._element
            };
            const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$5, relatedTarget);
            if (showEvent.defaultPrevented) {
                return;
            }
            this._createPopper();

            // If this is a touch-enabled device we add extra
            // empty mouseover listeners to the body's immediate children;
            // only needed because of broken event delegation on iOS
            // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
            if ('ontouchstart' in document.documentElement && !this._parent.closest(SELECTOR_NAVBAR_NAV)) {
                for (const element of [].concat(...document.body.children)) {
                    EventHandler.on(element, 'mouseover', noop);
                }
            }
            this._element.focus();
            this._element.setAttribute('aria-expanded', true);
            this._menu.classList.add(CLASS_NAME_SHOW$6);
            this._element.classList.add(CLASS_NAME_SHOW$6);
            EventHandler.trigger(this._element, EVENT_SHOWN$5, relatedTarget);
        }
        hide() {
            if (isDisabled(this._element) || !this._isShown()) {
                return;
            }
            const relatedTarget = {
                relatedTarget: this._element
            };
            this._completeHide(relatedTarget);
        }
        dispose() {
            if (this._popper) {
                this._popper.destroy();
            }
            super.dispose();
        }
        update() {
            this._inNavbar = this._detectNavbar();
            if (this._popper) {
                this._popper.update();
            }
        }

        // Private
        _completeHide(relatedTarget) {
            const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$5, relatedTarget);
            if (hideEvent.defaultPrevented) {
                return;
            }

            // If this is a touch-enabled device we remove the extra
            // empty mouseover listeners we added for iOS support
            if ('ontouchstart' in document.documentElement) {
                for (const element of [].concat(...document.body.children)) {
                    EventHandler.off(element, 'mouseover', noop);
                }
            }
            if (this._popper) {
                this._popper.destroy();
            }
            this._menu.classList.remove(CLASS_NAME_SHOW$6);
            this._element.classList.remove(CLASS_NAME_SHOW$6);
            this._element.setAttribute('aria-expanded', 'false');
            Manipulator.removeDataAttribute(this._menu, 'popper');
            EventHandler.trigger(this._element, EVENT_HIDDEN$5, relatedTarget);
        }
        _getConfig(config) {
            config = super._getConfig(config);
            if (typeof config.reference === 'object' && !isElement(config.reference) && typeof config.reference.getBoundingClientRect !== 'function') {
                // Popper virtual elements require a getBoundingClientRect method
                throw new TypeError(`${NAME$a.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);
            }
            return config;
        }
        _createPopper() {
            if (typeof Popper__namespace === 'undefined') {
                throw new TypeError('Bootstrap\'s dropdowns require Popper (https://popper.js.org/docs/v2/)');
            }
            let referenceElement = this._element;
            if (this._config.reference === 'parent') {
                referenceElement = this._parent;
            } else if (isElement(this._config.reference)) {
                referenceElement = getElement(this._config.reference);
            } else if (typeof this._config.reference === 'object') {
                referenceElement = this._config.reference;
            }
            const popperConfig = this._getPopperConfig();
            this._popper = Popper__namespace.createPopper(referenceElement, this._menu, popperConfig);
        }
        _isShown() {
            return this._menu.classList.contains(CLASS_NAME_SHOW$6);
        }
        _getPlacement() {
            const parentDropdown = this._parent;
            if (parentDropdown.classList.contains(CLASS_NAME_DROPEND)) {
                return PLACEMENT_RIGHT;
            }
            if (parentDropdown.classList.contains(CLASS_NAME_DROPSTART)) {
                return PLACEMENT_LEFT;
            }
            if (parentDropdown.classList.contains(CLASS_NAME_DROPUP_CENTER)) {
                return PLACEMENT_TOPCENTER;
            }
            if (parentDropdown.classList.contains(CLASS_NAME_DROPDOWN_CENTER)) {
                return PLACEMENT_BOTTOMCENTER;
            }

            // We need to trim the value because custom properties can also include spaces
            const isEnd = getComputedStyle(this._menu).getPropertyValue('--bs-position').trim() === 'end';
            if (parentDropdown.classList.contains(CLASS_NAME_DROPUP)) {
                return isEnd ? PLACEMENT_TOPEND : PLACEMENT_TOP;
            }
            return isEnd ? PLACEMENT_BOTTOMEND : PLACEMENT_BOTTOM;
        }
        _detectNavbar() {
            return this._element.closest(SELECTOR_NAVBAR) !== null;
        }
        _getOffset() {
            const {
                offset
            } = this._config;
            if (typeof offset === 'string') {
                return offset.split(',').map(value => Number.parseInt(value, 10));
            }
            if (typeof offset === 'function') {
                return popperData => offset(popperData, this._element);
            }
            return offset;
        }
        _getPopperConfig() {
            const defaultBsPopperConfig = {
                placement: this._getPlacement(),
                modifiers: [{
                    name: 'preventOverflow',
                    options: {
                        boundary: this._config.boundary
                    }
                }, {
                    name: 'offset',
                    options: {
                        offset: this._getOffset()
                    }
                }]
            };

            // Disable Popper if we have a static display or Dropdown is in Navbar
            if (this._inNavbar || this._config.display === 'static') {
                Manipulator.setDataAttribute(this._menu, 'popper', 'static'); // TODO: v6 remove
                defaultBsPopperConfig.modifiers = [{
                    name: 'applyStyles',
                    enabled: false
                }];
            }
            return {
                ...defaultBsPopperConfig,
                ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
            };
        }
        _selectMenuItem({
            key,
            target
        }) {
            const items = SelectorEngine.find(SELECTOR_VISIBLE_ITEMS, this._menu).filter(element => isVisible(element));
            if (!items.length) {
                return;
            }

            // if target isn't included in items (e.g. when expanding the dropdown)
            // allow cycling to get the last item in case key equals ARROW_UP_KEY
            getNextActiveElement(items, target, key === ARROW_DOWN_KEY$1, !items.includes(target)).focus();
        }

        // Static
        static jQueryInterface(config) {
            return this.each(function() {
                const data = Dropdown.getOrCreateInstance(this, config);
                if (typeof config !== 'string') {
                    return;
                }
                if (typeof data[config] === 'undefined') {
                    throw new TypeError(`No method named "${config}"`);
                }
                data[config]();
            });
        }
        static clearMenus(event) {
            if (event.button === RIGHT_MOUSE_BUTTON || event.type === 'keyup' && event.key !== TAB_KEY$1) {
                return;
            }
            const openToggles = SelectorEngine.find(SELECTOR_DATA_TOGGLE_SHOWN);
            for (const toggle of openToggles) {
                const context = Dropdown.getInstance(toggle);
                if (!context || context._config.autoClose === false) {
                    continue;
                }
                const composedPath = event.composedPath();
                const isMenuTarget = composedPath.includes(context._menu);
                if (composedPath.includes(context._element) || context._config.autoClose === 'inside' && !isMenuTarget || context._config.autoClose === 'outside' && isMenuTarget) {
                    continue;
                }

                // Tab navigation through the dropdown menu or events from contained inputs shouldn't close the menu
                if (context._menu.contains(event.target) && (event.type === 'keyup' && event.key === TAB_KEY$1 || /input|select|option|textarea|form/i.test(event.target.tagName))) {
                    continue;
                }
                const relatedTarget = {
                    relatedTarget: context._element
                };
                if (event.type === 'click') {
                    relatedTarget.clickEvent = event;
                }
                context._completeHide(relatedTarget);
            }
        }
        static dataApiKeydownHandler(event) {
            // If not an UP | DOWN | ESCAPE key => not a dropdown command
            // If input/textarea && if key is other than ESCAPE => not a dropdown command

            const isInput = /input|textarea/i.test(event.target.tagName);
            const isEscapeEvent = event.key === ESCAPE_KEY$2;
            const isUpOrDownEvent = [ARROW_UP_KEY$1, ARROW_DOWN_KEY$1].includes(event.key);
            if (!isUpOrDownEvent && !isEscapeEvent) {
                return;
            }
            if (isInput && !isEscapeEvent) {
                return;
            }
            event.preventDefault();

            // TODO: v6 revert #37011 & change markup https://getbootstrap.com/docs/5.3/forms/input-group/
            const getToggleButton = this.matches(SELECTOR_DATA_TOGGLE$3) ? this : SelectorEngine.prev(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.next(this, SELECTOR_DATA_TOGGLE$3)[0] || SelectorEngine.findOne(SELECTOR_DATA_TOGGLE$3, event.delegateTarget.parentNode);
            const instance = Dropdown.getOrCreateInstance(getToggleButton);
            if (isUpOrDownEvent) {
                event.stopPropagation();
                instance.show();
                instance._selectMenuItem(event);
                return;
            }
            if (instance._isShown()) {
                // else is escape and we check if it is shown
                event.stopPropagation();
                instance.hide();
                getToggleButton.focus();
            }
        }
    }

    /**
     * Data API implementation
     */

    EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_DATA_TOGGLE$3, Dropdown.dataApiKeydownHandler);
    EventHandler.on(document, EVENT_KEYDOWN_DATA_API, SELECTOR_MENU, Dropdown.dataApiKeydownHandler);
    EventHandler.on(document, EVENT_CLICK_DATA_API$3, Dropdown.clearMenus);
    EventHandler.on(document, EVENT_KEYUP_DATA_API, Dropdown.clearMenus);
    EventHandler.on(document, EVENT_CLICK_DATA_API$3, SELECTOR_DATA_TOGGLE$3, function(event) {
        event.preventDefault();
        Dropdown.getOrCreateInstance(this).toggle();
    });

    /**
     * jQuery
     */

    defineJQueryPlugin(Dropdown);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap util/backdrop.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$9 = 'backdrop';
    const CLASS_NAME_FADE$4 = 'fade';
    const CLASS_NAME_SHOW$5 = 'show';
    const EVENT_MOUSEDOWN = `mousedown.bs.${NAME$9}`;
    const Default$8 = {
        className: 'modal-backdrop',
        clickCallback: null,
        isAnimated: false,
        isVisible: true,
        // if false, we use the backdrop helper without adding any element to the dom
        rootElement: 'body' // give the choice to place backdrop under different elements
    };
    const DefaultType$8 = {
        className: 'string',
        clickCallback: '(function|null)',
        isAnimated: 'boolean',
        isVisible: 'boolean',
        rootElement: '(element|string)'
    };

    /**
     * Class definition
     */

    class Backdrop extends Config {
        constructor(config) {
            super();
            this._config = this._getConfig(config);
            this._isAppended = false;
            this._element = null;
        }

        // Getters
        static get Default() {
            return Default$8;
        }
        static get DefaultType() {
            return DefaultType$8;
        }
        static get NAME() {
            return NAME$9;
        }

        // Public
        show(callback) {
            if (!this._config.isVisible) {
                execute(callback);
                return;
            }
            this._append();
            const element = this._getElement();
            if (this._config.isAnimated) {
                reflow(element);
            }
            element.classList.add(CLASS_NAME_SHOW$5);
            this._emulateAnimation(() => {
                execute(callback);
            });
        }
        hide(callback) {
            if (!this._config.isVisible) {
                execute(callback);
                return;
            }
            this._getElement().classList.remove(CLASS_NAME_SHOW$5);
            this._emulateAnimation(() => {
                this.dispose();
                execute(callback);
            });
        }
        dispose() {
            if (!this._isAppended) {
                return;
            }
            EventHandler.off(this._element, EVENT_MOUSEDOWN);
            this._element.remove();
            this._isAppended = false;
        }

        // Private
        _getElement() {
            if (!this._element) {
                const backdrop = document.createElement('div');
                backdrop.className = this._config.className;
                if (this._config.isAnimated) {
                    backdrop.classList.add(CLASS_NAME_FADE$4);
                }
                this._element = backdrop;
            }
            return this._element;
        }
        _configAfterMerge(config) {
            // use getElement() with the default "body" to get a fresh Element on each instantiation
            config.rootElement = getElement(config.rootElement);
            return config;
        }
        _append() {
            if (this._isAppended) {
                return;
            }
            const element = this._getElement();
            this._config.rootElement.append(element);
            EventHandler.on(element, EVENT_MOUSEDOWN, () => {
                execute(this._config.clickCallback);
            });
            this._isAppended = true;
        }
        _emulateAnimation(callback) {
            executeAfterTransition(callback, this._getElement(), this._config.isAnimated);
        }
    }

    /**
     * --------------------------------------------------------------------------
     * Bootstrap util/focustrap.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$8 = 'focustrap';
    const DATA_KEY$5 = 'bs.focustrap';
    const EVENT_KEY$5 = `.${DATA_KEY$5}`;
    const EVENT_FOCUSIN$2 = `focusin${EVENT_KEY$5}`;
    const EVENT_KEYDOWN_TAB = `keydown.tab${EVENT_KEY$5}`;
    const TAB_KEY = 'Tab';
    const TAB_NAV_FORWARD = 'forward';
    const TAB_NAV_BACKWARD = 'backward';
    const Default$7 = {
        autofocus: true,
        trapElement: null // The element to trap focus inside of
    };
    const DefaultType$7 = {
        autofocus: 'boolean',
        trapElement: 'element'
    };

    /**
     * Class definition
     */

    class FocusTrap extends Config {
        constructor(config) {
            super();
            this._config = this._getConfig(config);
            this._isActive = false;
            this._lastTabNavDirection = null;
        }

        // Getters
        static get Default() {
            return Default$7;
        }
        static get DefaultType() {
            return DefaultType$7;
        }
        static get NAME() {
            return NAME$8;
        }

        // Public
        activate() {
            if (this._isActive) {
                return;
            }
            if (this._config.autofocus) {
                this._config.trapElement.focus();
            }
            EventHandler.off(document, EVENT_KEY$5); // guard against infinite focus loop
            EventHandler.on(document, EVENT_FOCUSIN$2, event => this._handleFocusin(event));
            EventHandler.on(document, EVENT_KEYDOWN_TAB, event => this._handleKeydown(event));
            this._isActive = true;
        }
        deactivate() {
            if (!this._isActive) {
                return;
            }
            this._isActive = false;
            EventHandler.off(document, EVENT_KEY$5);
        }

        // Private
        _handleFocusin(event) {
            const {
                trapElement
            } = this._config;
            if (event.target === document || event.target === trapElement || trapElement.contains(event.target)) {
                return;
            }
            const elements = SelectorEngine.focusableChildren(trapElement);
            if (elements.length === 0) {
                trapElement.focus();
            } else if (this._lastTabNavDirection === TAB_NAV_BACKWARD) {
                elements[elements.length - 1].focus();
            } else {
                elements[0].focus();
            }
        }
        _handleKeydown(event) {
            if (event.key !== TAB_KEY) {
                return;
            }
            this._lastTabNavDirection = event.shiftKey ? TAB_NAV_BACKWARD : TAB_NAV_FORWARD;
        }
    }

    /**
     * --------------------------------------------------------------------------
     * Bootstrap util/scrollBar.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const SELECTOR_FIXED_CONTENT = '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top';
    const SELECTOR_STICKY_CONTENT = '.sticky-top';
    const PROPERTY_PADDING = 'padding-right';
    const PROPERTY_MARGIN = 'margin-right';

    /**
     * Class definition
     */

    class ScrollBarHelper {
        constructor() {
            this._element = document.body;
        }

        // Public
        getWidth() {
            // https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth#usage_notes
            const documentWidth = document.documentElement.clientWidth;
            return Math.abs(window.innerWidth - documentWidth);
        }
        hide() {
            const width = this.getWidth();
            this._disableOverFlow();
            // give padding to element to balance the hidden scrollbar width
            this._setElementAttributes(this._element, PROPERTY_PADDING, calculatedValue => calculatedValue + width);
            // trick: We adjust positive paddingRight and negative marginRight to sticky-top elements to keep showing fullwidth
            this._setElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING, calculatedValue => calculatedValue + width);
            this._setElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN, calculatedValue => calculatedValue - width);
        }
        reset() {
            this._resetElementAttributes(this._element, 'overflow');
            this._resetElementAttributes(this._element, PROPERTY_PADDING);
            this._resetElementAttributes(SELECTOR_FIXED_CONTENT, PROPERTY_PADDING);
            this._resetElementAttributes(SELECTOR_STICKY_CONTENT, PROPERTY_MARGIN);
        }
        isOverflowing() {
            return this.getWidth() > 0;
        }

        // Private
        _disableOverFlow() {
            this._saveInitialAttribute(this._element, 'overflow');
            this._element.style.overflow = 'hidden';
        }
        _setElementAttributes(selector, styleProperty, callback) {
            const scrollbarWidth = this.getWidth();
            const manipulationCallBack = element => {
                if (element !== this._element && window.innerWidth > element.clientWidth + scrollbarWidth) {
                    return;
                }
                this._saveInitialAttribute(element, styleProperty);
                const calculatedValue = window.getComputedStyle(element).getPropertyValue(styleProperty);
                element.style.setProperty(styleProperty, `${callback(Number.parseFloat(calculatedValue))}px`);
            };
            this._applyManipulationCallback(selector, manipulationCallBack);
        }
        _saveInitialAttribute(element, styleProperty) {
            const actualValue = element.style.getPropertyValue(styleProperty);
            if (actualValue) {
                Manipulator.setDataAttribute(element, styleProperty, actualValue);
            }
        }
        _resetElementAttributes(selector, styleProperty) {
            const manipulationCallBack = element => {
                const value = Manipulator.getDataAttribute(element, styleProperty);
                // We only want to remove the property if the value is `null`; the value can also be zero
                if (value === null) {
                    element.style.removeProperty(styleProperty);
                    return;
                }
                Manipulator.removeDataAttribute(element, styleProperty);
                element.style.setProperty(styleProperty, value);
            };
            this._applyManipulationCallback(selector, manipulationCallBack);
        }
        _applyManipulationCallback(selector, callBack) {
            if (isElement(selector)) {
                callBack(selector);
                return;
            }
            for (const sel of SelectorEngine.find(selector, this._element)) {
                callBack(sel);
            }
        }
    }

    /**
     * --------------------------------------------------------------------------
     * Bootstrap modal.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$7 = 'modal';
    const DATA_KEY$4 = 'bs.modal';
    const EVENT_KEY$4 = `.${DATA_KEY$4}`;
    const DATA_API_KEY$2 = '.data-api';
    const ESCAPE_KEY$1 = 'Escape';
    const EVENT_HIDE$4 = `hide${EVENT_KEY$4}`;
    const EVENT_HIDE_PREVENTED$1 = `hidePrevented${EVENT_KEY$4}`;
    const EVENT_HIDDEN$4 = `hidden${EVENT_KEY$4}`;
    const EVENT_SHOW$4 = `show${EVENT_KEY$4}`;
    const EVENT_SHOWN$4 = `shown${EVENT_KEY$4}`;
    const EVENT_RESIZE$1 = `resize${EVENT_KEY$4}`;
    const EVENT_CLICK_DISMISS = `click.dismiss${EVENT_KEY$4}`;
    const EVENT_MOUSEDOWN_DISMISS = `mousedown.dismiss${EVENT_KEY$4}`;
    const EVENT_KEYDOWN_DISMISS$1 = `keydown.dismiss${EVENT_KEY$4}`;
    const EVENT_CLICK_DATA_API$2 = `click${EVENT_KEY$4}${DATA_API_KEY$2}`;
    const CLASS_NAME_OPEN = 'modal-open';
    const CLASS_NAME_FADE$3 = 'fade';
    const CLASS_NAME_SHOW$4 = 'show';
    const CLASS_NAME_STATIC = 'modal-static';
    const OPEN_SELECTOR$1 = '.modal.show';
    const SELECTOR_DIALOG = '.modal-dialog';
    const SELECTOR_MODAL_BODY = '.modal-body';
    const SELECTOR_DATA_TOGGLE$2 = '[data-bs-toggle="modal"]';
    const Default$6 = {
        backdrop: true,
        focus: true,
        keyboard: true
    };
    const DefaultType$6 = {
        backdrop: '(boolean|string)',
        focus: 'boolean',
        keyboard: 'boolean'
    };

    /**
     * Class definition
     */

    class Modal extends BaseComponent {
        constructor(element, config) {
            super(element, config);
            this._dialog = SelectorEngine.findOne(SELECTOR_DIALOG, this._element);
            this._backdrop = this._initializeBackDrop();
            this._focustrap = this._initializeFocusTrap();
            this._isShown = false;
            this._isTransitioning = false;
            this._scrollBar = new ScrollBarHelper();
            this._addEventListeners();
        }

        // Getters
        static get Default() {
            return Default$6;
        }
        static get DefaultType() {
            return DefaultType$6;
        }
        static get NAME() {
            return NAME$7;
        }

        // Public
        toggle(relatedTarget) {
            return this._isShown ? this.hide() : this.show(relatedTarget);
        }
        show(relatedTarget) {
            if (this._isShown || this._isTransitioning) {
                return;
            }
            const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$4, {
                relatedTarget
            });
            if (showEvent.defaultPrevented) {
                return;
            }
            this._isShown = true;
            this._isTransitioning = true;
            this._scrollBar.hide();
            document.body.classList.add(CLASS_NAME_OPEN);
            this._adjustDialog();
            this._backdrop.show(() => this._showElement(relatedTarget));
        }
        hide() {
            if (!this._isShown || this._isTransitioning) {
                return;
            }
            const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$4);
            if (hideEvent.defaultPrevented) {
                return;
            }
            this._isShown = false;
            this._isTransitioning = true;
            this._focustrap.deactivate();
            this._element.classList.remove(CLASS_NAME_SHOW$4);
            this._queueCallback(() => this._hideModal(), this._element, this._isAnimated());
        }
        dispose() {
            EventHandler.off(window, EVENT_KEY$4);
            EventHandler.off(this._dialog, EVENT_KEY$4);
            this._backdrop.dispose();
            this._focustrap.deactivate();
            super.dispose();
        }
        handleUpdate() {
            this._adjustDialog();
        }

        // Private
        _initializeBackDrop() {
            return new Backdrop({
                isVisible: Boolean(this._config.backdrop),
                // 'static' option will be translated to true, and booleans will keep their value,
                isAnimated: this._isAnimated()
            });
        }
        _initializeFocusTrap() {
            return new FocusTrap({
                trapElement: this._element
            });
        }
        _showElement(relatedTarget) {
            // try to append dynamic modal
            if (!document.body.contains(this._element)) {
                document.body.append(this._element);
            }
            this._element.style.display = 'block';
            this._element.removeAttribute('aria-hidden');
            this._element.setAttribute('aria-modal', true);
            this._element.setAttribute('role', 'dialog');
            this._element.scrollTop = 0;
            const modalBody = SelectorEngine.findOne(SELECTOR_MODAL_BODY, this._dialog);
            if (modalBody) {
                modalBody.scrollTop = 0;
            }
            reflow(this._element);
            this._element.classList.add(CLASS_NAME_SHOW$4);
            const transitionComplete = () => {
                if (this._config.focus) {
                    this._focustrap.activate();
                }
                this._isTransitioning = false;
                EventHandler.trigger(this._element, EVENT_SHOWN$4, {
                    relatedTarget
                });
            };
            this._queueCallback(transitionComplete, this._dialog, this._isAnimated());
        }
        _addEventListeners() {
            EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS$1, event => {
                if (event.key !== ESCAPE_KEY$1) {
                    return;
                }
                if (this._config.keyboard) {
                    this.hide();
                    return;
                }
                this._triggerBackdropTransition();
            });
            EventHandler.on(window, EVENT_RESIZE$1, () => {
                if (this._isShown && !this._isTransitioning) {
                    this._adjustDialog();
                }
            });
            EventHandler.on(this._element, EVENT_MOUSEDOWN_DISMISS, event => {
                // a bad trick to segregate clicks that may start inside dialog but end outside, and avoid listen to scrollbar clicks
                EventHandler.one(this._element, EVENT_CLICK_DISMISS, event2 => {
                    if (this._element !== event.target || this._element !== event2.target) {
                        return;
                    }
                    if (this._config.backdrop === 'static') {
                        this._triggerBackdropTransition();
                        return;
                    }
                    if (this._config.backdrop) {
                        this.hide();
                    }
                });
            });
        }
        _hideModal() {
            this._element.style.display = 'none';
            this._element.setAttribute('aria-hidden', true);
            this._element.removeAttribute('aria-modal');
            this._element.removeAttribute('role');
            this._isTransitioning = false;
            this._backdrop.hide(() => {
                document.body.classList.remove(CLASS_NAME_OPEN);
                this._resetAdjustments();
                this._scrollBar.reset();
                EventHandler.trigger(this._element, EVENT_HIDDEN$4);
            });
        }
        _isAnimated() {
            return this._element.classList.contains(CLASS_NAME_FADE$3);
        }
        _triggerBackdropTransition() {
            const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED$1);
            if (hideEvent.defaultPrevented) {
                return;
            }
            const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
            const initialOverflowY = this._element.style.overflowY;
            // return if the following background transition hasn't yet completed
            if (initialOverflowY === 'hidden' || this._element.classList.contains(CLASS_NAME_STATIC)) {
                return;
            }
            if (!isModalOverflowing) {
                this._element.style.overflowY = 'hidden';
            }
            this._element.classList.add(CLASS_NAME_STATIC);
            this._queueCallback(() => {
                this._element.classList.remove(CLASS_NAME_STATIC);
                this._queueCallback(() => {
                    this._element.style.overflowY = initialOverflowY;
                }, this._dialog);
            }, this._dialog);
            this._element.focus();
        }

        /**
         * The following methods are used to handle overflowing modals
         */

        _adjustDialog() {
            const isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
            const scrollbarWidth = this._scrollBar.getWidth();
            const isBodyOverflowing = scrollbarWidth > 0;
            if (isBodyOverflowing && !isModalOverflowing) {
                const property = isRTL() ? 'paddingLeft' : 'paddingRight';
                this._element.style[property] = `${scrollbarWidth}px`;
            }
            if (!isBodyOverflowing && isModalOverflowing) {
                const property = isRTL() ? 'paddingRight' : 'paddingLeft';
                this._element.style[property] = `${scrollbarWidth}px`;
            }
        }
        _resetAdjustments() {
            this._element.style.paddingLeft = '';
            this._element.style.paddingRight = '';
        }

        // Static
        static jQueryInterface(config, relatedTarget) {
            return this.each(function() {
                const data = Modal.getOrCreateInstance(this, config);
                if (typeof config !== 'string') {
                    return;
                }
                if (typeof data[config] === 'undefined') {
                    throw new TypeError(`No method named "${config}"`);
                }
                data[config](relatedTarget);
            });
        }
    }

    /**
     * Data API implementation
     */

    EventHandler.on(document, EVENT_CLICK_DATA_API$2, SELECTOR_DATA_TOGGLE$2, function(event) {
        const target = SelectorEngine.getElementFromSelector(this);
        if (['A', 'AREA'].includes(this.tagName)) {
            event.preventDefault();
        }
        EventHandler.one(target, EVENT_SHOW$4, showEvent => {
            if (showEvent.defaultPrevented) {
                // only register focus restorer if modal will actually get shown
                return;
            }
            EventHandler.one(target, EVENT_HIDDEN$4, () => {
                if (isVisible(this)) {
                    this.focus();
                }
            });
        });

        // avoid conflict when clicking modal toggler while another one is open
        const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR$1);
        if (alreadyOpen) {
            Modal.getInstance(alreadyOpen).hide();
        }
        const data = Modal.getOrCreateInstance(target);
        data.toggle(this);
    });
    enableDismissTrigger(Modal);

    /**
     * jQuery
     */

    defineJQueryPlugin(Modal);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap offcanvas.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$6 = 'offcanvas';
    const DATA_KEY$3 = 'bs.offcanvas';
    const EVENT_KEY$3 = `.${DATA_KEY$3}`;
    const DATA_API_KEY$1 = '.data-api';
    const EVENT_LOAD_DATA_API$2 = `load${EVENT_KEY$3}${DATA_API_KEY$1}`;
    const ESCAPE_KEY = 'Escape';
    const CLASS_NAME_SHOW$3 = 'show';
    const CLASS_NAME_SHOWING$1 = 'showing';
    const CLASS_NAME_HIDING = 'hiding';
    const CLASS_NAME_BACKDROP = 'offcanvas-backdrop';
    const OPEN_SELECTOR = '.offcanvas.show';
    const EVENT_SHOW$3 = `show${EVENT_KEY$3}`;
    const EVENT_SHOWN$3 = `shown${EVENT_KEY$3}`;
    const EVENT_HIDE$3 = `hide${EVENT_KEY$3}`;
    const EVENT_HIDE_PREVENTED = `hidePrevented${EVENT_KEY$3}`;
    const EVENT_HIDDEN$3 = `hidden${EVENT_KEY$3}`;
    const EVENT_RESIZE = `resize${EVENT_KEY$3}`;
    const EVENT_CLICK_DATA_API$1 = `click${EVENT_KEY$3}${DATA_API_KEY$1}`;
    const EVENT_KEYDOWN_DISMISS = `keydown.dismiss${EVENT_KEY$3}`;
    const SELECTOR_DATA_TOGGLE$1 = '[data-bs-toggle="offcanvas"]';
    const Default$5 = {
        backdrop: true,
        keyboard: true,
        scroll: false
    };
    const DefaultType$5 = {
        backdrop: '(boolean|string)',
        keyboard: 'boolean',
        scroll: 'boolean'
    };

    /**
     * Class definition
     */

    class Offcanvas extends BaseComponent {
        constructor(element, config) {
            super(element, config);
            this._isShown = false;
            this._backdrop = this._initializeBackDrop();
            this._focustrap = this._initializeFocusTrap();
            this._addEventListeners();
        }

        // Getters
        static get Default() {
            return Default$5;
        }
        static get DefaultType() {
            return DefaultType$5;
        }
        static get NAME() {
            return NAME$6;
        }

        // Public
        toggle(relatedTarget) {
            return this._isShown ? this.hide() : this.show(relatedTarget);
        }
        show(relatedTarget) {
            if (this._isShown) {
                return;
            }
            const showEvent = EventHandler.trigger(this._element, EVENT_SHOW$3, {
                relatedTarget
            });
            if (showEvent.defaultPrevented) {
                return;
            }
            this._isShown = true;
            this._backdrop.show();
            if (!this._config.scroll) {
                new ScrollBarHelper().hide();
            }
            this._element.setAttribute('aria-modal', true);
            this._element.setAttribute('role', 'dialog');
            this._element.classList.add(CLASS_NAME_SHOWING$1);
            const completeCallBack = () => {
                if (!this._config.scroll || this._config.backdrop) {
                    this._focustrap.activate();
                }
                this._element.classList.add(CLASS_NAME_SHOW$3);
                this._element.classList.remove(CLASS_NAME_SHOWING$1);
                EventHandler.trigger(this._element, EVENT_SHOWN$3, {
                    relatedTarget
                });
            };
            this._queueCallback(completeCallBack, this._element, true);
        }
        hide() {
            if (!this._isShown) {
                return;
            }
            const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE$3);
            if (hideEvent.defaultPrevented) {
                return;
            }
            this._focustrap.deactivate();
            this._element.blur();
            this._isShown = false;
            this._element.classList.add(CLASS_NAME_HIDING);
            this._backdrop.hide();
            const completeCallback = () => {
                this._element.classList.remove(CLASS_NAME_SHOW$3, CLASS_NAME_HIDING);
                this._element.removeAttribute('aria-modal');
                this._element.removeAttribute('role');
                if (!this._config.scroll) {
                    new ScrollBarHelper().reset();
                }
                EventHandler.trigger(this._element, EVENT_HIDDEN$3);
            };
            this._queueCallback(completeCallback, this._element, true);
        }
        dispose() {
            this._backdrop.dispose();
            this._focustrap.deactivate();
            super.dispose();
        }

        // Private
        _initializeBackDrop() {
            const clickCallback = () => {
                if (this._config.backdrop === 'static') {
                    EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
                    return;
                }
                this.hide();
            };

            // 'static' option will be translated to true, and booleans will keep their value
            const isVisible = Boolean(this._config.backdrop);
            return new Backdrop({
                className: CLASS_NAME_BACKDROP,
                isVisible,
                isAnimated: true,
                rootElement: this._element.parentNode,
                clickCallback: isVisible ? clickCallback : null
            });
        }
        _initializeFocusTrap() {
            return new FocusTrap({
                trapElement: this._element
            });
        }
        _addEventListeners() {
            EventHandler.on(this._element, EVENT_KEYDOWN_DISMISS, event => {
                if (event.key !== ESCAPE_KEY) {
                    return;
                }
                if (this._config.keyboard) {
                    this.hide();
                    return;
                }
                EventHandler.trigger(this._element, EVENT_HIDE_PREVENTED);
            });
        }

        // Static
        static jQueryInterface(config) {
            return this.each(function() {
                const data = Offcanvas.getOrCreateInstance(this, config);
                if (typeof config !== 'string') {
                    return;
                }
                if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
                    throw new TypeError(`No method named "${config}"`);
                }
                data[config](this);
            });
        }
    }

    /**
     * Data API implementation
     */

    EventHandler.on(document, EVENT_CLICK_DATA_API$1, SELECTOR_DATA_TOGGLE$1, function(event) {
        const target = SelectorEngine.getElementFromSelector(this);
        if (['A', 'AREA'].includes(this.tagName)) {
            event.preventDefault();
        }
        if (isDisabled(this)) {
            return;
        }
        EventHandler.one(target, EVENT_HIDDEN$3, () => {
            // focus on trigger when it is closed
            if (isVisible(this)) {
                this.focus();
            }
        });

        // avoid conflict when clicking a toggler of an offcanvas, while another is open
        const alreadyOpen = SelectorEngine.findOne(OPEN_SELECTOR);
        if (alreadyOpen && alreadyOpen !== target) {
            Offcanvas.getInstance(alreadyOpen).hide();
        }
        const data = Offcanvas.getOrCreateInstance(target);
        data.toggle(this);
    });
    EventHandler.on(window, EVENT_LOAD_DATA_API$2, () => {
        for (const selector of SelectorEngine.find(OPEN_SELECTOR)) {
            Offcanvas.getOrCreateInstance(selector).show();
        }
    });
    EventHandler.on(window, EVENT_RESIZE, () => {
        for (const element of SelectorEngine.find('[aria-modal][class*=show][class*=offcanvas-]')) {
            if (getComputedStyle(element).position !== 'fixed') {
                Offcanvas.getOrCreateInstance(element).hide();
            }
        }
    });
    enableDismissTrigger(Offcanvas);

    /**
     * jQuery
     */

    defineJQueryPlugin(Offcanvas);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap util/sanitizer.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */

    // js-docs-start allow-list
    const ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
    const DefaultAllowlist = {
        // Global attributes allowed on any supplied element below.
        '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
        a: ['target', 'href', 'title', 'rel'],
        area: [],
        b: [],
        br: [],
        col: [],
        code: [],
        dd: [],
        div: [],
        dl: [],
        dt: [],
        em: [],
        hr: [],
        h1: [],
        h2: [],
        h3: [],
        h4: [],
        h5: [],
        h6: [],
        i: [],
        img: ['src', 'srcset', 'alt', 'title', 'width', 'height'],
        li: [],
        ol: [],
        p: [],
        pre: [],
        s: [],
        small: [],
        span: [],
        sub: [],
        sup: [],
        strong: [],
        u: [],
        ul: []
    };
    // js-docs-end allow-list

    const uriAttributes = new Set(['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']);

    /**
     * A pattern that recognizes URLs that are safe wrt. XSS in URL navigation
     * contexts.
     *
     * Shout-out to Angular https://github.com/angular/angular/blob/15.2.8/packages/core/src/sanitization/url_sanitizer.ts#L38
     */
    const SAFE_URL_PATTERN = /^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i;
    const allowedAttribute = (attribute, allowedAttributeList) => {
        const attributeName = attribute.nodeName.toLowerCase();
        if (allowedAttributeList.includes(attributeName)) {
            if (uriAttributes.has(attributeName)) {
                return Boolean(SAFE_URL_PATTERN.test(attribute.nodeValue));
            }
            return true;
        }

        // Check if a regular expression validates the attribute.
        return allowedAttributeList.filter(attributeRegex => attributeRegex instanceof RegExp).some(regex => regex.test(attributeName));
    };

    function sanitizeHtml(unsafeHtml, allowList, sanitizeFunction) {
        if (!unsafeHtml.length) {
            return unsafeHtml;
        }
        if (sanitizeFunction && typeof sanitizeFunction === 'function') {
            return sanitizeFunction(unsafeHtml);
        }
        const domParser = new window.DOMParser();
        const createdDocument = domParser.parseFromString(unsafeHtml, 'text/html');
        const elements = [].concat(...createdDocument.body.querySelectorAll('*'));
        for (const element of elements) {
            const elementName = element.nodeName.toLowerCase();
            if (!Object.keys(allowList).includes(elementName)) {
                element.remove();
                continue;
            }
            const attributeList = [].concat(...element.attributes);
            const allowedAttributes = [].concat(allowList['*'] || [], allowList[elementName] || []);
            for (const attribute of attributeList) {
                if (!allowedAttribute(attribute, allowedAttributes)) {
                    element.removeAttribute(attribute.nodeName);
                }
            }
        }
        return createdDocument.body.innerHTML;
    }

    /**
     * --------------------------------------------------------------------------
     * Bootstrap util/template-factory.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$5 = 'TemplateFactory';
    const Default$4 = {
        allowList: DefaultAllowlist,
        content: {},
        // { selector : text ,  selector2 : text2 , }
        extraClass: '',
        html: false,
        sanitize: true,
        sanitizeFn: null,
        template: '<div></div>'
    };
    const DefaultType$4 = {
        allowList: 'object',
        content: 'object',
        extraClass: '(string|function)',
        html: 'boolean',
        sanitize: 'boolean',
        sanitizeFn: '(null|function)',
        template: 'string'
    };
    const DefaultContentType = {
        entry: '(string|element|function|null)',
        selector: '(string|element)'
    };

    /**
     * Class definition
     */

    class TemplateFactory extends Config {
        constructor(config) {
            super();
            this._config = this._getConfig(config);
        }

        // Getters
        static get Default() {
            return Default$4;
        }
        static get DefaultType() {
            return DefaultType$4;
        }
        static get NAME() {
            return NAME$5;
        }

        // Public
        getContent() {
            return Object.values(this._config.content).map(config => this._resolvePossibleFunction(config)).filter(Boolean);
        }
        hasContent() {
            return this.getContent().length > 0;
        }
        changeContent(content) {
            this._checkContent(content);
            this._config.content = {
                ...this._config.content,
                ...content
            };
            return this;
        }
        toHtml() {
            const templateWrapper = document.createElement('div');
            templateWrapper.innerHTML = this._maybeSanitize(this._config.template);
            for (const [selector, text] of Object.entries(this._config.content)) {
                this._setContent(templateWrapper, text, selector);
            }
            const template = templateWrapper.children[0];
            const extraClass = this._resolvePossibleFunction(this._config.extraClass);
            if (extraClass) {
                template.classList.add(...extraClass.split(' '));
            }
            return template;
        }

        // Private
        _typeCheckConfig(config) {
            super._typeCheckConfig(config);
            this._checkContent(config.content);
        }
        _checkContent(arg) {
            for (const [selector, content] of Object.entries(arg)) {
                super._typeCheckConfig({
                    selector,
                    entry: content
                }, DefaultContentType);
            }
        }
        _setContent(template, content, selector) {
            const templateElement = SelectorEngine.findOne(selector, template);
            if (!templateElement) {
                return;
            }
            content = this._resolvePossibleFunction(content);
            if (!content) {
                templateElement.remove();
                return;
            }
            if (isElement(content)) {
                this._putElementInTemplate(getElement(content), templateElement);
                return;
            }
            if (this._config.html) {
                templateElement.innerHTML = this._maybeSanitize(content);
                return;
            }
            templateElement.textContent = content;
        }
        _maybeSanitize(arg) {
            return this._config.sanitize ? sanitizeHtml(arg, this._config.allowList, this._config.sanitizeFn) : arg;
        }
        _resolvePossibleFunction(arg) {
            return execute(arg, [undefined, this]);
        }
        _putElementInTemplate(element, templateElement) {
            if (this._config.html) {
                templateElement.innerHTML = '';
                templateElement.append(element);
                return;
            }
            templateElement.textContent = element.textContent;
        }
    }

    /**
     * --------------------------------------------------------------------------
     * Bootstrap tooltip.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$4 = 'tooltip';
    const DISALLOWED_ATTRIBUTES = new Set(['sanitize', 'allowList', 'sanitizeFn']);
    const CLASS_NAME_FADE$2 = 'fade';
    const CLASS_NAME_MODAL = 'modal';
    const CLASS_NAME_SHOW$2 = 'show';
    const SELECTOR_TOOLTIP_INNER = '.tooltip-inner';
    const SELECTOR_MODAL = `.${CLASS_NAME_MODAL}`;
    const EVENT_MODAL_HIDE = 'hide.bs.modal';
    const TRIGGER_HOVER = 'hover';
    const TRIGGER_FOCUS = 'focus';
    const TRIGGER_CLICK = 'click';
    const TRIGGER_MANUAL = 'manual';
    const EVENT_HIDE$2 = 'hide';
    const EVENT_HIDDEN$2 = 'hidden';
    const EVENT_SHOW$2 = 'show';
    const EVENT_SHOWN$2 = 'shown';
    const EVENT_INSERTED = 'inserted';
    const EVENT_CLICK$1 = 'click';
    const EVENT_FOCUSIN$1 = 'focusin';
    const EVENT_FOCUSOUT$1 = 'focusout';
    const EVENT_MOUSEENTER = 'mouseenter';
    const EVENT_MOUSELEAVE = 'mouseleave';
    const AttachmentMap = {
        AUTO: 'auto',
        TOP: 'top',
        RIGHT: isRTL() ? 'left' : 'right',
        BOTTOM: 'bottom',
        LEFT: isRTL() ? 'right' : 'left'
    };
    const Default$3 = {
        allowList: DefaultAllowlist,
        animation: true,
        boundary: 'clippingParents',
        container: false,
        customClass: '',
        delay: 0,
        fallbackPlacements: ['top', 'right', 'bottom', 'left'],
        html: false,
        offset: [0, 6],
        placement: 'top',
        popperConfig: null,
        sanitize: true,
        sanitizeFn: null,
        selector: false,
        template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-arrow"></div>' + '<div class="tooltip-inner"></div>' + '</div>',
        title: '',
        trigger: 'hover focus'
    };
    const DefaultType$3 = {
        allowList: 'object',
        animation: 'boolean',
        boundary: '(string|element)',
        container: '(string|element|boolean)',
        customClass: '(string|function)',
        delay: '(number|object)',
        fallbackPlacements: 'array',
        html: 'boolean',
        offset: '(array|string|function)',
        placement: '(string|function)',
        popperConfig: '(null|object|function)',
        sanitize: 'boolean',
        sanitizeFn: '(null|function)',
        selector: '(string|boolean)',
        template: 'string',
        title: '(string|element|function)',
        trigger: 'string'
    };

    /**
     * Class definition
     */

    class Tooltip extends BaseComponent {
        constructor(element, config) {
            if (typeof Popper__namespace === 'undefined') {
                throw new TypeError('Bootstrap\'s tooltips require Popper (https://popper.js.org/docs/v2/)');
            }
            super(element, config);

            // Private
            this._isEnabled = true;
            this._timeout = 0;
            this._isHovered = null;
            this._activeTrigger = {};
            this._popper = null;
            this._templateFactory = null;
            this._newContent = null;

            // Protected
            this.tip = null;
            this._setListeners();
            if (!this._config.selector) {
                this._fixTitle();
            }
        }

        // Getters
        static get Default() {
            return Default$3;
        }
        static get DefaultType() {
            return DefaultType$3;
        }
        static get NAME() {
            return NAME$4;
        }

        // Public
        enable() {
            this._isEnabled = true;
        }
        disable() {
            this._isEnabled = false;
        }
        toggleEnabled() {
            this._isEnabled = !this._isEnabled;
        }
        toggle() {
            if (!this._isEnabled) {
                return;
            }
            if (this._isShown()) {
                this._leave();
                return;
            }
            this._enter();
        }
        dispose() {
            clearTimeout(this._timeout);
            EventHandler.off(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
            if (this._element.getAttribute('data-bs-original-title')) {
                this._element.setAttribute('title', this._element.getAttribute('data-bs-original-title'));
            }
            this._disposePopper();
            super.dispose();
        }
        show() {
            if (this._element.style.display === 'none') {
                throw new Error('Please use show on visible elements');
            }
            if (!(this._isWithContent() && this._isEnabled)) {
                return;
            }
            const showEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOW$2));
            const shadowRoot = findShadowRoot(this._element);
            const isInTheDom = (shadowRoot || this._element.ownerDocument.documentElement).contains(this._element);
            if (showEvent.defaultPrevented || !isInTheDom) {
                return;
            }

            // TODO: v6 remove this or make it optional
            this._disposePopper();
            const tip = this._getTipElement();
            this._element.setAttribute('aria-describedby', tip.getAttribute('id'));
            const {
                container
            } = this._config;
            if (!this._element.ownerDocument.documentElement.contains(this.tip)) {
                container.append(tip);
                EventHandler.trigger(this._element, this.constructor.eventName(EVENT_INSERTED));
            }
            this._popper = this._createPopper(tip);
            tip.classList.add(CLASS_NAME_SHOW$2);

            // If this is a touch-enabled device we add extra
            // empty mouseover listeners to the body's immediate children;
            // only needed because of broken event delegation on iOS
            // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
            if ('ontouchstart' in document.documentElement) {
                for (const element of [].concat(...document.body.children)) {
                    EventHandler.on(element, 'mouseover', noop);
                }
            }
            const complete = () => {
                EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN$2));
                if (this._isHovered === false) {
                    this._leave();
                }
                this._isHovered = false;
            };
            this._queueCallback(complete, this.tip, this._isAnimated());
        }
        hide() {
            if (!this._isShown()) {
                return;
            }
            const hideEvent = EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDE$2));
            if (hideEvent.defaultPrevented) {
                return;
            }
            const tip = this._getTipElement();
            tip.classList.remove(CLASS_NAME_SHOW$2);

            // If this is a touch-enabled device we remove the extra
            // empty mouseover listeners we added for iOS support
            if ('ontouchstart' in document.documentElement) {
                for (const element of [].concat(...document.body.children)) {
                    EventHandler.off(element, 'mouseover', noop);
                }
            }
            this._activeTrigger[TRIGGER_CLICK] = false;
            this._activeTrigger[TRIGGER_FOCUS] = false;
            this._activeTrigger[TRIGGER_HOVER] = false;
            this._isHovered = null; // it is a trick to support manual triggering

            const complete = () => {
                if (this._isWithActiveTrigger()) {
                    return;
                }
                if (!this._isHovered) {
                    this._disposePopper();
                }
                this._element.removeAttribute('aria-describedby');
                EventHandler.trigger(this._element, this.constructor.eventName(EVENT_HIDDEN$2));
            };
            this._queueCallback(complete, this.tip, this._isAnimated());
        }
        update() {
            if (this._popper) {
                this._popper.update();
            }
        }

        // Protected
        _isWithContent() {
            return Boolean(this._getTitle());
        }
        _getTipElement() {
            if (!this.tip) {
                this.tip = this._createTipElement(this._newContent || this._getContentForTemplate());
            }
            return this.tip;
        }
        _createTipElement(content) {
            const tip = this._getTemplateFactory(content).toHtml();

            // TODO: remove this check in v6
            if (!tip) {
                return null;
            }
            tip.classList.remove(CLASS_NAME_FADE$2, CLASS_NAME_SHOW$2);
            // TODO: v6 the following can be achieved with CSS only
            tip.classList.add(`bs-${this.constructor.NAME}-auto`);
            const tipId = getUID(this.constructor.NAME).toString();
            tip.setAttribute('id', tipId);
            if (this._isAnimated()) {
                tip.classList.add(CLASS_NAME_FADE$2);
            }
            return tip;
        }
        setContent(content) {
            this._newContent = content;
            if (this._isShown()) {
                this._disposePopper();
                this.show();
            }
        }
        _getTemplateFactory(content) {
            if (this._templateFactory) {
                this._templateFactory.changeContent(content);
            } else {
                this._templateFactory = new TemplateFactory({
                    ...this._config,
                    // the `content` var has to be after `this._config`
                    // to override config.content in case of popover
                    content,
                    extraClass: this._resolvePossibleFunction(this._config.customClass)
                });
            }
            return this._templateFactory;
        }
        _getContentForTemplate() {
            return {
                [SELECTOR_TOOLTIP_INNER]: this._getTitle()
            };
        }
        _getTitle() {
            return this._resolvePossibleFunction(this._config.title) || this._element.getAttribute('data-bs-original-title');
        }

        // Private
        _initializeOnDelegatedTarget(event) {
            return this.constructor.getOrCreateInstance(event.delegateTarget, this._getDelegateConfig());
        }
        _isAnimated() {
            return this._config.animation || this.tip && this.tip.classList.contains(CLASS_NAME_FADE$2);
        }
        _isShown() {
            return this.tip && this.tip.classList.contains(CLASS_NAME_SHOW$2);
        }
        _createPopper(tip) {
            const placement = execute(this._config.placement, [this, tip, this._element]);
            const attachment = AttachmentMap[placement.toUpperCase()];
            return Popper__namespace.createPopper(this._element, tip, this._getPopperConfig(attachment));
        }
        _getOffset() {
            const {
                offset
            } = this._config;
            if (typeof offset === 'string') {
                return offset.split(',').map(value => Number.parseInt(value, 10));
            }
            if (typeof offset === 'function') {
                return popperData => offset(popperData, this._element);
            }
            return offset;
        }
        _resolvePossibleFunction(arg) {
            return execute(arg, [this._element, this._element]);
        }
        _getPopperConfig(attachment) {
            const defaultBsPopperConfig = {
                placement: attachment,
                modifiers: [{
                    name: 'flip',
                    options: {
                        fallbackPlacements: this._config.fallbackPlacements
                    }
                }, {
                    name: 'offset',
                    options: {
                        offset: this._getOffset()
                    }
                }, {
                    name: 'preventOverflow',
                    options: {
                        boundary: this._config.boundary
                    }
                }, {
                    name: 'arrow',
                    options: {
                        element: `.${this.constructor.NAME}-arrow`
                    }
                }, {
                    name: 'preSetPlacement',
                    enabled: true,
                    phase: 'beforeMain',
                    fn: data => {
                        // Pre-set Popper's placement attribute in order to read the arrow sizes properly.
                        // Otherwise, Popper mixes up the width and height dimensions since the initial arrow style is for top placement
                        this._getTipElement().setAttribute('data-popper-placement', data.state.placement);
                    }
                }]
            };
            return {
                ...defaultBsPopperConfig,
                ...execute(this._config.popperConfig, [undefined, defaultBsPopperConfig])
            };
        }
        _setListeners() {
            const triggers = this._config.trigger.split(' ');
            for (const trigger of triggers) {
                if (trigger === 'click') {
                    EventHandler.on(this._element, this.constructor.eventName(EVENT_CLICK$1), this._config.selector, event => {
                        const context = this._initializeOnDelegatedTarget(event);
                        context._activeTrigger[TRIGGER_CLICK] = !(context._isShown() && context._activeTrigger[TRIGGER_CLICK]);
                        context.toggle();
                    });
                } else if (trigger !== TRIGGER_MANUAL) {
                    const eventIn = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSEENTER) : this.constructor.eventName(EVENT_FOCUSIN$1);
                    const eventOut = trigger === TRIGGER_HOVER ? this.constructor.eventName(EVENT_MOUSELEAVE) : this.constructor.eventName(EVENT_FOCUSOUT$1);
                    EventHandler.on(this._element, eventIn, this._config.selector, event => {
                        const context = this._initializeOnDelegatedTarget(event);
                        context._activeTrigger[event.type === 'focusin' ? TRIGGER_FOCUS : TRIGGER_HOVER] = true;
                        context._enter();
                    });
                    EventHandler.on(this._element, eventOut, this._config.selector, event => {
                        const context = this._initializeOnDelegatedTarget(event);
                        context._activeTrigger[event.type === 'focusout' ? TRIGGER_FOCUS : TRIGGER_HOVER] = context._element.contains(event.relatedTarget);
                        context._leave();
                    });
                }
            }
            this._hideModalHandler = () => {
                if (this._element) {
                    this.hide();
                }
            };
            EventHandler.on(this._element.closest(SELECTOR_MODAL), EVENT_MODAL_HIDE, this._hideModalHandler);
        }
        _fixTitle() {
            const title = this._element.getAttribute('title');
            if (!title) {
                return;
            }
            if (!this._element.getAttribute('aria-label') && !this._element.textContent.trim()) {
                this._element.setAttribute('aria-label', title);
            }
            this._element.setAttribute('data-bs-original-title', title); // DO NOT USE IT. Is only for backwards compatibility
            this._element.removeAttribute('title');
        }
        _enter() {
            if (this._isShown() || this._isHovered) {
                this._isHovered = true;
                return;
            }
            this._isHovered = true;
            this._setTimeout(() => {
                if (this._isHovered) {
                    this.show();
                }
            }, this._config.delay.show);
        }
        _leave() {
            if (this._isWithActiveTrigger()) {
                return;
            }
            this._isHovered = false;
            this._setTimeout(() => {
                if (!this._isHovered) {
                    this.hide();
                }
            }, this._config.delay.hide);
        }
        _setTimeout(handler, timeout) {
            clearTimeout(this._timeout);
            this._timeout = setTimeout(handler, timeout);
        }
        _isWithActiveTrigger() {
            return Object.values(this._activeTrigger).includes(true);
        }
        _getConfig(config) {
            const dataAttributes = Manipulator.getDataAttributes(this._element);
            for (const dataAttribute of Object.keys(dataAttributes)) {
                if (DISALLOWED_ATTRIBUTES.has(dataAttribute)) {
                    delete dataAttributes[dataAttribute];
                }
            }
            config = {
                ...dataAttributes,
                ...(typeof config === 'object' && config ? config : {})
            };
            config = this._mergeConfigObj(config);
            config = this._configAfterMerge(config);
            this._typeCheckConfig(config);
            return config;
        }
        _configAfterMerge(config) {
            config.container = config.container === false ? document.body : getElement(config.container);
            if (typeof config.delay === 'number') {
                config.delay = {
                    show: config.delay,
                    hide: config.delay
                };
            }
            if (typeof config.title === 'number') {
                config.title = config.title.toString();
            }
            if (typeof config.content === 'number') {
                config.content = config.content.toString();
            }
            return config;
        }
        _getDelegateConfig() {
            const config = {};
            for (const [key, value] of Object.entries(this._config)) {
                if (this.constructor.Default[key] !== value) {
                    config[key] = value;
                }
            }
            config.selector = false;
            config.trigger = 'manual';

            // In the future can be replaced with:
            // const keysWithDifferentValues = Object.entries(this._config).filter(entry => this.constructor.Default[entry[0]] !== this._config[entry[0]])
            // `Object.fromEntries(keysWithDifferentValues)`
            return config;
        }
        _disposePopper() {
            if (this._popper) {
                this._popper.destroy();
                this._popper = null;
            }
            if (this.tip) {
                this.tip.remove();
                this.tip = null;
            }
        }

        // Static
        static jQueryInterface(config) {
            return this.each(function() {
                const data = Tooltip.getOrCreateInstance(this, config);
                if (typeof config !== 'string') {
                    return;
                }
                if (typeof data[config] === 'undefined') {
                    throw new TypeError(`No method named "${config}"`);
                }
                data[config]();
            });
        }
    }

    /**
     * jQuery
     */

    defineJQueryPlugin(Tooltip);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap popover.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$3 = 'popover';
    const SELECTOR_TITLE = '.popover-header';
    const SELECTOR_CONTENT = '.popover-body';
    const Default$2 = {
        ...Tooltip.Default,
        content: '',
        offset: [0, 8],
        placement: 'right',
        template: '<div class="popover" role="tooltip">' + '<div class="popover-arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div>' + '</div>',
        trigger: 'click'
    };
    const DefaultType$2 = {
        ...Tooltip.DefaultType,
        content: '(null|string|element|function)'
    };

    /**
     * Class definition
     */

    class Popover extends Tooltip {
        // Getters
        static get Default() {
            return Default$2;
        }
        static get DefaultType() {
            return DefaultType$2;
        }
        static get NAME() {
            return NAME$3;
        }

        // Overrides
        _isWithContent() {
            return this._getTitle() || this._getContent();
        }

        // Private
        _getContentForTemplate() {
            return {
                [SELECTOR_TITLE]: this._getTitle(),
                [SELECTOR_CONTENT]: this._getContent()
            };
        }
        _getContent() {
            return this._resolvePossibleFunction(this._config.content);
        }

        // Static
        static jQueryInterface(config) {
            return this.each(function() {
                const data = Popover.getOrCreateInstance(this, config);
                if (typeof config !== 'string') {
                    return;
                }
                if (typeof data[config] === 'undefined') {
                    throw new TypeError(`No method named "${config}"`);
                }
                data[config]();
            });
        }
    }

    /**
     * jQuery
     */

    defineJQueryPlugin(Popover);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap scrollspy.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$2 = 'scrollspy';
    const DATA_KEY$2 = 'bs.scrollspy';
    const EVENT_KEY$2 = `.${DATA_KEY$2}`;
    const DATA_API_KEY = '.data-api';
    const EVENT_ACTIVATE = `activate${EVENT_KEY$2}`;
    const EVENT_CLICK = `click${EVENT_KEY$2}`;
    const EVENT_LOAD_DATA_API$1 = `load${EVENT_KEY$2}${DATA_API_KEY}`;
    const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item';
    const CLASS_NAME_ACTIVE$1 = 'active';
    const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]';
    const SELECTOR_TARGET_LINKS = '[href]';
    const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group';
    const SELECTOR_NAV_LINKS = '.nav-link';
    const SELECTOR_NAV_ITEMS = '.nav-item';
    const SELECTOR_LIST_ITEMS = '.list-group-item';
    const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`;
    const SELECTOR_DROPDOWN = '.dropdown';
    const SELECTOR_DROPDOWN_TOGGLE$1 = '.dropdown-toggle';
    const Default$1 = {
        offset: null,
        // TODO: v6 @deprecated, keep it for backwards compatibility reasons
        rootMargin: '0px 0px -25%',
        smoothScroll: false,
        target: null,
        threshold: [0.1, 0.5, 1]
    };
    const DefaultType$1 = {
        offset: '(number|null)',
        // TODO v6 @deprecated, keep it for backwards compatibility reasons
        rootMargin: 'string',
        smoothScroll: 'boolean',
        target: 'element',
        threshold: 'array'
    };

    /**
     * Class definition
     */

    class ScrollSpy extends BaseComponent {
        constructor(element, config) {
            super(element, config);

            // this._element is the observablesContainer and config.target the menu links wrapper
            this._targetLinks = new Map();
            this._observableSections = new Map();
            this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element;
            this._activeTarget = null;
            this._observer = null;
            this._previousScrollData = {
                visibleEntryTop: 0,
                parentScrollTop: 0
            };
            this.refresh(); // initialize
        }

        // Getters
        static get Default() {
            return Default$1;
        }
        static get DefaultType() {
            return DefaultType$1;
        }
        static get NAME() {
            return NAME$2;
        }

        // Public
        refresh() {
            this._initializeTargetsAndObservables();
            this._maybeEnableSmoothScroll();
            if (this._observer) {
                this._observer.disconnect();
            } else {
                this._observer = this._getNewObserver();
            }
            for (const section of this._observableSections.values()) {
                this._observer.observe(section);
            }
        }
        dispose() {
            this._observer.disconnect();
            super.dispose();
        }

        // Private
        _configAfterMerge(config) {
            // TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case
            config.target = getElement(config.target) || document.body;

            // TODO: v6 Only for backwards compatibility reasons. Use rootMargin only
            config.rootMargin = config.offset ? `${config.offset}px 0px -30%` : config.rootMargin;
            if (typeof config.threshold === 'string') {
                config.threshold = config.threshold.split(',').map(value => Number.parseFloat(value));
            }
            return config;
        }
        _maybeEnableSmoothScroll() {
            if (!this._config.smoothScroll) {
                return;
            }

            // unregister any previous listeners
            EventHandler.off(this._config.target, EVENT_CLICK);
            EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => {
                const observableSection = this._observableSections.get(event.target.hash);
                if (observableSection) {
                    event.preventDefault();
                    const root = this._rootElement || window;
                    const height = observableSection.offsetTop - this._element.offsetTop;
                    if (root.scrollTo) {
                        root.scrollTo({
                            top: height,
                            behavior: 'smooth'
                        });
                        return;
                    }

                    // Chrome 60 doesn't support `scrollTo`
                    root.scrollTop = height;
                }
            });
        }
        _getNewObserver() {
            const options = {
                root: this._rootElement,
                threshold: this._config.threshold,
                rootMargin: this._config.rootMargin
            };
            return new IntersectionObserver(entries => this._observerCallback(entries), options);
        }

        // The logic of selection
        _observerCallback(entries) {
            const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`);
            const activate = entry => {
                this._previousScrollData.visibleEntryTop = entry.target.offsetTop;
                this._process(targetElement(entry));
            };
            const parentScrollTop = (this._rootElement || document.documentElement).scrollTop;
            const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop;
            this._previousScrollData.parentScrollTop = parentScrollTop;
            for (const entry of entries) {
                if (!entry.isIntersecting) {
                    this._activeTarget = null;
                    this._clearActiveClass(targetElement(entry));
                    continue;
                }
                const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop;
                // if we are scrolling down, pick the bigger offsetTop
                if (userScrollsDown && entryIsLowerThanPrevious) {
                    activate(entry);
                    // if parent isn't scrolled, let's keep the first visible item, breaking the iteration
                    if (!parentScrollTop) {
                        return;
                    }
                    continue;
                }

                // if we are scrolling up, pick the smallest offsetTop
                if (!userScrollsDown && !entryIsLowerThanPrevious) {
                    activate(entry);
                }
            }
        }
        _initializeTargetsAndObservables() {
            this._targetLinks = new Map();
            this._observableSections = new Map();
            const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target);
            for (const anchor of targetLinks) {
                // ensure that the anchor has an id and is not disabled
                if (!anchor.hash || isDisabled(anchor)) {
                    continue;
                }
                const observableSection = SelectorEngine.findOne(decodeURI(anchor.hash), this._element);

                // ensure that the observableSection exists & is visible
                if (isVisible(observableSection)) {
                    this._targetLinks.set(decodeURI(anchor.hash), anchor);
                    this._observableSections.set(anchor.hash, observableSection);
                }
            }
        }
        _process(target) {
            if (this._activeTarget === target) {
                return;
            }
            this._clearActiveClass(this._config.target);
            this._activeTarget = target;
            target.classList.add(CLASS_NAME_ACTIVE$1);
            this._activateParents(target);
            EventHandler.trigger(this._element, EVENT_ACTIVATE, {
                relatedTarget: target
            });
        }
        _activateParents(target) {
            // Activate dropdown parents
            if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {
                SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE$1, target.closest(SELECTOR_DROPDOWN)).classList.add(CLASS_NAME_ACTIVE$1);
                return;
            }
            for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) {
                // Set triggered links parents as active
                // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
                for (const item of SelectorEngine.prev(listGroup, SELECTOR_LINK_ITEMS)) {
                    item.classList.add(CLASS_NAME_ACTIVE$1);
                }
            }
        }
        _clearActiveClass(parent) {
            parent.classList.remove(CLASS_NAME_ACTIVE$1);
            const activeNodes = SelectorEngine.find(`${SELECTOR_TARGET_LINKS}.${CLASS_NAME_ACTIVE$1}`, parent);
            for (const node of activeNodes) {
                node.classList.remove(CLASS_NAME_ACTIVE$1);
            }
        }

        // Static
        static jQueryInterface(config) {
            return this.each(function() {
                const data = ScrollSpy.getOrCreateInstance(this, config);
                if (typeof config !== 'string') {
                    return;
                }
                if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
                    throw new TypeError(`No method named "${config}"`);
                }
                data[config]();
            });
        }
    }

    /**
     * Data API implementation
     */

    EventHandler.on(window, EVENT_LOAD_DATA_API$1, () => {
        for (const spy of SelectorEngine.find(SELECTOR_DATA_SPY)) {
            ScrollSpy.getOrCreateInstance(spy);
        }
    });

    /**
     * jQuery
     */

    defineJQueryPlugin(ScrollSpy);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap tab.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME$1 = 'tab';
    const DATA_KEY$1 = 'bs.tab';
    const EVENT_KEY$1 = `.${DATA_KEY$1}`;
    const EVENT_HIDE$1 = `hide${EVENT_KEY$1}`;
    const EVENT_HIDDEN$1 = `hidden${EVENT_KEY$1}`;
    const EVENT_SHOW$1 = `show${EVENT_KEY$1}`;
    const EVENT_SHOWN$1 = `shown${EVENT_KEY$1}`;
    const EVENT_CLICK_DATA_API = `click${EVENT_KEY$1}`;
    const EVENT_KEYDOWN = `keydown${EVENT_KEY$1}`;
    const EVENT_LOAD_DATA_API = `load${EVENT_KEY$1}`;
    const ARROW_LEFT_KEY = 'ArrowLeft';
    const ARROW_RIGHT_KEY = 'ArrowRight';
    const ARROW_UP_KEY = 'ArrowUp';
    const ARROW_DOWN_KEY = 'ArrowDown';
    const HOME_KEY = 'Home';
    const END_KEY = 'End';
    const CLASS_NAME_ACTIVE = 'active';
    const CLASS_NAME_FADE$1 = 'fade';
    const CLASS_NAME_SHOW$1 = 'show';
    const CLASS_DROPDOWN = 'dropdown';
    const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle';
    const SELECTOR_DROPDOWN_MENU = '.dropdown-menu';
    const NOT_SELECTOR_DROPDOWN_TOGGLE = `:not(${SELECTOR_DROPDOWN_TOGGLE})`;
    const SELECTOR_TAB_PANEL = '.list-group, .nav, [role="tablist"]';
    const SELECTOR_OUTER = '.nav-item, .list-group-item';
    const SELECTOR_INNER = `.nav-link${NOT_SELECTOR_DROPDOWN_TOGGLE}, .list-group-item${NOT_SELECTOR_DROPDOWN_TOGGLE}, [role="tab"]${NOT_SELECTOR_DROPDOWN_TOGGLE}`;
    const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]'; // TODO: could only be `tab` in v6
    const SELECTOR_INNER_ELEM = `${SELECTOR_INNER}, ${SELECTOR_DATA_TOGGLE}`;
    const SELECTOR_DATA_TOGGLE_ACTIVE = `.${CLASS_NAME_ACTIVE}[data-bs-toggle="tab"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="pill"], .${CLASS_NAME_ACTIVE}[data-bs-toggle="list"]`;

    /**
     * Class definition
     */

    class Tab extends BaseComponent {
        constructor(element) {
            super(element);
            this._parent = this._element.closest(SELECTOR_TAB_PANEL);
            if (!this._parent) {
                return;
                // TODO: should throw exception in v6
                // throw new TypeError(`${element.outerHTML} has not a valid parent ${SELECTOR_INNER_ELEM}`)
            }

            // Set up initial aria attributes
            this._setInitialAttributes(this._parent, this._getChildren());
            EventHandler.on(this._element, EVENT_KEYDOWN, event => this._keydown(event));
        }

        // Getters
        static get NAME() {
            return NAME$1;
        }

        // Public
        show() {
            // Shows this elem and deactivate the active sibling if exists
            const innerElem = this._element;
            if (this._elemIsActive(innerElem)) {
                return;
            }

            // Search for active tab on same parent to deactivate it
            const active = this._getActiveElem();
            const hideEvent = active ? EventHandler.trigger(active, EVENT_HIDE$1, {
                relatedTarget: innerElem
            }) : null;
            const showEvent = EventHandler.trigger(innerElem, EVENT_SHOW$1, {
                relatedTarget: active
            });
            if (showEvent.defaultPrevented || hideEvent && hideEvent.defaultPrevented) {
                return;
            }
            this._deactivate(active, innerElem);
            this._activate(innerElem, active);
        }

        // Private
        _activate(element, relatedElem) {
            if (!element) {
                return;
            }
            element.classList.add(CLASS_NAME_ACTIVE);
            this._activate(SelectorEngine.getElementFromSelector(element)); // Search and activate/show the proper section

            const complete = () => {
                if (element.getAttribute('role') !== 'tab') {
                    element.classList.add(CLASS_NAME_SHOW$1);
                    return;
                }
                element.removeAttribute('tabindex');
                element.setAttribute('aria-selected', true);
                this._toggleDropDown(element, true);
                EventHandler.trigger(element, EVENT_SHOWN$1, {
                    relatedTarget: relatedElem
                });
            };
            this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE$1));
        }
        _deactivate(element, relatedElem) {
            if (!element) {
                return;
            }
            element.classList.remove(CLASS_NAME_ACTIVE);
            element.blur();
            this._deactivate(SelectorEngine.getElementFromSelector(element)); // Search and deactivate the shown section too

            const complete = () => {
                if (element.getAttribute('role') !== 'tab') {
                    element.classList.remove(CLASS_NAME_SHOW$1);
                    return;
                }
                element.setAttribute('aria-selected', false);
                element.setAttribute('tabindex', '-1');
                this._toggleDropDown(element, false);
                EventHandler.trigger(element, EVENT_HIDDEN$1, {
                    relatedTarget: relatedElem
                });
            };
            this._queueCallback(complete, element, element.classList.contains(CLASS_NAME_FADE$1));
        }
        _keydown(event) {
            if (![ARROW_LEFT_KEY, ARROW_RIGHT_KEY, ARROW_UP_KEY, ARROW_DOWN_KEY, HOME_KEY, END_KEY].includes(event.key)) {
                return;
            }
            event.stopPropagation(); // stopPropagation/preventDefault both added to support up/down keys without scrolling the page
            event.preventDefault();
            const children = this._getChildren().filter(element => !isDisabled(element));
            let nextActiveElement;
            if ([HOME_KEY, END_KEY].includes(event.key)) {
                nextActiveElement = children[event.key === HOME_KEY ? 0 : children.length - 1];
            } else {
                const isNext = [ARROW_RIGHT_KEY, ARROW_DOWN_KEY].includes(event.key);
                nextActiveElement = getNextActiveElement(children, event.target, isNext, true);
            }
            if (nextActiveElement) {
                nextActiveElement.focus({
                    preventScroll: true
                });
                Tab.getOrCreateInstance(nextActiveElement).show();
            }
        }
        _getChildren() {
            // collection of inner elements
            return SelectorEngine.find(SELECTOR_INNER_ELEM, this._parent);
        }
        _getActiveElem() {
            return this._getChildren().find(child => this._elemIsActive(child)) || null;
        }
        _setInitialAttributes(parent, children) {
            this._setAttributeIfNotExists(parent, 'role', 'tablist');
            for (const child of children) {
                this._setInitialAttributesOnChild(child);
            }
        }
        _setInitialAttributesOnChild(child) {
            child = this._getInnerElement(child);
            const isActive = this._elemIsActive(child);
            const outerElem = this._getOuterElement(child);
            child.setAttribute('aria-selected', isActive);
            if (outerElem !== child) {
                this._setAttributeIfNotExists(outerElem, 'role', 'presentation');
            }
            if (!isActive) {
                child.setAttribute('tabindex', '-1');
            }
            this._setAttributeIfNotExists(child, 'role', 'tab');

            // set attributes to the related panel too
            this._setInitialAttributesOnTargetPanel(child);
        }
        _setInitialAttributesOnTargetPanel(child) {
            const target = SelectorEngine.getElementFromSelector(child);
            if (!target) {
                return;
            }
            this._setAttributeIfNotExists(target, 'role', 'tabpanel');
            if (child.id) {
                this._setAttributeIfNotExists(target, 'aria-labelledby', `${child.id}`);
            }
        }
        _toggleDropDown(element, open) {
            const outerElem = this._getOuterElement(element);
            if (!outerElem.classList.contains(CLASS_DROPDOWN)) {
                return;
            }
            const toggle = (selector, className) => {
                const element = SelectorEngine.findOne(selector, outerElem);
                if (element) {
                    element.classList.toggle(className, open);
                }
            };
            toggle(SELECTOR_DROPDOWN_TOGGLE, CLASS_NAME_ACTIVE);
            toggle(SELECTOR_DROPDOWN_MENU, CLASS_NAME_SHOW$1);
            outerElem.setAttribute('aria-expanded', open);
        }
        _setAttributeIfNotExists(element, attribute, value) {
            if (!element.hasAttribute(attribute)) {
                element.setAttribute(attribute, value);
            }
        }
        _elemIsActive(elem) {
            return elem.classList.contains(CLASS_NAME_ACTIVE);
        }

        // Try to get the inner element (usually the .nav-link)
        _getInnerElement(elem) {
            return elem.matches(SELECTOR_INNER_ELEM) ? elem : SelectorEngine.findOne(SELECTOR_INNER_ELEM, elem);
        }

        // Try to get the outer element (usually the .nav-item)
        _getOuterElement(elem) {
            return elem.closest(SELECTOR_OUTER) || elem;
        }

        // Static
        static jQueryInterface(config) {
            return this.each(function() {
                const data = Tab.getOrCreateInstance(this);
                if (typeof config !== 'string') {
                    return;
                }
                if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
                    throw new TypeError(`No method named "${config}"`);
                }
                data[config]();
            });
        }
    }

    /**
     * Data API implementation
     */

    EventHandler.on(document, EVENT_CLICK_DATA_API, SELECTOR_DATA_TOGGLE, function(event) {
        if (['A', 'AREA'].includes(this.tagName)) {
            event.preventDefault();
        }
        if (isDisabled(this)) {
            return;
        }
        Tab.getOrCreateInstance(this).show();
    });

    /**
     * Initialize on focus
     */
    EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
        for (const element of SelectorEngine.find(SELECTOR_DATA_TOGGLE_ACTIVE)) {
            Tab.getOrCreateInstance(element);
        }
    });
    /**
     * jQuery
     */

    defineJQueryPlugin(Tab);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap toast.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */


    /**
     * Constants
     */

    const NAME = 'toast';
    const DATA_KEY = 'bs.toast';
    const EVENT_KEY = `.${DATA_KEY}`;
    const EVENT_MOUSEOVER = `mouseover${EVENT_KEY}`;
    const EVENT_MOUSEOUT = `mouseout${EVENT_KEY}`;
    const EVENT_FOCUSIN = `focusin${EVENT_KEY}`;
    const EVENT_FOCUSOUT = `focusout${EVENT_KEY}`;
    const EVENT_HIDE = `hide${EVENT_KEY}`;
    const EVENT_HIDDEN = `hidden${EVENT_KEY}`;
    const EVENT_SHOW = `show${EVENT_KEY}`;
    const EVENT_SHOWN = `shown${EVENT_KEY}`;
    const CLASS_NAME_FADE = 'fade';
    const CLASS_NAME_HIDE = 'hide'; // @deprecated - kept here only for backwards compatibility
    const CLASS_NAME_SHOW = 'show';
    const CLASS_NAME_SHOWING = 'showing';
    const DefaultType = {
        animation: 'boolean',
        autohide: 'boolean',
        delay: 'number'
    };
    const Default = {
        animation: true,
        autohide: true,
        delay: 5000
    };

    /**
     * Class definition
     */

    class Toast extends BaseComponent {
        constructor(element, config) {
            super(element, config);
            this._timeout = null;
            this._hasMouseInteraction = false;
            this._hasKeyboardInteraction = false;
            this._setListeners();
        }

        // Getters
        static get Default() {
            return Default;
        }
        static get DefaultType() {
            return DefaultType;
        }
        static get NAME() {
            return NAME;
        }

        // Public
        show() {
            const showEvent = EventHandler.trigger(this._element, EVENT_SHOW);
            if (showEvent.defaultPrevented) {
                return;
            }
            this._clearTimeout();
            if (this._config.animation) {
                this._element.classList.add(CLASS_NAME_FADE);
            }
            const complete = () => {
                this._element.classList.remove(CLASS_NAME_SHOWING);
                EventHandler.trigger(this._element, EVENT_SHOWN);
                this._maybeScheduleHide();
            };
            this._element.classList.remove(CLASS_NAME_HIDE); // @deprecated
            reflow(this._element);
            this._element.classList.add(CLASS_NAME_SHOW, CLASS_NAME_SHOWING);
            this._queueCallback(complete, this._element, this._config.animation);
        }
        hide() {
            if (!this.isShown()) {
                return;
            }
            const hideEvent = EventHandler.trigger(this._element, EVENT_HIDE);
            if (hideEvent.defaultPrevented) {
                return;
            }
            const complete = () => {
                this._element.classList.add(CLASS_NAME_HIDE); // @deprecated
                this._element.classList.remove(CLASS_NAME_SHOWING, CLASS_NAME_SHOW);
                EventHandler.trigger(this._element, EVENT_HIDDEN);
            };
            this._element.classList.add(CLASS_NAME_SHOWING);
            this._queueCallback(complete, this._element, this._config.animation);
        }
        dispose() {
            this._clearTimeout();
            if (this.isShown()) {
                this._element.classList.remove(CLASS_NAME_SHOW);
            }
            super.dispose();
        }
        isShown() {
            return this._element.classList.contains(CLASS_NAME_SHOW);
        }

        // Private
        _maybeScheduleHide() {
            if (!this._config.autohide) {
                return;
            }
            if (this._hasMouseInteraction || this._hasKeyboardInteraction) {
                return;
            }
            this._timeout = setTimeout(() => {
                this.hide();
            }, this._config.delay);
        }
        _onInteraction(event, isInteracting) {
            switch (event.type) {
                case 'mouseover':
                case 'mouseout': {
                    this._hasMouseInteraction = isInteracting;
                    break;
                }
                case 'focusin':
                case 'focusout': {
                    this._hasKeyboardInteraction = isInteracting;
                    break;
                }
            }
            if (isInteracting) {
                this._clearTimeout();
                return;
            }
            const nextElement = event.relatedTarget;
            if (this._element === nextElement || this._element.contains(nextElement)) {
                return;
            }
            this._maybeScheduleHide();
        }
        _setListeners() {
            EventHandler.on(this._element, EVENT_MOUSEOVER, event => this._onInteraction(event, true));
            EventHandler.on(this._element, EVENT_MOUSEOUT, event => this._onInteraction(event, false));
            EventHandler.on(this._element, EVENT_FOCUSIN, event => this._onInteraction(event, true));
            EventHandler.on(this._element, EVENT_FOCUSOUT, event => this._onInteraction(event, false));
        }
        _clearTimeout() {
            clearTimeout(this._timeout);
            this._timeout = null;
        }

        // Static
        static jQueryInterface(config) {
            return this.each(function() {
                const data = Toast.getOrCreateInstance(this, config);
                if (typeof config === 'string') {
                    if (typeof data[config] === 'undefined') {
                        throw new TypeError(`No method named "${config}"`);
                    }
                    data[config](this);
                }
            });
        }
    }

    /**
     * Data API implementation
     */

    enableDismissTrigger(Toast);

    /**
     * jQuery
     */

    defineJQueryPlugin(Toast);

    /**
     * --------------------------------------------------------------------------
     * Bootstrap index.umd.js
     * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
     * --------------------------------------------------------------------------
     */

    const index_umd = {
        Alert,
        Button,
        Carousel,
        Collapse,
        Dropdown,
        Modal,
        Offcanvas,
        Popover,
        ScrollSpy,
        Tab,
        Toast,
        Tooltip
    };

    return index_umd;

}));
//# sourceMappingURL=bootstrap.js.map
(function(global2, factory) {
    typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : (global2 = typeof globalThis !== "undefined" ? globalThis : global2 || self, global2.ApexCharts = factory());
})(this, (function() {
    "use strict";
    var __defProp = Object.defineProperty;
    var __defProps = Object.defineProperties;
    var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
    var __getOwnPropSymbols = Object.getOwnPropertySymbols;
    var __hasOwnProp = Object.prototype.hasOwnProperty;
    var __propIsEnum = Object.prototype.propertyIsEnumerable;
    var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
        enumerable: true,
        configurable: true,
        writable: true,
        value
    }) : obj[key] = value;
    var __spreadValues = (a, b) => {
        for (var prop in b || (b = {}))
            if (__hasOwnProp.call(b, prop))
                __defNormalProp(a, prop, b[prop]);
        if (__getOwnPropSymbols)
            for (var prop of __getOwnPropSymbols(b)) {
                if (__propIsEnum.call(b, prop))
                    __defNormalProp(a, prop, b[prop]);
            }
        return a;
    };
    var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
    var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
    /*!
     * ApexCharts v5.14.0
     * (c) 2018-2026 ApexCharts
     */

    class Environment {
        /**
         * Check if running in server-side rendering environment (Node.js)
         * @returns {boolean} True if in SSR/Node.js, false if in browser
         */
        static isSSR() {
            return typeof window === "undefined" || typeof document === "undefined";
        }
        /**
         * Check if running in browser environment
         * @returns {boolean} True if in browser, false if in SSR/Node.js
         */
        static isBrowser() {
            return !this.isSSR();
        }
        /**
         * Check if a specific browser API is available
         * @param {string} api - Name of the API to check (e.g., 'ResizeObserver')
         * @returns {boolean} True if API is available
         */
        static hasAPI(api) {
            if (this.isSSR()) return false;
            return typeof /** @type {any} */
            window[api] !== "undefined";
        }
        /**
         * Returns the global Apex config object regardless of environment.
         * In browser: window.Apex; in SSR/Node.js: global.Apex; fallback: {}.
         * @returns {any}
         */
        static getApex() {
            if (typeof window !== "undefined" && window.Apex) return window.Apex;
            if (typeof global !== "undefined" && global.Apex) return global.Apex;
            return {};
        }
    }
    class SSRElement {
        /**
         * @param {string} nodeName
         * @param {any} namespaceURI
         */
        constructor(nodeName, namespaceURI = null) {
            this.nodeName = nodeName;
            this.namespaceURI = namespaceURI;
            this.attributes = /* @__PURE__ */ new Map();
            this.children = [];
            this.textContent = "";
            this.style = {};
            this.classList = new SSRClassList();
            this.parentNode = /** @type {SSRElement | null} */
                null;
            this._ssrWidth = void 0;
            this._ssrHeight = void 0;
            this._ssrMode = void 0;
        }
        /**
         * @param {string} name
         * @param {any} value
         */
        setAttribute(name2, value) {
            this.attributes.set(name2, value);
        }
        /**
         * @param {string} name
         */
        getAttribute(name2) {
            return this.attributes.get(name2);
        }
        /**
         * @param {string} name
         */
        removeAttribute(name2) {
            this.attributes.delete(name2);
        }
        /**
         * @param {string} name
         */
        hasAttribute(name2) {
            return this.attributes.has(name2);
        }
        /**
         * @param {any} child
         */
        appendChild(child) {
            if (child && child !== this) {
                if (child.parentNode && child.parentNode !== this) {
                    child.parentNode.removeChild(child);
                } else if (child.parentNode === this) {
                    const index = this.children.indexOf(child);
                    if (index !== -1) this.children.splice(index, 1);
                }
                child.parentNode = this;
                this.children.push(child);
            }
            return child;
        }
        /**
         * @param {any} child
         */
        removeChild(child) {
            const index = this.children.indexOf(child);
            if (index !== -1) {
                this.children.splice(index, 1);
                child.parentNode = null;
            }
            return child;
        }
        /**
         * @param {any} newNode
         * @param {any} referenceNode
         */
        insertBefore(newNode, referenceNode) {
            if (!referenceNode) {
                return this.appendChild(newNode);
            }
            if (newNode.parentNode && newNode.parentNode !== this) {
                newNode.parentNode.removeChild(newNode);
            } else if (newNode.parentNode === this) {
                const existingIndex = this.children.indexOf(newNode);
                if (existingIndex !== -1) this.children.splice(existingIndex, 1);
            }
            const index = this.children.indexOf(referenceNode);
            if (index !== -1) {
                newNode.parentNode = this;
                this.children.splice(index, 0, newNode);
            }
            return newNode;
        }
        cloneNode(deep = false) {
            const clone = new SSRElement(this.nodeName, this.namespaceURI);
            clone.textContent = this.textContent;
            this.attributes.forEach((value, key) => {
                clone.attributes.set(key, value);
            });
            Object.assign(clone.style, this.style);
            if (deep) {
                this.children.forEach((child) => {
                    if (child.cloneNode) {
                        clone.appendChild(child.cloneNode(true));
                    }
                });
            }
            return clone;
        }
        getBoundingClientRect() {
            return {
                width: this._ssrWidth || 0,
                height: this._ssrHeight || 0,
                top: 0,
                left: 0,
                right: this._ssrWidth || 0,
                bottom: this._ssrHeight || 0,
                x: 0,
                y: 0
            };
        }
        getRootNode() {
            let root = this;
            while (root.parentNode) {
                root = root.parentNode;
            }
            return root;
        }
        querySelector() {
            return null;
        }
        querySelectorAll() {
            return [];
        }
        getElementsByClassName() {
            return [];
        }
        addEventListener() {}
        removeEventListener() {}
        get childNodes() {
            return this.children;
        }
        toString() {
            let attrs = "";
            this.attributes.forEach((value, key) => {
                attrs += ` ${key}="${value}"`;
            });
            if (this.children.length === 0 && !this.textContent) {
                return `<${this.nodeName}${attrs}/>`;
            }
            const childrenStr = this.children.map((c) => c.toString()).join("");
            return `<${this.nodeName}${attrs}>${this.textContent}${childrenStr}</${this.nodeName}>`;
        }
        // Property getters/setters
        get innerHTML() {
            return this.children.map((c) => c.toString()).join("");
        }
        set innerHTML(value) {
            this.children = [];
            this.textContent = value;
        }
        get outerHTML() {
            return this.toString();
        }
        get isConnected() {
            return true;
        }
    }
    class SSRClassList {
        constructor() {
            this.classes = /* @__PURE__ */ new Set();
        }
        add(...classNames) {
            classNames.forEach((name2) => this.classes.add(name2));
        }
        remove(...classNames) {
            classNames.forEach((name2) => this.classes.delete(name2));
        }
        /**
         * @param {string} className
         */
        contains(className) {
            return this.classes.has(className);
        }
        /**
         * @param {string} className
         * @param {any} force
         */
        toggle(className, force) {
            if (force === true) {
                this.classes.add(className);
                return true;
            } else if (force === false) {
                this.classes.delete(className);
                return false;
            } else {
                if (this.classes.has(className)) {
                    this.classes.delete(className);
                    return false;
                } else {
                    this.classes.add(className);
                    return true;
                }
            }
        }
        toString() {
            return Array.from(this.classes).join(" ");
        }
    }
    class SSRDOMShim {
        constructor() {
            this.SVGNS = "http://www.w3.org/2000/svg";
            this.XLINKNS = "http://www.w3.org/1999/xlink";
        }
        /**
         * Create SVG element with namespace
         * @param {string} namespaceURI - Namespace URI
         * @param {string} qualifiedName - Element tag name
         * @returns {SSRElement} Mock SVG element
         */
        createElementNS(namespaceURI, qualifiedName) {
            return new SSRElement(qualifiedName, namespaceURI);
        }
        /**
         * Create text node
         * @param {string} data - Text content
         * @returns {object} Text node mock
         */
        createTextNode(data) {
            const node = {
                nodeName: "#text",
                nodeType: 3,
                textContent: data,
                toString() {
                    return node.textContent;
                }
            };
            return node;
        }
        /**
         * Query selector (returns null in SSR)
         * @returns {null}
         */
        querySelector() {
            return null;
        }
        /**
         * Query selector all (returns empty array in SSR)
         * @returns {any[]}
         */
        querySelectorAll() {
            return [];
        }
        /**
         * Get computed style (returns empty object in SSR)
         * @returns {object}
         */
        getComputedStyle() {
            return {};
        }
        /**
         * Get bounding client rect for element
         * @param {SSRElement} element - Element to measure
         * @returns {object} Mock dimensions
         */
        getBoundingClientRect(element) {
            if (element && element.getBoundingClientRect) {
                return element.getBoundingClientRect();
            }
            return {
                width: 0,
                height: 0,
                top: 0,
                left: 0,
                right: 0,
                bottom: 0,
                x: 0,
                y: 0
            };
        }
        /**
         * Create mock XMLSerializer for SSR
         * @returns {object} XMLSerializer mock
         */
        createXMLSerializer() {
            return {
                /**
                 * @param {Element} element
                 */
                serializeToString(element) {
                    return element.toString ? element.toString() : "";
                }
            };
        }
        /**
         * Create mock DOMParser for SSR
         * @returns {object} DOMParser mock
         */
        createDOMParser() {
            return {
                /**
                 * @param {string} str
                 * @param {string} _type
                 */
                parseFromString(str, _type) {
                    const root = new SSRElement("root");
                    root.innerHTML = str;
                    return {
                        documentElement: root
                    };
                }
            };
        }
    }
    let shim = null;
    let xmlSerializerInstance = null;
    let domParserInstance = null;
    class BrowserAPIs {
        /**
         * Initialize the SSR shim if in SSR environment
         * Must be called before using other methods
         */
        static init() {
            if (Environment.isSSR() && !shim) {
                shim = new SSRDOMShim();
            }
        }
        /**
         * Create an HTML element
         * @param {string} tagName - Element tag name
         * @returns {HTMLElement} HTML element
         */
        static createElement(tagName) {
            if (Environment.isSSR()) {
                if (!shim) this.init();
                return shim.createElementNS(null, tagName);
            }
            return document.createElement(tagName);
        }
        /**
         * Create an SVG element with namespace
         * @param {string} namespaceURI - Namespace URI
         * @param {string} qualifiedName - Element tag name
         * @returns {HTMLElement} created element
         */
        static createElementNS(namespaceURI, qualifiedName) {
            if (Environment.isSSR()) {
                if (!shim) this.init();
                return shim.createElementNS(namespaceURI, qualifiedName);
            }
            return (
                /** @type {HTMLElement} */
                document.createElementNS(namespaceURI, qualifiedName)
            );
        }
        /**
         * Create a text node
         * @param {string} data - Text content
         * @returns {Text|object} Text node
         */
        static createTextNode(data) {
            if (Environment.isSSR()) {
                if (!shim) this.init();
                return shim.createTextNode(data);
            }
            return document.createTextNode(data);
        }
        /**
         * Query selector
         * @param {string} selector - CSS selector
         * @returns {Element|null}
         */
        static querySelector(selector) {
            if (Environment.isSSR()) {
                return null;
            }
            return document.querySelector(selector);
        }
        /**
         * Query selector all
         * @param {string} selector - CSS selector
         * @returns {NodeList|any[]}
         */
        static querySelectorAll(selector) {
            if (Environment.isSSR()) {
                return [];
            }
            return document.querySelectorAll(selector);
        }
        /**
         * Get computed style for an element
         * @param {Element} element - Element to get styles for
         * @returns {CSSStyleDeclaration|object}
         */
        static getComputedStyle(element) {
            if (Environment.isSSR()) {
                return {};
            }
            return window.getComputedStyle(element);
        }
        /**
         * Get bounding client rect for an element
         * @param {Element} element - Element to measure
         * @returns {DOMRect|object}
         */
        static getBoundingClientRect(element) {
            if (Environment.isSSR()) {
                if (!shim) this.init();
                return shim.getBoundingClientRect(element);
            }
            return element ? element.getBoundingClientRect() : {
                width: 0,
                height: 0,
                top: 0,
                left: 0,
                right: 0,
                bottom: 0,
                x: 0,
                y: 0
            };
        }
        /**
         * Get XMLSerializer instance
         * @returns {XMLSerializer|object}
         */
        static getXMLSerializer() {
            if (Environment.isSSR()) {
                if (!shim) this.init();
                if (!xmlSerializerInstance) {
                    xmlSerializerInstance = shim.createXMLSerializer();
                }
                return xmlSerializerInstance;
            }
            if (!xmlSerializerInstance) {
                xmlSerializerInstance = new XMLSerializer();
            }
            return xmlSerializerInstance;
        }
        /**
         * Get DOMParser instance
         * @returns {DOMParser|object}
         */
        static getDOMParser() {
            if (Environment.isSSR()) {
                if (!shim) this.init();
                if (!domParserInstance) {
                    domParserInstance = shim.createDOMParser();
                }
                return domParserInstance;
            }
            if (!domParserInstance) {
                domParserInstance = new DOMParser();
            }
            return domParserInstance;
        }
        /**
         * Add event listener to window
         * @param {string} event - Event name
         * @param {EventListenerOrEventListenerObject} handler - Event handler
         * @param {object} options - Event options
         */
        static addWindowEventListener(event, handler, options2) {
            if (Environment.isBrowser()) {
                window.addEventListener(event, handler, options2);
            }
        }
        /**
         * Remove event listener from window
         * @param {string} event - Event name
         * @param {EventListenerOrEventListenerObject} handler - Event handler
         * @param {object} options - Event options
         */
        static removeWindowEventListener(event, handler, options2) {
            if (Environment.isBrowser()) {
                window.removeEventListener(event, handler, options2);
            }
        }
        /**
         * Request animation frame
         * @param {FrameRequestCallback} callback - Callback function
         * @returns {number|null}
         */
        static requestAnimationFrame(callback) {
            if (Environment.isBrowser()) {
                return window.requestAnimationFrame(callback);
            }
            callback(0);
            return null;
        }
        /**
         * Cancel animation frame
         * @param {number} id - Animation frame ID
         */
        static cancelAnimationFrame(id) {
            if (Environment.isBrowser() && id) {
                window.cancelAnimationFrame(id);
            }
        }
        /**
         * Check if element exists
         * @param {Element} element - Element to check
         * @returns {boolean}
         */
        static elementExists(element) {
            if (!element) return false;
            if (Environment.isSSR()) {
                return element._ssrMode === true || element.nodeName !== void 0;
            }
            return element.getRootNode ? element.getRootNode({
                composed: true
            }) === document || element.isConnected : false;
        }
        /**
         * Get window object (or null in SSR)
         * @returns {Window|null}
         */
        static getWindow() {
            return Environment.isBrowser() ? window : null;
        }
        /**
         * Get document object (or null in SSR)
         * @returns {Document|null}
         */
        static getDocument() {
            return Environment.isBrowser() ? document : null;
        }
        /**
         * Get the shim instance (for testing purposes)
         * @returns {SSRDOMShim|null}
         */
        static _getShim() {
            return shim;
        }
        /**
         * Reset the shim instance (for testing purposes)
         */
        static _resetShim() {
            shim = null;
            xmlSerializerInstance = null;
            domParserInstance = null;
        }
    }
    let Utils$1 = class Utils2 {
        /**
         * @param {*} item
         */
        static isObject(item) {
            return item && typeof item === "object" && !Array.isArray(item);
        }
        // Type checking that works across different window objects
        /**
         * @param {string} type
         * @param {string} val
         */
        static is(type, val) {
            return Object.prototype.toString.call(val) === "[object " + type + "]";
        }
        static isSafari() {
            return Environment.isBrowser() && /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
        }
        // to extend defaults with user options
        // credit: http://stackoverflow.com/questions/27936772/deep-object-merging-in-es6-es7#answer-34749873
        /**
         * @param {any} target
         * @param {any} source
         */
        static extend(target, source) {
            const output = Object.assign({}, target);
            if (this.isObject(target) && this.isObject(source)) {
                Object.keys(source).forEach((key) => {
                    if (this.isObject(source[key])) {
                        if (!(key in target)) {
                            Object.assign(output, {
                                [key]: source[key]
                            });
                        } else {
                            output[key] = this.extend(target[key], source[key]);
                        }
                    } else {
                        Object.assign(output, {
                            [key]: source[key]
                        });
                    }
                });
            }
            return output;
        }
        /**
         * @param {any[]} arrToExtend
         * @param {any} resultArr
         */
        static extendArray(arrToExtend, resultArr) {
            const extendedArr = [];
            arrToExtend.map((item) => {
                extendedArr.push(Utils2.extend(resultArr, item));
            });
            arrToExtend = extendedArr;
            return arrToExtend;
        }
        // If month counter exceeds 12, it starts again from 1
        /**
         * @param {number} month
         */
        static monthMod(month) {
            return month % 12;
        }
        /**
         * clone object with optional shallow copy for performance
         * @param {*} source - Source object to clone
         * @param {WeakMap<any, any>} visited - Circular reference tracker
         * @param {boolean} shallow - If true, performs shallow copy (default: false)
         * @returns {*} Cloned object
         */
        static clone(source, visited = /* @__PURE__ */ new WeakMap(), shallow = false) {
            if (source === null || typeof source !== "object") {
                return source;
            }
            if (visited.has(source)) {
                return visited.get(source);
            }
            let cloneResult;
            if (Array.isArray(source)) {
                if (shallow) {
                    cloneResult = source.slice();
                } else {
                    cloneResult = [];
                    visited.set(source, cloneResult);
                    for (let i = 0; i < source.length; i++) {
                        cloneResult[i] = this.clone(source[i], visited, false);
                    }
                }
            } else if (source instanceof Date) {
                cloneResult = new Date(source.getTime());
            } else {
                if (shallow) {
                    cloneResult = Object.assign({}, source);
                } else {
                    cloneResult = {};
                    visited.set(source, cloneResult);
                    for (const prop in source) {
                        if (Object.prototype.hasOwnProperty.call(source, prop)) {
                            cloneResult[prop] = this.clone(
                                /** @type {Record<string,any>} */
                                source[prop],
                                visited,
                                false
                            );
                        }
                    }
                }
            }
            return cloneResult;
        }
        /**
         * Shallow clone for performance when deep clone isn't needed
         * @param {*} source - Source to clone
         * @returns {*} Shallow cloned object
         */
        static shallowClone(source) {
            if (source === null || typeof source !== "object") {
                return source;
            }
            if (Array.isArray(source)) {
                return source.slice();
            }
            return Object.assign({}, source);
        }
        /**
         * Fast shallow equality check for objects
         * @param {Object} obj1 - First object
         * @param {Object} obj2 - Second object
         * @returns {boolean} True if shallowly equal
         */
        static shallowEqual(obj1, obj2) {
            if (obj1 === obj2) return true;
            if (!obj1 || !obj2) return false;
            if (typeof obj1 !== "object" || typeof obj2 !== "object") {
                return obj1 === obj2;
            }
            const keys1 = Object.keys(obj1);
            const keys2 = Object.keys(obj2);
            if (keys1.length !== keys2.length) return false;
            for (const key of keys1) {
                if (
                    /** @type {Record<string,any>} */
                    obj1[key] !== /** @type {Record<string,any>} */
                    obj2[key]
                )
                    return false;
            }
            return true;
        }
        /**
         * @param {number} x
         */
        static log10(x) {
            return Math.log(x) / Math.LN10;
        }
        /**
         * @param {number} x
         */
        static roundToBase10(x) {
            return Math.pow(10, Math.floor(Math.log10(x)));
        }
        /**
         * @param {number} x
         * @param {number} base
         */
        static roundToBase(x, base) {
            return Math.pow(base, Math.floor(Math.log(x) / Math.log(base)));
        }
        /**
         * @param {any} val
         */
        static parseNumber(val) {
            if (typeof val === "number" || val === null) return val;
            return parseFloat(val);
        }
        /**
         * @param {number} num
         */
        static stripNumber(num, precision = 2) {
            return Number.isInteger(num) ? num : parseFloat(num.toPrecision(precision));
        }
        static randomId() {
            return (Math.random() + 1).toString(36).substring(4);
        }
        /**
         * @param {number} num
         */
        static noExponents(num) {
            if (num.toString().includes("e")) {
                return Math.round(num);
            }
            return num;
        }
        /**
         * @param {any} element
         */
        static elementExists(element) {
            if (!element || !element.isConnected) {
                return false;
            }
            return true;
        }
        /**
         * detects if an element is inside a Shadow DOM
         * @param {any} el
         */
        static isInShadowDOM(el) {
            if (!el || !el.getRootNode) {
                return false;
            }
            const rootNode = el.getRootNode();
            return rootNode && rootNode !== document && Utils2.is("ShadowRoot", rootNode);
        }
        /**
         * gets the shadow root host element
         * @param {any} el
         */
        static getShadowRootHost(el) {
            if (!Utils2.isInShadowDOM(el)) {
                return null;
            }
            const rootNode = el.getRootNode();
            return rootNode.host || null;
        }
        /**
         * @param {any} el
         */
        static getDimensions(el) {
            if (!el) return [0, 0];
            if (Environment.isSSR()) {
                return [el._ssrWidth || 400, el._ssrHeight || 300];
            }
            let computedStyle;
            try {
                computedStyle = getComputedStyle(el, null);
            } catch (e) {
                return [el.clientWidth || 0, el.clientHeight || 0];
            }
            let elementWidth = el.clientWidth;
            let elementHeight = el.clientHeight;
            if (!elementWidth || !elementHeight) {
                const rect = el.getBoundingClientRect();
                elementWidth = elementWidth || rect.width;
                elementHeight = elementHeight || rect.height;
            }
            elementHeight -= parseFloat(computedStyle.paddingTop) + parseFloat(computedStyle.paddingBottom);
            elementWidth -= parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight);
            return [elementWidth, elementHeight];
        }
        /**
         * @returns {any}
         * @param {any} element
         */
        static getBoundingClientRect(element) {
            if (!element) {
                return {
                    top: 0,
                    right: 0,
                    bottom: 0,
                    left: 0,
                    width: 0,
                    height: 0,
                    x: 0,
                    y: 0
                };
            }
            if (Environment.isSSR()) {
                return BrowserAPIs.getBoundingClientRect(element);
            }
            const rect = element.getBoundingClientRect();
            return {
                top: rect.top,
                right: rect.right,
                bottom: rect.bottom,
                left: rect.left,
                width: element.clientWidth,
                height: element.clientHeight,
                x: rect.left,
                y: rect.top
            };
        }
        /**
         * @param {any[]} arr
         */
        static getLargestStringFromArr(arr) {
            return arr.reduce((a, b) => {
                if (Array.isArray(b)) {
                    b = b.reduce((aa, bb) => aa.length > bb.length ? aa : bb);
                }
                return a.length > b.length ? a : b;
            }, 0);
        }
        // http://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb#answer-12342275
        static hexToRgba(hex = "#999999", opacity = 0.6) {
            if (hex.substring(0, 1) !== "#") {
                hex = "#999999";
            }
            const hexStr = hex.replace("#", "");
            const h = hexStr.match(new RegExp("(.{" + hexStr.length / 3 + "})", "g")) || [];
            for (let i = 0; i < h.length; i++) {
                h[i] = parseInt(h[i].length === 1 ? h[i] + h[i] : h[i], 16);
            }
            if (typeof opacity !== "undefined") h.push(opacity);
            return "rgba(" + h.join(",") + ")";
        }
        /**
         * @param {string} rgba
         */
        static getOpacityFromRGBA(rgba) {
            return parseFloat(rgba.replace(/^.*,(.+)\)/, "$1"));
        }
        /**
         * Parse a #RGB or #RRGGBB hex colour string into [r,g,b] in 0–255.
         * Returns null for invalid input. Used by getContrastRatio.
         * @param {string} hex
         * @returns {[number, number, number] | null}
         */
        static parseHex(hex) {
            if (typeof hex !== "string") return null;
            let h = hex.trim().replace("#", "");
            if (h.length === 3) {
                h = h.split("").map((c) => c + c).join("");
            }
            if (!/^[0-9a-fA-F]{6}$/.test(h)) return null;
            return [
                parseInt(h.slice(0, 2), 16),
                parseInt(h.slice(2, 4), 16),
                parseInt(h.slice(4, 6), 16)
            ];
        }
        /**
         * Relative luminance per WCAG 2.x (https://www.w3.org/TR/WCAG22/#dfn-relative-luminance).
         * @param {[number, number, number]} rgb 0–255 sRGB triplet
         * @returns {number} 0.0–1.0
         */
        static relativeLuminance([r, g, b]) {
            const channel = (c) => {
                const v = c / 255;
                return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
            };
            return 0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b);
        }
        /**
         * WCAG contrast ratio between two hex colours. Returns 0 for invalid input.
         * Range: 1 (identical) … 21 (#000 vs #fff).
         * WCAG AA requires ≥ 4.5 for normal text and ≥ 3.0 for large text / UI components.
         * @param {string} hex1
         * @param {string} hex2
         * @returns {number}
         */
        static getContrastRatio(hex1, hex2) {
            const rgb1 = Utils2.parseHex(hex1);
            const rgb2 = Utils2.parseHex(hex2);
            if (!rgb1 || !rgb2) return 0;
            const l1 = Utils2.relativeLuminance(rgb1);
            const l2 = Utils2.relativeLuminance(rgb2);
            const lighter = Math.max(l1, l2);
            const darker = Math.min(l1, l2);
            return (lighter + 0.05) / (darker + 0.05);
        }
        /**
         * @param {any} rgb
         */
        static rgb2hex(rgb) {
            rgb = rgb.match(
                /^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i
            );
            return rgb && rgb.length === 4 ? "#" + ("0" + parseInt(rgb[1], 10).toString(16)).slice(-2) + ("0" + parseInt(rgb[2], 10).toString(16)).slice(-2) + ("0" + parseInt(rgb[3], 10).toString(16)).slice(-2) : "";
        }
        /**
         * @param {number} percent
         * @param {string} color
         */
        shadeRGBColor(percent, color) {
            const f = color.split(","),
                t = percent < 0 ? 0 : 255,
                p = percent < 0 ? percent * -1 : percent,
                R = parseInt(f[0].slice(4), 10),
                G = parseInt(f[1], 10),
                B = parseInt(f[2], 10);
            return "rgb(" + (Math.round((t - R) * p) + R) + "," + (Math.round((t - G) * p) + G) + "," + (Math.round((t - B) * p) + B) + ")";
        }
        /**
         * @param {number} percent
         * @param {string} color
         */
        shadeHexColor(percent, color) {
            const f = parseInt(color.slice(1), 16),
                t = percent < 0 ? 0 : 255,
                p = percent < 0 ? percent * -1 : percent,
                R = f >> 16,
                G = f >> 8 & 255,
                B = f & 255;
            return "#" + (16777216 + (Math.round((t - R) * p) + R) * 65536 + (Math.round((t - G) * p) + G) * 256 + (Math.round((t - B) * p) + B)).toString(16).slice(1);
        }
        // beautiful color shading blending code
        // http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color-or-rgb-and-blend-colors
        /**
         * @param {number} p
         * @param {string} color
         */
        shadeColor(p, color) {
            if (Utils2.isColorHex(color)) {
                return this.shadeHexColor(p, color);
            } else {
                return this.shadeRGBColor(p, color);
            }
        }
        /**
         * @param {string} color
         */
        static isColorHex(color) {
            return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)|(^#[0-9A-F]{8}$)/i.test(color);
        }
        /**
         * @param {string} color
         */
        static isCSSVariable(color) {
            if (typeof color !== "string") return false;
            const value = color.trim();
            return value.startsWith("var(") && value.endsWith(")");
        }
        /**
         * @param {string} color
         */
        static getThemeColor(color) {
            if (!Utils2.isCSSVariable(color)) return color;
            if (Environment.isSSR()) return color;
            const tempElem = document.createElement("div");
            tempElem.style.cssText = "position:fixed; left: -9999px; visibility:hidden;";
            tempElem.style.color = color;
            document.body.appendChild(tempElem);
            let computedColor;
            try {
                computedColor = window.getComputedStyle(tempElem).color;
            } finally {
                if (tempElem.parentNode) {
                    tempElem.parentNode.removeChild(tempElem);
                }
            }
            return computedColor;
        }
        /**
         * @param {string} color
         * @param {number} opacity
         */
        static applyOpacityToColor(color, opacity) {
            const value = Number(opacity);
            if (!Number.isFinite(value)) return color;
            if (value <= 0) return "transparent";
            if (value >= 1) return color;
            const percent = Math.round(value * 100);
            return `color-mix(in srgb, ${color} ${percent}%, transparent)`;
        }
        /**
         * @param {number} size
         * @param {number} dataPointsLen
         */
        static getPolygonPos(size, dataPointsLen) {
            const dotsArray = [];
            const angle = Math.PI * 2 / dataPointsLen;
            for (let i = 0; i < dataPointsLen; i++) {
                const curPos = {};
                curPos.x = size * Math.sin(i * angle);
                curPos.y = -size * Math.cos(i * angle);
                dotsArray.push(curPos);
            }
            return dotsArray;
        }
        /**
         * @param {number} centerX
         * @param {number} centerY
         * @param {number} radius
         * @param {number} angleInDegrees
         */
        static polarToCartesian(centerX, centerY, radius, angleInDegrees) {
            const angleInRadians = (angleInDegrees - 90) * Math.PI / 180;
            return {
                x: centerX + radius * Math.cos(angleInRadians),
                y: centerY + radius * Math.sin(angleInRadians)
            };
        }
        /**
         * @param {string} str
         */
        static escapeString(str, escapeWith = "x") {
            let newStr = str.toString().slice();
            newStr = newStr.replace(/[` ~!@#$%^&*()|+=?;:'",.<>{}[\]\\/]/gi, escapeWith);
            return newStr;
        }
        /**
         * @param {number} val
         */
        static negToZero(val) {
            return val < 0 ? 0 : val;
        }
        /**
         * @param {any[]} arr
         * @param {number} old_index
         * @param {number} new_index
         */
        static moveIndexInArray(arr, old_index, new_index) {
            if (new_index >= arr.length) {
                let k = new_index - arr.length + 1;
                while (k--) {
                    arr.push(void 0);
                }
            }
            arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
            return arr;
        }
        /**
         * @param {string} s
         */
        static extractNumber(s) {
            return parseFloat(s.replace(/[^\d.]*/g, ""));
        }
        /**
         * @param {any} el
         * @param {string} cls
         */
        static findAncestor(el, cls) {
            while ((el = el.parentElement) && !el.classList.contains(cls));
            return el;
        }
        /**
         * @param {any} el
         * @param {Record<string, any>} styles
         */
        static setELstyles(el, styles) {
            for (const key in styles) {
                if (Object.prototype.hasOwnProperty.call(styles, key)) {
                    el.style.key = styles[key];
                }
            }
        }
        // prevents JS prevision errors when adding
        /**
         * @param {number} a
         * @param {number} b
         */
        static preciseAddition(a, b) {
            const aDecimals = (String(a).split(".")[1] || "").length;
            const bDecimals = (String(b).split(".")[1] || "").length;
            const factor = Math.pow(10, Math.max(aDecimals, bDecimals));
            return (Math.round(a * factor) + Math.round(b * factor)) / factor;
        }
        /**
         * @param {any} value
         */
        static isNumber(value) {
            return !isNaN(value) && parseFloat(String(Number(value))) === value && !isNaN(parseInt(value, 10));
        }
        /**
         * @param {number} n
         */
        static isFloat(n) {
            return Number(n) === n && n % 1 !== 0;
        }
        static isMsEdge() {
            if (Environment.isSSR()) return false;
            const ua = window.navigator.userAgent;
            const edge = ua.indexOf("Edge/");
            if (edge > 0) {
                return parseInt(ua.substring(edge + 5, ua.indexOf(".", edge)), 10);
            }
            return false;
        }
        //
        // Find the Greatest Common Divisor of two numbers
        //
        /**
         * @param {number} a
         * @param {number} b
         */
        static getGCD(a, b, p = 7) {
            let factor = Math.pow(10, p - Math.floor(Math.log10(Math.max(a, b))));
            if (factor > 1) {
                a = Math.round(Math.abs(a) * factor);
                b = Math.round(Math.abs(b) * factor);
            } else {
                factor = 1;
            }
            while (b) {
                const t = b;
                b = a % b;
                a = t;
            }
            return a / factor;
        }
        /**
         * @param {number} n
         */
        static getPrimeFactors(n) {
            const factors = [];
            let divisor = 2;
            while (n >= 2) {
                if (n % divisor == 0) {
                    factors.push(divisor);
                    n = n / divisor;
                } else {
                    divisor++;
                }
            }
            return factors;
        }
        /**
         * @param {number} a
         * @param {number} b
         */
        static mod(a, b, p = 7) {
            const big = Math.pow(10, p - Math.floor(Math.log10(Math.max(a, b))));
            a = Math.round(Math.abs(a) * big);
            b = Math.round(Math.abs(b) * big);
            return a % b / big;
        }
    };
    class DateTime {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
            this.months31 = [1, 3, 5, 7, 8, 10, 12];
            this.months30 = [2, 4, 6, 9, 11];
            this.daysCntOfYear = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
        }
        /**
         * @param {any} date
         */
        isValidDate(date) {
            if (typeof date === "number") {
                return false;
            }
            return !isNaN(this.parseDate(date));
        }
        /**
         * @param {any} dateStr
         */
        getTimeStamp(dateStr) {
            if (!Date.parse(dateStr)) {
                return dateStr;
            }
            const utc = this.w.config.xaxis.labels.datetimeUTC;
            return !utc ? new Date(dateStr).getTime() : new Date(new Date(dateStr).toISOString().substr(0, 25)).getTime();
        }
        /**
         * @param {any} timestamp
         */
        getDate(timestamp) {
            const utc = this.w.config.xaxis.labels.datetimeUTC;
            return utc ? new Date(new Date(timestamp).toUTCString()) : new Date(timestamp);
        }
        /**
         * @param {string} dateStr
         */
        parseDate(dateStr) {
            const parsed = Date.parse(dateStr);
            if (!isNaN(parsed)) {
                return this.getTimeStamp(dateStr);
            }
            let output = Date.parse(dateStr.replace(/-/g, "/").replace(/[a-z]+/gi, " "));
            output = this.getTimeStamp(output);
            return output;
        }
        // This fixes the difference of x-axis labels between chrome/safari
        // Fixes #1726, #1544, #1485, #1255
        /**
         * @param {string} dateStr
         */
        parseDateWithTimezone(dateStr) {
            return Date.parse(dateStr.replace(/-/g, "/").replace(/[a-z]+/gi, " "));
        }
        // http://stackoverflow.com/questions/14638018/current-time-formatting-with-javascript#answer-14638191
        /**
         * @param {Date} date
         * @param {string} format
         */
        formatDate(date, format) {
            const locale = this.w.globals.locale;
            const utc = this.w.config.xaxis.labels.datetimeUTC;
            const MMMM = ["\0", ...locale.months];
            const MMM = ["", ...locale.shortMonths];
            const dddd = ["", ...locale.days];
            const ddd = ["", ...locale.shortDays];

            function ii(i, len = 2) {
                let s2 = i + "";
                while (s2.length < len) s2 = "0" + s2;
                return s2;
            }
            const y = utc ? date.getUTCFullYear() : date.getFullYear();
            format = format.replace(/(^|[^\\])yyyy+/g, "$1" + y);
            format = format.replace(/(^|[^\\])yy/g, "$1" + y.toString().substr(2, 2));
            format = format.replace(/(^|[^\\])y/g, "$1" + y);
            const M = (utc ? date.getUTCMonth() : date.getMonth()) + 1;
            format = format.replace(/(^|[^\\])MMMM+/g, "$1" + MMMM[0]);
            format = format.replace(/(^|[^\\])MMM/g, "$1" + MMM[0]);
            format = format.replace(/(^|[^\\])MM/g, "$1" + ii(M));
            format = format.replace(/(^|[^\\])M/g, "$1" + M);
            const d = utc ? date.getUTCDate() : date.getDate();
            format = format.replace(/(^|[^\\])dddd+/g, "$1" + dddd[0]);
            format = format.replace(/(^|[^\\])ddd/g, "$1" + ddd[0]);
            format = format.replace(/(^|[^\\])dd/g, "$1" + ii(d));
            format = format.replace(/(^|[^\\])d/g, "$1" + d);
            const H = utc ? date.getUTCHours() : date.getHours();
            format = format.replace(/(^|[^\\])HH+/g, "$1" + ii(H));
            format = format.replace(/(^|[^\\])H/g, "$1" + H);
            const h = H > 12 ? H - 12 : H === 0 ? 12 : H;
            format = format.replace(/(^|[^\\])hh+/g, "$1" + ii(h));
            format = format.replace(/(^|[^\\])h/g, "$1" + h);
            const m = utc ? date.getUTCMinutes() : date.getMinutes();
            format = format.replace(/(^|[^\\])mm+/g, "$1" + ii(m));
            format = format.replace(/(^|[^\\])m/g, "$1" + m);
            const s = utc ? date.getUTCSeconds() : date.getSeconds();
            format = format.replace(/(^|[^\\])ss+/g, "$1" + ii(s));
            format = format.replace(/(^|[^\\])s/g, "$1" + s);
            let f = utc ? date.getUTCMilliseconds() : date.getMilliseconds();
            format = format.replace(/(^|[^\\])fff+/g, "$1" + ii(f, 3));
            f = Math.round(f / 10);
            format = format.replace(/(^|[^\\])ff/g, "$1" + ii(f));
            f = Math.round(f / 10);
            format = format.replace(/(^|[^\\])f/g, "$1" + f);
            const T = H < 12 ? "AM" : "PM";
            format = format.replace(/(^|[^\\])TT+/g, "$1" + T);
            format = format.replace(/(^|[^\\])T/g, "$1" + T.charAt(0));
            const t = T.toLowerCase();
            format = format.replace(/(^|[^\\])tt+/g, "$1" + t);
            format = format.replace(/(^|[^\\])t/g, "$1" + t.charAt(0));
            let tz = -date.getTimezoneOffset();
            let K = utc || !tz ? "Z" : tz > 0 ? "+" : "-";
            if (!utc) {
                tz = Math.abs(tz);
                const tzHrs = Math.floor(tz / 60);
                const tzMin = tz % 60;
                K += ii(tzHrs) + ":" + ii(tzMin);
            }
            format = format.replace(/(^|[^\\])K/g, "$1" + K);
            const day = (utc ? date.getUTCDay() : date.getDay()) + 1;
            format = format.replace(new RegExp(dddd[0], "g"), dddd[day]);
            format = format.replace(new RegExp(ddd[0], "g"), ddd[day]);
            format = format.replace(new RegExp(MMMM[0], "g"), MMMM[M]);
            format = format.replace(new RegExp(MMM[0], "g"), MMM[M]);
            format = format.replace(/\\(.)/g, "$1");
            return format;
        }
        /**
         * @param {number} minX
         * @param {number} maxX
         */
        getTimeUnitsfromTimestamp(minX, maxX) {
            const w = this.w;
            if (w.config.xaxis.min !== void 0) {
                minX = w.config.xaxis.min;
            }
            if (w.config.xaxis.max !== void 0) {
                maxX = w.config.xaxis.max;
            }
            const tsMin = this.getDate(minX);
            const tsMax = this.getDate(maxX);
            const minD = this.formatDate(tsMin, "yyyy MM dd HH mm ss fff").split(" ");
            const maxD = this.formatDate(tsMax, "yyyy MM dd HH mm ss fff").split(" ");
            return {
                minMillisecond: parseInt(minD[6], 10),
                maxMillisecond: parseInt(maxD[6], 10),
                minSecond: parseInt(minD[5], 10),
                maxSecond: parseInt(maxD[5], 10),
                minMinute: parseInt(minD[4], 10),
                maxMinute: parseInt(maxD[4], 10),
                minHour: parseInt(minD[3], 10),
                maxHour: parseInt(maxD[3], 10),
                minDate: parseInt(minD[2], 10),
                maxDate: parseInt(maxD[2], 10),
                minMonth: parseInt(minD[1], 10) - 1,
                maxMonth: parseInt(maxD[1], 10) - 1,
                minYear: parseInt(minD[0], 10),
                maxYear: parseInt(maxD[0], 10)
            };
        }
        /**
         * @param {number} year
         */
        isLeapYear(year) {
            return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
        }
        /**
         * @param {number} month
         * @param {number} year
         * @param {number} subtract
         */
        calculcateLastDaysOfMonth(month, year, subtract) {
            const days = this.determineDaysOfMonths(month, year);
            return days - subtract;
        }
        /**
         * @param {number} year
         */
        determineDaysOfYear(year) {
            let days = 365;
            if (this.isLeapYear(year)) {
                days = 366;
            }
            return days;
        }
        /**
         * @param {number} year
         * @param {number} month
         * @param {number} date
         */
        determineRemainingDaysOfYear(year, month, date) {
            let dayOfYear = this.daysCntOfYear[month] + date;
            if (month > 1 && this.isLeapYear(year)) dayOfYear++;
            return dayOfYear;
        }
        /**
         * @param {number} month
         * @param {number} year
         */
        determineDaysOfMonths(month, year) {
            let days = 30;
            month = Utils$1.monthMod(month);
            switch (true) {
                case this.months30.indexOf(month) > -1:
                    if (month === 2) {
                        if (this.isLeapYear(year)) {
                            days = 29;
                        } else {
                            days = 28;
                        }
                    }
                    break;
                case this.months31.indexOf(month) > -1:
                    days = 31;
                    break;
                default:
                    days = 31;
                    break;
            }
            return days;
        }
        // ───────────────────────────────────────────────────────────────────────────
        // Pure date helpers used by the v6 single-interval TimeScale.
        // Native Date setters/getters do all rollover work (leap years, month
        // length, year crossings), eliminating the manual rollover code that was
        // the source of the historical TimeScale boundary bugs.
        // ───────────────────────────────────────────────────────────────────────────
        /**
         * Extract calendar fields from a timestamp. Month is 0-indexed (matches
         * Date.getMonth / getUTCMonth).
         *
         * @param {number} timestamp
         * @param {boolean} isUTC
         * @returns {{ year: number, month: number, date: number, hour: number, minute: number, second: number, ms: number, weekday: number }}
         */
        getDateFields(timestamp, isUTC) {
            const d = new Date(timestamp);
            return isUTC ? {
                year: d.getUTCFullYear(),
                month: d.getUTCMonth(),
                date: d.getUTCDate(),
                hour: d.getUTCHours(),
                minute: d.getUTCMinutes(),
                second: d.getUTCSeconds(),
                ms: d.getUTCMilliseconds(),
                weekday: d.getUTCDay()
            } : {
                year: d.getFullYear(),
                month: d.getMonth(),
                date: d.getDate(),
                hour: d.getHours(),
                minute: d.getMinutes(),
                second: d.getSeconds(),
                ms: d.getMilliseconds(),
                weekday: d.getDay()
            };
        }
        /**
         * Advance a timestamp by `count` units. Native setters handle cross-month,
         * cross-year, leap-year, and DST rollover correctly.
         *
         * @param {number} timestamp
         * @param {'year'|'month'|'week'|'day'|'hour'|'minute'|'second'} unit
         * @param {number} count  may be negative
         * @param {boolean} isUTC
         * @returns {number}
         */
        addInterval(timestamp, unit, count, isUTC) {
            const d = new Date(timestamp);
            if (isUTC) {
                switch (unit) {
                    case "year":
                        d.setUTCFullYear(d.getUTCFullYear() + count);
                        break;
                    case "month":
                        d.setUTCMonth(d.getUTCMonth() + count);
                        break;
                    case "week":
                        d.setUTCDate(d.getUTCDate() + count * 7);
                        break;
                    case "day":
                        d.setUTCDate(d.getUTCDate() + count);
                        break;
                    case "hour":
                        d.setUTCHours(d.getUTCHours() + count);
                        break;
                    case "minute":
                        d.setUTCMinutes(d.getUTCMinutes() + count);
                        break;
                    case "second":
                        d.setUTCSeconds(d.getUTCSeconds() + count);
                        break;
                }
            } else {
                switch (unit) {
                    case "year":
                        d.setFullYear(d.getFullYear() + count);
                        break;
                    case "month":
                        d.setMonth(d.getMonth() + count);
                        break;
                    case "week":
                        d.setDate(d.getDate() + count * 7);
                        break;
                    case "day":
                        d.setDate(d.getDate() + count);
                        break;
                    case "hour":
                        d.setHours(d.getHours() + count);
                        break;
                    case "minute":
                        d.setMinutes(d.getMinutes() + count);
                        break;
                    case "second":
                        d.setSeconds(d.getSeconds() + count);
                        break;
                }
            }
            return d.getTime();
        }
        /**
         * Snap a timestamp UP to the next boundary aligned with `step` units of
         * `unit`. Returns the input unchanged if already on a boundary. Alignment
         * rules per unit:
         *   - second: 0/step/2*step/... seconds within a minute (step must divide 60)
         *   - minute: 0/step/2*step/... minutes within an hour (step must divide 60)
         *   - hour:   0/step/... hours within a day (step must divide 24)
         *   - day:    every day (step always 1)
         *   - week:   next Monday on a `step`-week stride from a fixed epoch Monday
         *   - month:  Jan/Apr/Jul/Oct for step=3, Jan/Jul for step=6 (step must divide 12)
         *   - year:   year % step === 0
         *
         * @param {number} timestamp
         * @param {'year'|'month'|'week'|'day'|'hour'|'minute'|'second'} unit
         * @param {number} step
         * @param {boolean} isUTC
         * @returns {number}
         */
        ceilToBoundary(timestamp, unit, step, isUTC) {
            const d = new Date(timestamp);
            if (isUTC) {
                switch (unit) {
                    case "second": {
                        const s = d.getUTCSeconds();
                        const aligned = Math.ceil(s / step) * step;
                        if (aligned === s && d.getUTCMilliseconds() === 0)
                            return timestamp;
                        d.setUTCMilliseconds(0);
                        d.setUTCSeconds(aligned);
                        return d.getTime();
                    }
                    case "minute": {
                        const m = d.getUTCMinutes();
                        const aligned = Math.ceil(m / step) * step;
                        if (aligned === m && d.getUTCSeconds() === 0 && d.getUTCMilliseconds() === 0)
                            return timestamp;
                        d.setUTCMilliseconds(0);
                        d.setUTCSeconds(0);
                        d.setUTCMinutes(aligned);
                        return d.getTime();
                    }
                    case "hour": {
                        const h = d.getUTCHours();
                        const aligned = Math.ceil(h / step) * step;
                        if (aligned === h && d.getUTCMinutes() === 0 && d.getUTCSeconds() === 0 && d.getUTCMilliseconds() === 0)
                            return timestamp;
                        d.setUTCMilliseconds(0);
                        d.setUTCSeconds(0);
                        d.setUTCMinutes(0);
                        d.setUTCHours(aligned);
                        return d.getTime();
                    }
                    case "day": {
                        if (d.getUTCHours() === 0 && d.getUTCMinutes() === 0 && d.getUTCSeconds() === 0 && d.getUTCMilliseconds() === 0)
                            return timestamp;
                        d.setUTCMilliseconds(0);
                        d.setUTCSeconds(0);
                        d.setUTCMinutes(0);
                        d.setUTCHours(0);
                        d.setUTCDate(d.getUTCDate() + 1);
                        return d.getTime();
                    }
                    case "week": {
                        const MS_PER_WEEK = 7 * 24 * 60 * 60 * 1e3;
                        const REF_MONDAY_UTC = Date.UTC(1970, 0, 5);
                        d.setUTCMilliseconds(0);
                        d.setUTCSeconds(0);
                        d.setUTCMinutes(0);
                        d.setUTCHours(0);
                        const startOfDay = d.getTime();
                        const weeksSinceRef = Math.ceil(
                            (startOfDay - REF_MONDAY_UTC) / MS_PER_WEEK
                        );
                        const alignedWeeks = Math.ceil(weeksSinceRef / step) * step;
                        const aligned = REF_MONDAY_UTC + alignedWeeks * MS_PER_WEEK;
                        if (aligned >= timestamp) return aligned;
                        return aligned + step * MS_PER_WEEK;
                    }
                    case "month": {
                        const m = d.getUTCMonth();
                        const aligned = Math.ceil(m / step) * step;
                        if (aligned === m && d.getUTCDate() === 1 && d.getUTCHours() === 0 && d.getUTCMinutes() === 0 && d.getUTCSeconds() === 0 && d.getUTCMilliseconds() === 0)
                            return timestamp;
                        d.setUTCMilliseconds(0);
                        d.setUTCSeconds(0);
                        d.setUTCMinutes(0);
                        d.setUTCHours(0);
                        d.setUTCDate(1);
                        d.setUTCMonth(aligned);
                        return d.getTime();
                    }
                    case "year": {
                        const y = d.getUTCFullYear();
                        const aligned = Math.ceil(y / step) * step;
                        if (aligned === y && d.getUTCMonth() === 0 && d.getUTCDate() === 1 && d.getUTCHours() === 0 && d.getUTCMinutes() === 0 && d.getUTCSeconds() === 0 && d.getUTCMilliseconds() === 0)
                            return timestamp;
                        return Date.UTC(aligned, 0, 1);
                    }
                }
            } else {
                switch (unit) {
                    case "second": {
                        const s = d.getSeconds();
                        const aligned = Math.ceil(s / step) * step;
                        if (aligned === s && d.getMilliseconds() === 0) return timestamp;
                        d.setMilliseconds(0);
                        d.setSeconds(aligned);
                        return d.getTime();
                    }
                    case "minute": {
                        const m = d.getMinutes();
                        const aligned = Math.ceil(m / step) * step;
                        if (aligned === m && d.getSeconds() === 0 && d.getMilliseconds() === 0)
                            return timestamp;
                        d.setMilliseconds(0);
                        d.setSeconds(0);
                        d.setMinutes(aligned);
                        return d.getTime();
                    }
                    case "hour": {
                        const h = d.getHours();
                        const aligned = Math.ceil(h / step) * step;
                        if (aligned === h && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0)
                            return timestamp;
                        d.setMilliseconds(0);
                        d.setSeconds(0);
                        d.setMinutes(0);
                        d.setHours(aligned);
                        return d.getTime();
                    }
                    case "day": {
                        if (d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0)
                            return timestamp;
                        d.setMilliseconds(0);
                        d.setSeconds(0);
                        d.setMinutes(0);
                        d.setHours(0);
                        d.setDate(d.getDate() + 1);
                        return d.getTime();
                    }
                    case "week": {
                        const MS_PER_WEEK = 7 * 24 * 60 * 60 * 1e3;
                        const REF_MONDAY_LOCAL = new Date(1970, 0, 5).getTime();
                        d.setMilliseconds(0);
                        d.setSeconds(0);
                        d.setMinutes(0);
                        d.setHours(0);
                        const startOfDay = d.getTime();
                        const weeksSinceRef = Math.ceil(
                            (startOfDay - REF_MONDAY_LOCAL) / MS_PER_WEEK
                        );
                        const alignedWeeks = Math.ceil(weeksSinceRef / step) * step;
                        const aligned = REF_MONDAY_LOCAL + alignedWeeks * MS_PER_WEEK;
                        if (aligned >= timestamp) return aligned;
                        return aligned + step * MS_PER_WEEK;
                    }
                    case "month": {
                        const m = d.getMonth();
                        const aligned = Math.ceil(m / step) * step;
                        if (aligned === m && d.getDate() === 1 && d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0)
                            return timestamp;
                        d.setMilliseconds(0);
                        d.setSeconds(0);
                        d.setMinutes(0);
                        d.setHours(0);
                        d.setDate(1);
                        d.setMonth(aligned);
                        return d.getTime();
                    }
                    case "year": {
                        const y = d.getFullYear();
                        const aligned = Math.ceil(y / step) * step;
                        if (aligned === y && d.getMonth() === 0 && d.getDate() === 1 && d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0 && d.getMilliseconds() === 0)
                            return timestamp;
                        return new Date(aligned, 0, 1).getTime();
                    }
                }
            }
            return timestamp;
        }
        /**
         * Test whether a timestamp falls exactly on a unit boundary (start of year,
         * start of month, start of day, etc.). Used by the multi-resolution
         * formatter to upgrade a tick's display unit to a coarser scale.
         *
         * @param {number} timestamp
         * @param {'year'|'month'|'day'|'hour'|'minute'|'second'} unit
         * @param {boolean} isUTC
         * @returns {boolean}
         */
        isAtBoundary(timestamp, unit, isUTC) {
            const f = this.getDateFields(timestamp, isUTC);
            switch (unit) {
                case "year":
                    return f.month === 0 && f.date === 1 && f.hour === 0 && f.minute === 0 && f.second === 0 && f.ms === 0;
                case "month":
                    return f.date === 1 && f.hour === 0 && f.minute === 0 && f.second === 0 && f.ms === 0;
                case "day":
                    return f.hour === 0 && f.minute === 0 && f.second === 0 && f.ms === 0;
                case "hour":
                    return f.minute === 0 && f.second === 0 && f.ms === 0;
                case "minute":
                    return f.second === 0 && f.ms === 0;
                case "second":
                    return f.ms === 0;
            }
            return false;
        }
    }
    class Formatters {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
            this.tooltipKeyFormat = "dd MMM";
        }
        /**
         * @param {Function} fn
         * @param {any} val
         * @param {any} timestamp
         * @param {any} _opts
         */
        xLabelFormat(fn, val, timestamp, _opts) {
            const w = this.w;
            if (w.config.xaxis.type === "datetime") {
                if (w.config.xaxis.labels.formatter === void 0) {
                    if (w.config.tooltip.x.formatter === void 0) {
                        const datetimeObj = new DateTime(this.w);
                        return datetimeObj.formatDate(
                            datetimeObj.getDate(val),
                            w.config.tooltip.x.format
                        );
                    }
                }
            }
            return fn(val, timestamp, _opts);
        }
        /**
         * @param {any} val
         */
        defaultGeneralFormatter(val) {
            if (Array.isArray(val)) {
                return val.map((v) => {
                    return v;
                });
            } else {
                return val;
            }
        }
        /**
         * @param {any} v
         * @param {ApexYAxis} yaxe
         */
        defaultYFormatter(v, yaxe) {
            const w = this.w;
            if (Utils$1.isNumber(v)) {
                if (w.globals.yValueDecimal !== 0) {
                    v = v.toFixed(
                        yaxe.decimalsInFloat !== void 0 ? yaxe.decimalsInFloat : w.globals.yValueDecimal
                    );
                } else {
                    const f = v.toFixed(0);
                    v = Number(f) === v ? f : v.toFixed(1);
                }
            }
            return v;
        }
        setLabelFormatters() {
            const w = this.w;
            const fmt = w.formatters;
            fmt.xaxisTooltipFormatter = (val) => {
                return this.defaultGeneralFormatter(val);
            };
            fmt.ttKeyFormatter = (val) => {
                return this.defaultGeneralFormatter(val);
            };
            fmt.ttZFormatter = (val) => {
                return val;
            };
            fmt.legendFormatter = (val) => {
                return this.defaultGeneralFormatter(val);
            };
            if (w.config.xaxis.labels.formatter !== void 0) {
                fmt.xLabelFormatter = w.config.xaxis.labels.formatter;
            } else {
                fmt.xLabelFormatter = (val) => {
                    if (Utils$1.isNumber(val)) {
                        if (!w.config.xaxis.convertedCatToNumeric && w.config.xaxis.type === "numeric") {
                            if (Utils$1.isNumber(w.config.xaxis.decimalsInFloat)) {
                                return val.toFixed(w.config.xaxis.decimalsInFloat);
                            } else {
                                const diff = w.globals.maxX - w.globals.minX;
                                if (diff > 0) {
                                    const step = diff / 10;
                                    const decimals = Math.max(0, -Math.floor(Math.log10(step)));
                                    return val.toFixed(decimals);
                                }
                                return val.toFixed(0);
                            }
                        }
                        if (w.globals.isBarHorizontal) {
                            const range = w.globals.maxY - /** @type {any} */
                                w.globals.minYArr;
                            if (range < 4) {
                                return val.toFixed(1);
                            }
                        }
                        return val.toFixed(0);
                    }
                    return val;
                };
            }
            if (typeof w.config.tooltip.x.formatter === "function") {
                fmt.ttKeyFormatter = w.config.tooltip.x.formatter;
            } else {
                fmt.ttKeyFormatter = fmt.xLabelFormatter;
            }
            if (typeof w.config.xaxis.tooltip.formatter === "function") {
                fmt.xaxisTooltipFormatter = w.config.xaxis.tooltip.formatter;
            }
            if (Array.isArray(w.config.tooltip.y)) {
                fmt.ttVal = w.config.tooltip.y;
            } else {
                if (w.config.tooltip.y.formatter !== void 0) {
                    fmt.ttVal = w.config.tooltip.y;
                }
            }
            if (w.config.tooltip.z.formatter !== void 0) {
                fmt.ttZFormatter = w.config.tooltip.z.formatter;
            }
            if (w.config.legend.formatter !== void 0) {
                fmt.legendFormatter = w.config.legend.formatter;
            }
            fmt.yLabelFormatters = [];
            w.config.yaxis.forEach((yaxe, i) => {
                if (yaxe.labels.formatter !== void 0) {
                    fmt.yLabelFormatters[i] = yaxe.labels.formatter;
                } else {
                    fmt.yLabelFormatters[i] = (val) => {
                        if (!w.globals.xyCharts) return val;
                        if (Array.isArray(val)) {
                            return val.map((v) => {
                                return this.defaultYFormatter(v, yaxe);
                            });
                        } else {
                            return this.defaultYFormatter(val, yaxe);
                        }
                    };
                }
            });
            return w.globals;
        }
        heatmapLabelFormatters() {
            const w = this.w;
            if (w.config.chart.type === "heatmap") {
                w.globals.yAxisScale[0].result = /** @type {any} */
                    w.seriesData.seriesNames.slice();
                const longest = (
                    /** @type {any} */
                    w.seriesData.seriesNames.reduce(
                        (a, b) => a.length > b.length ? a : b,
                        0
                    )
                );
                w.globals.yAxisScale[0].niceMax = longest;
                w.globals.yAxisScale[0].niceMin = longest;
            }
        }
    }
    const getRangeValues = ({
        isTimeline,
        seriesIndex,
        dataPointIndex,
        y1,
        y2,
        w
    }) => {
        var _a;
        let start = w.rangeData.seriesRangeStart[seriesIndex][dataPointIndex];
        let end = w.rangeData.seriesRangeEnd[seriesIndex][dataPointIndex];
        let ylabel = w.labelData.labels[dataPointIndex];
        let seriesName = w.config.series[seriesIndex].name ? w.config.series[seriesIndex].name : "";
        const yLbFormatter = w.formatters.ttKeyFormatter;
        const yLbTitleFormatter = w.config.tooltip.y.title.formatter;
        const opts = {
            w,
            seriesIndex,
            dataPointIndex,
            start,
            end
        };
        if (typeof yLbTitleFormatter === "function") {
            seriesName = yLbTitleFormatter(seriesName, opts);
        }
        if ((_a = w.config.series[seriesIndex].data[dataPointIndex]) == null ? void 0 : _a.x) {
            ylabel = w.config.series[seriesIndex].data[dataPointIndex].x;
        }
        if (!isTimeline) {
            if (w.config.xaxis.type === "datetime") {
                const xFormat = new Formatters(w);
                ylabel = xFormat.xLabelFormat(
                    w.formatters.ttKeyFormatter,
                    ylabel,
                    ylabel, {
                        i: void 0,
                        dateFormatter: new DateTime(w).formatDate,
                        w
                    }
                );
            }
        }
        if (typeof yLbFormatter === "function") {
            ylabel = yLbFormatter(ylabel, opts);
        }
        if (Number.isFinite(y1) && Number.isFinite(y2)) {
            start = y1;
            end = y2;
        }
        let startVal = "";
        let endVal = "";
        const color = w.globals.colors[seriesIndex];
        if (w.config.tooltip.x.formatter === void 0) {
            if (w.config.xaxis.type === "datetime") {
                const datetimeObj = new DateTime(w);
                startVal = datetimeObj.formatDate(
                    datetimeObj.getDate(start),
                    w.config.tooltip.x.format
                );
                endVal = datetimeObj.formatDate(
                    datetimeObj.getDate(end),
                    w.config.tooltip.x.format
                );
            } else {
                startVal = start;
                endVal = end;
            }
        } else {
            startVal = w.config.tooltip.x.formatter(start);
            endVal = w.config.tooltip.x.formatter(end);
        }
        return {
            start,
            end,
            startVal,
            endVal,
            ylabel,
            color,
            seriesName
        };
    };
    const buildRangeTooltipHTML = (opts) => {
        let {
            color,
            seriesName,
            ylabel,
            start,
            end,
            seriesIndex,
            dataPointIndex
        } = opts;
        const formatter = opts.w.globals.tooltip.tooltipLabels.getFormatters(seriesIndex);
        start = formatter.yLbFormatter(start);
        end = formatter.yLbFormatter(end);
        const val = formatter.yLbFormatter(
            opts.w.seriesData.series[seriesIndex][dataPointIndex]
        );
        let valueHTML = "";
        const rangeValues = `<span class="value start-value">
  ${start}
  </span> <span class="separator">-</span> <span class="value end-value">
  ${end}
  </span>`;
        if (opts.w.globals.comboCharts) {
            if (opts.w.config.series[seriesIndex].type === "rangeArea" || opts.w.config.series[seriesIndex].type === "rangeBar") {
                valueHTML = rangeValues;
            } else {
                valueHTML = `<span>${val}</span>`;
            }
        } else {
            valueHTML = rangeValues;
        }
        return '<div class="apexcharts-tooltip-rangebar"><div> <span class="series-name" style="color: ' + color + '">' + (seriesName ? seriesName : "") + '</span></div><div> <span class="category">' + ylabel + ": </span> " + valueHTML + " </div></div>";
    };
    class Defaults {
        /**
         * @param {Record<string, any>} opts
         */
        constructor(opts) {
            this.opts = opts;
        }
        hideYAxis() {
            this.opts.yaxis[0].show = false;
            this.opts.yaxis[0].title.text = "";
            this.opts.yaxis[0].axisBorder.show = false;
            this.opts.yaxis[0].axisTicks.show = false;
            this.opts.yaxis[0].floating = true;
        }
        line() {
            return {
                dataLabels: {
                    enabled: false
                },
                stroke: {
                    width: 5,
                    curve: "straight"
                },
                markers: {
                    size: 0,
                    hover: {
                        sizeOffset: 6
                    }
                },
                xaxis: {
                    crosshairs: {
                        width: 1
                    }
                }
            };
        }
        /**
         * @param {Record<string, any>} defaults
         */
        sparkline(defaults) {
            this.hideYAxis();
            const ret = {
                grid: {
                    show: false,
                    padding: {
                        left: 0,
                        right: 0,
                        top: 0,
                        bottom: 0
                    }
                },
                legend: {
                    show: false
                },
                xaxis: {
                    labels: {
                        show: false
                    },
                    tooltip: {
                        enabled: false
                    },
                    axisBorder: {
                        show: false
                    },
                    axisTicks: {
                        show: false
                    }
                },
                chart: {
                    toolbar: {
                        show: false
                    },
                    zoom: {
                        enabled: false
                    }
                },
                dataLabels: {
                    enabled: false
                }
            };
            return Utils$1.extend(defaults, ret);
        }
        slope() {
            this.hideYAxis();
            return {
                chart: {
                    toolbar: {
                        show: false
                    },
                    zoom: {
                        enabled: false
                    }
                },
                dataLabels: {
                    enabled: true,
                    /**
                     * @param {any} val
                     * @param {Record<string, any>} opts
                     */
                    formatter(val, opts) {
                        const seriesName = opts.w.config.series[opts.seriesIndex].name;
                        return val !== null ? seriesName + ": " + val : "";
                    },
                    background: {
                        enabled: false
                    },
                    offsetX: -5
                },
                grid: {
                    xaxis: {
                        lines: {
                            show: true
                        }
                    },
                    yaxis: {
                        lines: {
                            show: false
                        }
                    }
                },
                xaxis: {
                    position: "top",
                    labels: {
                        style: {
                            fontSize: 14,
                            fontWeight: 900
                        }
                    },
                    tooltip: {
                        enabled: false
                    },
                    crosshairs: {
                        show: false
                    }
                },
                markers: {
                    size: 8,
                    hover: {
                        sizeOffset: 1
                    }
                },
                legend: {
                    show: false
                },
                tooltip: {
                    shared: false,
                    intersect: true,
                    followCursor: true
                },
                stroke: {
                    width: 5,
                    curve: "straight"
                }
            };
        }
        bar() {
            return {
                chart: {
                    stacked: false
                },
                plotOptions: {
                    bar: {
                        dataLabels: {
                            position: "center"
                        }
                    }
                },
                dataLabels: {
                    style: {
                        colors: ["#fff"]
                    },
                    background: {
                        enabled: false
                    }
                },
                stroke: {
                    width: 0,
                    lineCap: "square"
                },
                fill: {
                    opacity: 0.85
                },
                legend: {
                    markers: {
                        shape: "square"
                    }
                },
                tooltip: {
                    shared: false,
                    intersect: true
                },
                xaxis: {
                    tooltip: {
                        enabled: false
                    },
                    tickPlacement: "between",
                    crosshairs: {
                        width: "barWidth",
                        position: "back",
                        fill: {
                            type: "gradient"
                        },
                        dropShadow: {
                            enabled: false
                        },
                        stroke: {
                            width: 0
                        }
                    }
                }
            };
        }
        funnel() {
            this.hideYAxis();
            return __spreadProps(__spreadValues({}, this.bar()), {
                chart: {
                    animations: {
                        speed: 800,
                        animateGradually: {
                            enabled: false
                        }
                    }
                },
                plotOptions: {
                    bar: {
                        horizontal: true,
                        borderRadiusApplication: "around",
                        borderRadius: 0,
                        dataLabels: {
                            position: "center"
                        }
                    }
                },
                grid: {
                    show: false,
                    padding: {
                        left: 0,
                        right: 0
                    }
                },
                xaxis: {
                    labels: {
                        show: false
                    },
                    tooltip: {
                        enabled: false
                    },
                    axisBorder: {
                        show: false
                    },
                    axisTicks: {
                        show: false
                    }
                }
            });
        }
        pyramid() {
            return this.funnel();
        }
        gauge() {
            const base = this.radialBar();
            return __spreadProps(__spreadValues({}, base), {
                plotOptions: {
                    radialBar: {
                        startAngle: -135,
                        endAngle: 135,
                        hollow: {
                            margin: 0,
                            size: "60%"
                        },
                        track: {
                            background: "#e7e7e7",
                            strokeWidth: "100%",
                            margin: 5
                        },
                        dataLabels: {
                            name: {
                                show: false
                            },
                            value: {
                                show: true,
                                fontSize: "32px",
                                fontWeight: 600,
                                offsetY: 8
                            }
                        }
                    }
                }
            });
        }
        candlestick() {
            return {
                stroke: {
                    width: 1
                },
                fill: {
                    opacity: 1
                },
                dataLabels: {
                    enabled: false
                },
                tooltip: {
                    shared: true,
                    custom: ({
                        seriesIndex,
                        dataPointIndex,
                        w
                    }) => {
                        return this._getBoxTooltip(
                            w,
                            seriesIndex,
                            dataPointIndex,
                            ["Open", "High", "", "Low", "Close"],
                            "candlestick"
                        );
                    }
                },
                states: {
                    active: {
                        filter: {
                            type: "none"
                        }
                    }
                },
                xaxis: {
                    crosshairs: {
                        width: 1
                    }
                }
            };
        }
        boxPlot() {
            return {
                chart: {
                    animations: {
                        dynamicAnimation: {
                            enabled: false
                        }
                    }
                },
                stroke: {
                    width: 1,
                    colors: ["#24292e"]
                },
                dataLabels: {
                    enabled: false
                },
                tooltip: {
                    shared: true,
                    custom: ({
                        seriesIndex,
                        dataPointIndex,
                        w
                    }) => {
                        return this._getBoxTooltip(
                            w,
                            seriesIndex,
                            dataPointIndex,
                            ["Minimum", "Q1", "Median", "Q3", "Maximum"],
                            "boxPlot"
                        );
                    }
                },
                markers: {
                    size: 7,
                    strokeWidth: 1,
                    strokeColors: "#111"
                },
                xaxis: {
                    crosshairs: {
                        width: 1
                    }
                }
            };
        }
        rangeBar() {
            const handleTimelineTooltip = (opts) => {
                const {
                    color,
                    seriesName,
                    ylabel,
                    startVal,
                    endVal
                } = getRangeValues(__spreadProps(__spreadValues({}, opts), {
                    isTimeline: true
                }));
                return buildRangeTooltipHTML(__spreadProps(__spreadValues({}, opts), {
                    color,
                    seriesName,
                    ylabel,
                    start: startVal,
                    end: endVal
                }));
            };
            const handleRangeColumnTooltip = (opts) => {
                const {
                    color,
                    seriesName,
                    ylabel,
                    start,
                    end
                } = getRangeValues(opts);
                return buildRangeTooltipHTML(__spreadProps(__spreadValues({}, opts), {
                    color,
                    seriesName,
                    ylabel,
                    start,
                    end
                }));
            };
            return {
                chart: {
                    animations: {
                        animateGradually: false
                    }
                },
                stroke: {
                    width: 0,
                    lineCap: "square"
                },
                plotOptions: {
                    bar: {
                        borderRadius: 0,
                        dataLabels: {
                            position: "center"
                        }
                    }
                },
                dataLabels: {
                    enabled: false,
                    /**
                     * @param {any} val
                     */
                    formatter(val, {
                        seriesIndex,
                        dataPointIndex,
                        w
                    }) {
                        const getVal = () => {
                            const start = w.rangeData.seriesRangeStart[seriesIndex][dataPointIndex];
                            const end = w.rangeData.seriesRangeEnd[seriesIndex][dataPointIndex];
                            return end - start;
                        };
                        if (w.globals.comboCharts) {
                            if (w.config.series[seriesIndex].type === "rangeBar" || w.config.series[seriesIndex].type === "rangeArea") {
                                return getVal();
                            } else {
                                return val;
                            }
                        } else {
                            return getVal();
                        }
                    },
                    background: {
                        enabled: false
                    },
                    style: {
                        colors: ["#fff"]
                    }
                },
                markers: {
                    size: 10
                },
                tooltip: {
                    shared: false,
                    followCursor: true,
                    /**
                     * @param {Record<string, any>} opts
                     */
                    custom(opts) {
                        if (opts.w.config.plotOptions && opts.w.config.plotOptions.bar && opts.w.config.plotOptions.bar.horizontal) {
                            return handleTimelineTooltip(opts);
                        } else {
                            return handleRangeColumnTooltip(opts);
                        }
                    }
                },
                xaxis: {
                    tickPlacement: "between",
                    tooltip: {
                        enabled: false
                    },
                    crosshairs: {
                        stroke: {
                            width: 0
                        }
                    }
                }
            };
        }
        /**
         * @param {Record<string, any>} opts
         */
        dumbbell(opts) {
            var _a, _b;
            if (!((_a = opts.plotOptions.bar) == null ? void 0 : _a.barHeight)) {
                opts.plotOptions.bar.barHeight = 2;
            }
            if (!((_b = opts.plotOptions.bar) == null ? void 0 : _b.columnWidth)) {
                opts.plotOptions.bar.columnWidth = 2;
            }
            return opts;
        }
        area() {
            return {
                stroke: {
                    width: 4,
                    fill: {
                        type: "solid",
                        gradient: {
                            inverseColors: false,
                            shade: "light",
                            type: "vertical",
                            opacityFrom: 0.65,
                            opacityTo: 0.5,
                            stops: [0, 100, 100]
                        }
                    }
                },
                fill: {
                    type: "gradient",
                    gradient: {
                        inverseColors: false,
                        shade: "light",
                        type: "vertical",
                        opacityFrom: 0.65,
                        opacityTo: 0.5,
                        stops: [0, 100, 100]
                    }
                },
                markers: {
                    size: 0,
                    hover: {
                        sizeOffset: 6
                    }
                },
                tooltip: {
                    followCursor: false
                }
            };
        }
        rangeArea() {
            const handleRangeAreaTooltip = (opts) => {
                const {
                    color,
                    seriesName,
                    ylabel,
                    start,
                    end
                } = getRangeValues(opts);
                return buildRangeTooltipHTML(__spreadProps(__spreadValues({}, opts), {
                    color,
                    seriesName,
                    ylabel,
                    start,
                    end
                }));
            };
            return {
                stroke: {
                    curve: "straight",
                    width: 0
                },
                fill: {
                    type: "solid",
                    opacity: 0.6
                },
                markers: {
                    size: 0
                },
                states: {
                    hover: {
                        filter: {
                            type: "none"
                        }
                    },
                    active: {
                        filter: {
                            type: "none"
                        }
                    }
                },
                tooltip: {
                    intersect: false,
                    shared: true,
                    followCursor: true,
                    /**
                     * @param {Record<string, any>} opts
                     */
                    custom(opts) {
                        return handleRangeAreaTooltip(opts);
                    }
                }
            };
        }
        /**
         * @param {Record<string, any>} defaults
         */
        brush(defaults) {
            const ret = {
                chart: {
                    toolbar: {
                        autoSelected: "selection",
                        show: false
                    },
                    zoom: {
                        enabled: false
                    }
                },
                dataLabels: {
                    enabled: false
                },
                stroke: {
                    width: 1
                },
                tooltip: {
                    enabled: false
                },
                xaxis: {
                    tooltip: {
                        enabled: false
                    }
                }
            };
            return Utils$1.extend(defaults, ret);
        }
        /**
         * @param {Record<string, any>} opts
         */
        stacked100(opts) {
            opts.dataLabels = opts.dataLabels || {};
            opts.dataLabels.formatter = opts.dataLabels.formatter || void 0;
            const existingDataLabelFormatter = opts.dataLabels.formatter;
            opts.yaxis.forEach((yaxe, index) => {
                opts.yaxis[index].min = 0;
                opts.yaxis[index].max = 100;
            });
            const isBar = opts.chart.type === "bar";
            if (isBar) {
                opts.dataLabels.formatter = existingDataLabelFormatter ||
                    /**
                     * @param {any} val
                     */
                    function(val) {
                        if (typeof val === "number") {
                            return val ? val.toFixed(0) + "%" : val;
                        }
                        return val;
                    };
            }
            return opts;
        }
        stackedBars() {
            const barDefaults = this.bar();
            return __spreadProps(__spreadValues({}, barDefaults), {
                plotOptions: __spreadProps(__spreadValues({}, barDefaults.plotOptions), {
                    bar: __spreadProps(__spreadValues({}, barDefaults.plotOptions.bar), {
                        borderRadiusApplication: "end",
                        borderRadiusWhenStacked: "last"
                    })
                })
            });
        }
        // This function removes the left and right spacing in chart for line/area/scatter if xaxis type = category for those charts by converting xaxis = numeric. Numeric/Datetime xaxis prevents the unnecessary spacing in the left/right of the chart area
        /**
         * @param {Record<string, any>} opts
         */
        convertCatToNumeric(opts) {
            opts.xaxis.convertedCatToNumeric = true;
            return opts;
        }
        /**
         * @param {Record<string, any>} opts
         * @param {any} cats
         */
        convertCatToNumericXaxis(opts, cats) {
            opts.xaxis.type = "numeric";
            opts.xaxis.labels = opts.xaxis.labels || {};
            opts.xaxis.labels.formatter = opts.xaxis.labels.formatter ||
                /**
                 * @param {any} val
                 */
                function(val) {
                    return Utils$1.isNumber(val) ? Math.floor(val) : val;
                };
            const defaultFormatter = opts.xaxis.labels.formatter;
            let labels = opts.xaxis.categories && opts.xaxis.categories.length ? opts.xaxis.categories : opts.labels;
            if (cats && cats.length) {
                labels = cats.map((c) => {
                    return Array.isArray(c) ? c : String(c);
                });
            }
            if (labels && labels.length) {
                opts.xaxis.labels.formatter = function(val) {
                    return Utils$1.isNumber(val) ? defaultFormatter(labels[Math.floor(val) - 1]) : defaultFormatter(val);
                };
            }
            opts.xaxis.categories = [];
            opts.labels = [];
            opts.xaxis.tickAmount = opts.xaxis.tickAmount || "dataPoints";
            return opts;
        }
        bubble() {
            return {
                dataLabels: {
                    style: {
                        colors: ["#fff"]
                    }
                },
                tooltip: {
                    shared: false,
                    intersect: true
                },
                xaxis: {
                    crosshairs: {
                        width: 0
                    }
                },
                fill: {
                    type: "solid",
                    gradient: {
                        shade: "light",
                        inverse: true,
                        shadeIntensity: 0.55,
                        opacityFrom: 0.4,
                        opacityTo: 0.8
                    }
                }
            };
        }
        scatter() {
            return {
                dataLabels: {
                    enabled: false
                },
                tooltip: {
                    shared: false,
                    intersect: true
                },
                markers: {
                    size: 6,
                    strokeWidth: 1,
                    hover: {
                        sizeOffset: 2
                    }
                }
            };
        }
        heatmap() {
            return {
                chart: {
                    stacked: false
                },
                fill: {
                    opacity: 1
                },
                dataLabels: {
                    style: {
                        colors: ["#fff"]
                    }
                },
                stroke: {
                    colors: ["#fff"]
                },
                tooltip: {
                    followCursor: true,
                    marker: {
                        show: false
                    },
                    x: {
                        show: false
                    }
                },
                legend: {
                    position: "top",
                    markers: {
                        shape: "square"
                    }
                },
                grid: {
                    padding: {
                        right: 20
                    }
                }
            };
        }
        treemap() {
            return {
                chart: {
                    zoom: {
                        enabled: false
                    }
                },
                dataLabels: {
                    style: {
                        fontSize: 14,
                        fontWeight: 600,
                        colors: ["#fff"]
                    }
                },
                stroke: {
                    show: true,
                    width: 2,
                    colors: ["#fff"]
                },
                legend: {
                    show: false
                },
                fill: {
                    opacity: 1,
                    gradient: {
                        stops: [0, 100]
                    }
                },
                tooltip: {
                    followCursor: true,
                    x: {
                        show: false
                    }
                },
                grid: {
                    padding: {
                        left: 0,
                        right: 0
                    }
                },
                xaxis: {
                    crosshairs: {
                        show: false
                    },
                    tooltip: {
                        enabled: false
                    }
                }
            };
        }
        pie() {
            return {
                chart: {
                    toolbar: {
                        show: false
                    }
                },
                plotOptions: {
                    pie: {
                        donut: {
                            labels: {
                                show: false
                            }
                        }
                    }
                },
                dataLabels: {
                    /**
                     * @param {number} val
                     */
                    formatter(val) {
                        return val.toFixed(1) + "%";
                    },
                    style: {
                        colors: ["#fff"]
                    },
                    background: {
                        enabled: false
                    },
                    dropShadow: {
                        enabled: true
                    }
                },
                stroke: {
                    colors: ["#fff"]
                },
                fill: {
                    opacity: 1,
                    gradient: {
                        shade: "light",
                        stops: [0, 100]
                    }
                },
                tooltip: {
                    theme: "dark",
                    fillSeriesColor: true
                },
                legend: {
                    position: "right"
                },
                grid: {
                    padding: {
                        left: 0,
                        right: 0,
                        top: 0,
                        bottom: 0
                    }
                }
            };
        }
        donut() {
            return {
                chart: {
                    toolbar: {
                        show: false
                    }
                },
                dataLabels: {
                    /**
                     * @param {number} val
                     */
                    formatter(val) {
                        return val.toFixed(1) + "%";
                    },
                    style: {
                        colors: ["#fff"]
                    },
                    background: {
                        enabled: false
                    },
                    dropShadow: {
                        enabled: true
                    }
                },
                stroke: {
                    colors: ["#fff"]
                },
                fill: {
                    opacity: 1,
                    gradient: {
                        shade: "light",
                        shadeIntensity: 0.35,
                        stops: [80, 100],
                        opacityFrom: 1,
                        opacityTo: 1
                    }
                },
                tooltip: {
                    theme: "dark",
                    fillSeriesColor: true
                },
                legend: {
                    position: "right"
                },
                grid: {
                    padding: {
                        left: 0,
                        right: 0,
                        top: 0,
                        bottom: 0
                    }
                }
            };
        }
        polarArea() {
            return {
                chart: {
                    toolbar: {
                        show: false
                    }
                },
                dataLabels: {
                    /**
                     * @param {number} val
                     */
                    formatter(val) {
                        return val.toFixed(1) + "%";
                    },
                    enabled: false
                },
                stroke: {
                    show: true,
                    width: 2
                },
                fill: {
                    opacity: 0.7
                },
                tooltip: {
                    theme: "dark",
                    fillSeriesColor: true
                },
                legend: {
                    position: "right"
                },
                grid: {
                    padding: {
                        left: 0,
                        right: 0,
                        top: 0,
                        bottom: 0
                    }
                }
            };
        }
        radar() {
            this.opts.yaxis[0].labels.offsetY = this.opts.yaxis[0].labels.offsetY ? this.opts.yaxis[0].labels.offsetY : 6;
            return {
                dataLabels: {
                    enabled: false,
                    style: {
                        fontSize: "11px"
                    }
                },
                stroke: {
                    width: 2
                },
                markers: {
                    size: 5,
                    strokeWidth: 1,
                    strokeOpacity: 1
                },
                fill: {
                    opacity: 0.2
                },
                tooltip: {
                    shared: false,
                    intersect: true,
                    followCursor: true
                },
                grid: {
                    show: false,
                    padding: {
                        left: 0,
                        right: 0,
                        top: 0,
                        bottom: 0
                    }
                },
                xaxis: {
                    labels: {
                        formatter: (val) => val,
                        style: {
                            colors: ["#a8a8a8"],
                            fontSize: "11px"
                        }
                    },
                    tooltip: {
                        enabled: false
                    },
                    crosshairs: {
                        show: false
                    }
                }
            };
        }
        radialBar() {
            return {
                chart: {
                    animations: {
                        dynamicAnimation: {
                            enabled: true,
                            speed: 800
                        }
                    },
                    toolbar: {
                        show: false
                    }
                },
                stroke: {
                    // Radial value arcs are stroked open arcs; square/round caps would
                    // extend the stroke half a stroke-width past each endpoint, making
                    // the "starting edge" visibly stick out past the geometric arc.
                    // Butt cap is the only one that aligns with the arc's true angular
                    // span. Without this, a chart that previously was a bar (whose
                    // defaults set lineCap='square') would carry that cap across into
                    // the radial render after a type morph.
                    lineCap: "butt"
                },
                fill: {
                    gradient: {
                        shade: "dark",
                        shadeIntensity: 0.4,
                        inverseColors: false,
                        type: "diagonal2",
                        opacityFrom: 1,
                        opacityTo: 1,
                        stops: [70, 98, 100]
                    }
                },
                legend: {
                    show: false,
                    position: "right"
                },
                tooltip: {
                    enabled: false,
                    fillSeriesColor: true
                },
                grid: {
                    padding: {
                        left: 0,
                        right: 0,
                        top: 0,
                        bottom: 0
                    }
                }
            };
        }
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {number} seriesIndex
         * @param {number} dataPointIndex
         * @param {any[]} labels
         * @param {string} chartType
         */
        _getBoxTooltip(w, seriesIndex, dataPointIndex, labels, chartType) {
            const o = w.candleData.seriesCandleO[seriesIndex][dataPointIndex];
            const h = w.candleData.seriesCandleH[seriesIndex][dataPointIndex];
            const m = w.candleData.seriesCandleM[seriesIndex][dataPointIndex];
            const l = w.candleData.seriesCandleL[seriesIndex][dataPointIndex];
            const c = w.candleData.seriesCandleC[seriesIndex][dataPointIndex];
            const _si = (
                /** @type {Record<string,any>} */
                w.config.series[seriesIndex]
            );
            if (_si.type && _si.type !== chartType) {
                return `<div class="apexcharts-custom-tooltip">
          ${_si.name ? _si.name : "series-" + (seriesIndex + 1)}: <strong>${w.seriesData.series[seriesIndex][dataPointIndex]}</strong>
        </div>`;
            } else {
                return `<div class="apexcharts-tooltip-box apexcharts-tooltip-${w.config.chart.type}"><div>${labels[0]}: <span class="value">` + o + `</span></div><div>${labels[1]}: <span class="value">` + h + "</span></div>" + (m ? `<div>${labels[2]}: <span class="value">` + m + "</span></div>" : "") + `<div>${labels[3]}: <span class="value">` + l + `</span></div><div>${labels[4]}: <span class="value">` + c + "</span></div></div>";
            }
        }
    }
    const name = "en";
    const options = {
        "months": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
        "shortMonths": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
        "days": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
        "shortDays": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
        "toolbar": {
            "exportToSVG": "Download SVG",
            "exportToPNG": "Download PNG",
            "exportToCSV": "Download CSV",
            "menu": "Menu",
            "selection": "Selection",
            "selectionZoom": "Selection Zoom",
            "zoomIn": "Zoom In",
            "zoomOut": "Zoom Out",
            "pan": "Panning",
            "reset": "Reset Zoom"
        }
    };
    const en = {
        name,
        options
    };
    class Options {
        constructor() {
            this.yAxis = {
                show: true,
                showAlways: false,
                showForNullSeries: true,
                seriesName: void 0,
                opposite: false,
                reversed: false,
                logarithmic: false,
                logBase: 10,
                tickAmount: void 0,
                stepSize: void 0,
                forceNiceScale: false,
                alignZero: false,
                max: void 0,
                min: void 0,
                floating: false,
                decimalsInFloat: void 0,
                labels: {
                    show: true,
                    showDuplicates: false,
                    minWidth: 0,
                    maxWidth: 160,
                    offsetX: 0,
                    offsetY: 0,
                    align: void 0,
                    rotate: 0,
                    padding: 20,
                    style: {
                        colors: [],
                        fontSize: "11px",
                        fontWeight: 400,
                        fontFamily: void 0,
                        cssClass: ""
                    },
                    formatter: void 0
                },
                axisBorder: {
                    show: false,
                    color: "#e0e0e0",
                    width: 1,
                    offsetX: 0,
                    offsetY: 0
                },
                axisTicks: {
                    show: false,
                    color: "#e0e0e0",
                    width: 6,
                    offsetX: 0,
                    offsetY: 0
                },
                title: {
                    text: void 0,
                    rotate: -90,
                    offsetY: 0,
                    offsetX: 0,
                    style: {
                        color: void 0,
                        fontSize: "11px",
                        fontWeight: 900,
                        fontFamily: void 0,
                        cssClass: ""
                    }
                },
                tooltip: {
                    enabled: false,
                    offsetX: 0
                },
                crosshairs: {
                    show: true,
                    position: "front",
                    stroke: {
                        color: "#b6b6b6",
                        width: 1,
                        dashArray: 0
                    }
                }
            };
            this.pointAnnotation = {
                id: void 0,
                x: 0,
                y: null,
                yAxisIndex: 0,
                seriesIndex: void 0,
                mouseEnter: void 0,
                mouseLeave: void 0,
                click: void 0,
                marker: {
                    size: 4,
                    fillColor: "#fff",
                    strokeWidth: 2,
                    strokeColor: "#333",
                    shape: "circle",
                    offsetX: 0,
                    offsetY: 0,
                    // radius: 2, // DEPRECATED
                    cssClass: ""
                },
                label: {
                    borderColor: "#c2c2c2",
                    borderWidth: 1,
                    borderRadius: 2,
                    text: void 0,
                    textAnchor: "middle",
                    offsetX: 0,
                    offsetY: 0,
                    mouseEnter: void 0,
                    mouseLeave: void 0,
                    click: void 0,
                    style: {
                        background: "#fff",
                        color: void 0,
                        fontSize: "11px",
                        fontFamily: void 0,
                        fontWeight: 400,
                        cssClass: "",
                        padding: {
                            left: 5,
                            right: 5,
                            top: 2,
                            bottom: 2
                        }
                    }
                },
                customSVG: {
                    // this will be deprecated in the next major version as it is going to be replaced with a better alternative below (image)
                    SVG: void 0,
                    cssClass: void 0,
                    offsetX: 0,
                    offsetY: 0
                },
                image: {
                    path: void 0,
                    width: 20,
                    height: 20,
                    offsetX: 0,
                    offsetY: 0
                }
            };
            this.yAxisAnnotation = {
                id: void 0,
                y: 0,
                y2: null,
                strokeDashArray: 1,
                fillColor: "#c2c2c2",
                borderColor: "#c2c2c2",
                borderWidth: 1,
                opacity: 0.3,
                offsetX: 0,
                offsetY: 0,
                width: "100%",
                yAxisIndex: 0,
                label: {
                    borderColor: "#c2c2c2",
                    borderWidth: 1,
                    borderRadius: 2,
                    text: void 0,
                    textAnchor: "end",
                    position: "right",
                    offsetX: 0,
                    offsetY: -3,
                    mouseEnter: void 0,
                    mouseLeave: void 0,
                    click: void 0,
                    style: {
                        background: "#fff",
                        color: void 0,
                        fontSize: "11px",
                        fontFamily: void 0,
                        fontWeight: 400,
                        cssClass: "",
                        padding: {
                            left: 5,
                            right: 5,
                            top: 2,
                            bottom: 2
                        }
                    }
                }
            };
            this.xAxisAnnotation = {
                id: void 0,
                x: 0,
                x2: null,
                strokeDashArray: 1,
                fillColor: "#c2c2c2",
                borderColor: "#c2c2c2",
                borderWidth: 1,
                opacity: 0.3,
                offsetX: 0,
                offsetY: 0,
                label: {
                    borderColor: "#c2c2c2",
                    borderWidth: 1,
                    borderRadius: 2,
                    text: void 0,
                    textAnchor: "middle",
                    orientation: "vertical",
                    position: "top",
                    offsetX: 0,
                    offsetY: 0,
                    mouseEnter: void 0,
                    mouseLeave: void 0,
                    click: void 0,
                    style: {
                        background: "#fff",
                        color: void 0,
                        fontSize: "11px",
                        fontFamily: void 0,
                        fontWeight: 400,
                        cssClass: "",
                        padding: {
                            left: 5,
                            right: 5,
                            top: 2,
                            bottom: 2
                        }
                    }
                }
            };
            this.text = {
                x: 0,
                y: 0,
                text: "",
                textAnchor: "start",
                foreColor: void 0,
                fontSize: "13px",
                fontFamily: void 0,
                fontWeight: 400,
                appendTo: ".apexcharts-annotations",
                backgroundColor: "transparent",
                borderColor: "#c2c2c2",
                borderRadius: 0,
                borderWidth: 0,
                paddingLeft: 4,
                paddingRight: 4,
                paddingTop: 2,
                paddingBottom: 2
            };
        }
        init() {
            return {
                annotations: {
                    yaxis: [this.yAxisAnnotation],
                    xaxis: [this.xAxisAnnotation],
                    points: [this.pointAnnotation],
                    texts: [],
                    images: [],
                    shapes: []
                },
                chart: {
                    animations: {
                        // Master switch — set false to render charts without any animation.
                        // Each chart type gets a tailored initial-mount animation by default:
                        //   line/area/rangeArea/radar: pen-stroke draw + radial fill bloom
                        //   bar/stacked/range/funnel:  grow from baseline (+ stagger)
                        //   scatter/bubble:            scale-up pop with overshoot
                        //   heatmap:                   diagonal-wave cell reveal
                        //   treemap:                   largest-tile-first cascade
                        //   pie/donut/polar/gauge:     arc sweep + needle settle
                        // Speed is controlled by `speed`; per-element stagger by
                        // `animateGradually.enabled` / `animateGradually.delay`.
                        enabled: true,
                        speed: 800,
                        animateGradually: {
                            // Drives per-element stagger across all chart types. When enabled,
                            // bars/heatmap-cells/scatter-points/treemap-tiles reveal in
                            // sequence; line/area markers fade in progressively along the
                            // draw. `delay` is the requested step in ms (auto-capped per
                            // chart so total stagger ≤ ~half the animation duration).
                            delay: 150,
                            enabled: true
                        },
                        dynamicAnimation: {
                            // Data-change (updateSeries) animation. Independent from the
                            // initial-mount animations above.
                            enabled: true,
                            speed: 350
                        },
                        chartTypeMorph: {
                            // Cross-type morph (updateOptions changing chart.type). Bridges
                            // the destroy+recreate flicker by sampling source + target paths
                            // into N evenly-spaced perimeter points and tweening point-by-point
                            // with rotation-search alignment, so the transition is always smooth
                            // and non-self-intersecting even between very different shapes (bar
                            // rect ↔ pie wedge / radial arc). Supported pairs include bar ↔
                            // pie / donut / radialBar / polarArea / funnel / pyramid (plus the
                            // trivial pie ↔ donut ↔ polarArea cases). Falls back to instant
                            // snap when types or data shape are incompatible.
                            enabled: true,
                            speed: 600
                        },
                        // Honor the OS-level prefers-reduced-motion setting. When true (default)
                        // and the user has the accessibility preference enabled, all initial-mount
                        // animations are skipped and the chart renders instantly.
                        respectReducedMotion: true
                    },
                    background: "",
                    locales: [en],
                    defaultLocale: "en",
                    dropShadow: {
                        enabled: false,
                        enabledOnSeries: void 0,
                        top: 2,
                        left: 2,
                        blur: 4,
                        color: "#000",
                        opacity: 0.7
                    },
                    events: {
                        animationEnd: void 0,
                        beforeMount: void 0,
                        mounted: void 0,
                        updated: void 0,
                        click: void 0,
                        mouseMove: void 0,
                        mouseLeave: void 0,
                        xAxisLabelClick: void 0,
                        legendClick: void 0,
                        markerClick: void 0,
                        selection: void 0,
                        dataPointSelection: void 0,
                        dataPointMouseEnter: void 0,
                        dataPointMouseLeave: void 0,
                        beforeZoom: void 0,
                        beforeResetZoom: void 0,
                        zoomed: void 0,
                        scrolled: void 0,
                        brushScrolled: void 0,
                        keyDown: void 0,
                        keyUp: void 0
                    },
                    foreColor: "#373d3f",
                    fontFamily: "Helvetica, Arial, sans-serif",
                    height: "auto",
                    parentHeightOffset: 15,
                    redrawOnParentResize: true,
                    redrawOnWindowResize: true,
                    id: void 0,
                    group: void 0,
                    nonce: void 0,
                    offsetX: 0,
                    offsetY: 0,
                    injectStyleSheet: true,
                    selection: {
                        enabled: false,
                        type: "x",
                        // selectedPoints: undefined, // default datapoints that should be selected automatically
                        fill: {
                            color: "#24292e",
                            opacity: 0.1
                        },
                        stroke: {
                            width: 1,
                            color: "#24292e",
                            opacity: 0.4,
                            dashArray: 3
                        },
                        xaxis: {
                            min: void 0,
                            max: void 0
                        },
                        yaxis: {
                            min: void 0,
                            max: void 0
                        }
                    },
                    sparkline: {
                        enabled: false
                    },
                    brush: {
                        enabled: false,
                        autoScaleYaxis: true,
                        target: void 0,
                        targets: void 0
                    },
                    stacked: false,
                    stackOnlyBar: true,
                    // mixed chart with stacked bars and line series - incorrect line draw #907
                    stackType: "normal",
                    toolbar: {
                        show: true,
                        offsetX: 0,
                        offsetY: 0,
                        tools: {
                            download: true,
                            selection: true,
                            zoom: true,
                            zoomin: true,
                            zoomout: true,
                            pan: true,
                            reset: true,
                            customIcons: []
                        },
                        export: {
                            csv: {
                                filename: void 0,
                                columnDelimiter: ",",
                                headerCategory: "category",
                                headerValue: "value",
                                categoryFormatter: void 0,
                                valueFormatter: void 0
                            },
                            png: {
                                filename: void 0
                            },
                            svg: {
                                filename: void 0
                            },
                            scale: void 0,
                            width: void 0
                        },
                        autoSelected: "zoom"
                        // accepts -> zoom, pan, selection
                    },
                    type: "line",
                    width: "100%",
                    zoom: {
                        enabled: true,
                        type: "x",
                        autoScaleYaxis: false,
                        allowMouseWheelZoom: true,
                        zoomedArea: {
                            fill: {
                                color: "#90CAF9",
                                opacity: 0.4
                            },
                            stroke: {
                                color: "#0D47A1",
                                opacity: 0.4,
                                width: 1
                            }
                        }
                    },
                    accessibility: {
                        enabled: true,
                        description: void 0,
                        announcements: {
                            enabled: true
                        },
                        keyboard: {
                            enabled: true,
                            navigation: {
                                enabled: true,
                                wrapAround: false
                            }
                        }
                    },
                    dataReducer: {
                        enabled: false,
                        algorithm: "lttb",
                        targetPoints: 250,
                        threshold: 500
                    }
                },
                parsing: {
                    x: void 0,
                    y: void 0
                },
                plotOptions: {
                    line: {
                        isSlopeChart: false,
                        colors: {
                            threshold: 0,
                            colorAboveThreshold: void 0,
                            colorBelowThreshold: void 0
                        }
                    },
                    area: {
                        fillTo: "origin"
                    },
                    bar: {
                        horizontal: false,
                        columnWidth: "70%",
                        // should be in percent 0 - 100
                        barHeight: "70%",
                        // should be in percent 0 - 100
                        distributed: false,
                        borderRadius: 0,
                        borderRadiusApplication: "around",
                        // [around, end]
                        borderRadiusWhenStacked: "last",
                        // [all, last]
                        rangeBarOverlap: true,
                        rangeBarGroupRows: false,
                        hideZeroBarsWhenGrouped: false,
                        isDumbbell: false,
                        dumbbellColors: void 0,
                        isFunnel: false,
                        isFunnel3d: true,
                        colors: {
                            ranges: [],
                            backgroundBarColors: [],
                            backgroundBarOpacity: 1,
                            backgroundBarRadius: 0
                        },
                        dataLabels: {
                            position: "top",
                            // top, center, bottom
                            maxItems: 100,
                            hideOverflowingLabels: true,
                            orientation: "horizontal",
                            total: {
                                enabled: false,
                                formatter: void 0,
                                offsetX: 0,
                                offsetY: 0,
                                style: {
                                    color: "#373d3f",
                                    fontSize: "12px",
                                    fontFamily: void 0,
                                    fontWeight: 600
                                }
                            }
                        }
                    },
                    bubble: {
                        zScaling: true,
                        minBubbleRadius: void 0,
                        maxBubbleRadius: void 0
                    },
                    candlestick: {
                        colors: {
                            upward: "#00B746",
                            downward: "#EF403C"
                        },
                        wick: {
                            useFillColor: true
                        }
                    },
                    boxPlot: {
                        colors: {
                            upper: "#00E396",
                            lower: "#008FFB"
                        }
                    },
                    heatmap: {
                        radius: 2,
                        enableShades: true,
                        shadeIntensity: 0.5,
                        reverseNegativeShade: false,
                        distributed: false,
                        useFillColorAsStroke: false,
                        colorScale: {
                            inverse: false,
                            ranges: [],
                            min: void 0,
                            max: void 0,
                            // Replaces the default categorical legend with a continuous
                            // gradient stripe + a hover indicator arrow. Honors
                            // `chart.legend.position` (top / right / bottom / left).
                            gradientLegend: {
                                enabled: false,
                                // Strip length along the legend's long axis. Accepts a number
                                // (pixels) or a percentage string. For top/bottom placement the
                                // percentage is resolved against the chart's SVG width; for
                                // left/right placement, against the SVG height.
                                width: "70%",
                                height: "70%",
                                thickness: 12,
                                // Alignment of the strip within the legend area:
                                //  - top/bottom: 'start' = left, 'center', 'end' = right
                                //  - left/right: 'start' = top,  'center', 'end' = bottom
                                align: "center",
                                // Number of gradient stops sampled from the shade function when
                                // no explicit `ranges` are provided.
                                stops: 16,
                                // Show min/max labels at the ends of the strip.
                                showLabels: true,
                                // Show a value tooltip next to the arrow when hovering a cell.
                                showHoverValue: true,
                                labelStyle: {
                                    fontSize: "11px",
                                    fontFamily: void 0,
                                    colors: void 0
                                },
                                arrow: {
                                    size: 8,
                                    color: void 0
                                    // falls back to chart.foreColor
                                },
                                formatter: void 0
                                // (val) => string, for min/max + hover value
                            }
                        }
                    },
                    funnel: {
                        // 'rectangle' preserves the existing centered-rectangle funnel
                        // geometry. 'trapezoid' produces continuous sloped sides between
                        // consecutive stages (each stage's bottom width matches the next
                        // stage's top width).
                        shape: "rectangle",
                        // For shape: 'trapezoid' only — what to do with the last stage's
                        // bottom edge: 'flat' (parallel sides) or 'taper' (taper to a point).
                        lastShape: "flat"
                    },
                    treemap: {
                        enableShades: true,
                        shadeIntensity: 0.5,
                        distributed: false,
                        reverseNegativeShade: false,
                        useFillColorAsStroke: false,
                        borderRadius: 4,
                        dataLabels: {
                            format: "scale"
                            // scale | truncate
                        },
                        colorScale: {
                            inverse: false,
                            ranges: [],
                            min: void 0,
                            max: void 0
                        },
                        seriesTitle: {
                            show: true,
                            offsetY: 1,
                            offsetX: 1,
                            borderColor: "#000",
                            borderWidth: 1,
                            borderRadius: 2,
                            style: {
                                background: "rgba(0, 0, 0, 0.6)",
                                color: "#fff",
                                fontSize: "12px",
                                fontFamily: void 0,
                                fontWeight: 400,
                                cssClass: "",
                                padding: {
                                    left: 6,
                                    right: 6,
                                    top: 2,
                                    bottom: 2
                                }
                            }
                        }
                    },
                    radialBar: {
                        inverseOrder: false,
                        startAngle: 0,
                        endAngle: 360,
                        offsetX: 0,
                        offsetY: 0,
                        // Gauge sub-shape. 'arc' (default) renders the existing filled
                        // value-arc gauge; 'needle' replaces the value-arc with a rotating
                        // pointer/needle. Bands and ticks are independent and work for both
                        // shapes.
                        shape: "arc",
                        // Value-to-angle mapping. Defaults to the existing 0..100 range
                        // used by radialBar. Override for gauges that need a custom domain
                        // (e.g. min: 0, max: 240 for a speedometer).
                        min: 0,
                        max: 100,
                        // Threshold bands rendered as colored arc segments along the gauge
                        // arc (e.g. [{from:0,to:30,color:'#FF4560'}, ...]). Bands draw
                        // behind the value-arc and tick marks. Set to [] (default) to
                        // disable.
                        bands: [],
                        bandsStyle: {
                            // % of arc radius. Slightly less than the value-arc stroke so
                            // the value-arc reads on top by default.
                            strokeWidth: "40%",
                            // px gap between consecutive bands.
                            gap: 0,
                            // Hide the track when bands cover the full range; the bands
                            // themselves act as the visual backdrop.
                            hideTrackWhenPresent: true
                        },
                        // Tick marks rendered along (outside) the gauge arc.
                        ticks: {
                            show: false,
                            major: {
                                count: 11,
                                length: 10,
                                width: 2,
                                color: "#666",
                                // 'inside' draws ticks from `radius - length` to `radius`;
                                // 'outside' draws from `radius` to `radius + length`.
                                placement: "outside"
                            },
                            minor: {
                                count: 4,
                                // minor ticks BETWEEN each pair of major ticks
                                length: 5,
                                width: 1,
                                color: "#999",
                                placement: "outside"
                            },
                            labels: {
                                show: false,
                                offset: 6,
                                fontSize: "11px",
                                fontFamily: void 0,
                                fontWeight: 400,
                                color: "#666",
                                /** @param {number} v */
                                formatter(v) {
                                    return String(v);
                                }
                            }
                        },
                        // Needle/dial configuration. Only applies when `shape: 'needle'`.
                        needle: {
                            color: "#333",
                            // Needle length as a % of the gauge radius (string like '85%')
                            // or as an absolute px number.
                            length: "85%",
                            // px width of the needle line at the base.
                            baseWidth: 4,
                            // px width of the needle tip (tapered if smaller than baseWidth).
                            tipWidth: 1,
                            // px offset from the geometric arc center on Y. Positive values
                            // push the needle base down (toward the chord midpoint of a
                            // ∩-shape gauge); negative pushes up. The needle rotates around
                            // this shifted point.
                            offsetY: 0,
                            // When true, also render the filled value-arc alongside the
                            // needle. Default false preserves the previous needle-only
                            // behavior. Useful for gauges that want a progress ring plus a
                            // pointer indicator.
                            showValueArc: false,
                            animation: {
                                enabled: true,
                                duration: 800,
                                easing: "ease-out"
                            }
                        },
                        hollow: {
                            margin: 5,
                            size: "50%",
                            background: "transparent",
                            image: void 0,
                            imageWidth: 150,
                            imageHeight: 150,
                            imageOffsetX: 0,
                            imageOffsetY: 0,
                            imageClipped: true,
                            position: "front",
                            // Optional stroke around the hollow ring. Combined with
                            // `strokeDasharray` this produces a dashed indicator circle
                            // around the value text — useful for gauge designs where the
                            // value sits inside its own boundary.
                            stroke: void 0,
                            strokeWidth: 1,
                            strokeDasharray: void 0,
                            dropShadow: {
                                enabled: false,
                                top: 0,
                                left: 0,
                                blur: 3,
                                color: "#000",
                                opacity: 0.5
                            }
                        },
                        track: {
                            show: true,
                            startAngle: void 0,
                            endAngle: void 0,
                            background: "#f2f2f2",
                            strokeWidth: "97%",
                            opacity: 1,
                            margin: 5,
                            // margin is in pixels
                            dropShadow: {
                                enabled: false,
                                top: 0,
                                left: 0,
                                blur: 3,
                                color: "#000",
                                opacity: 0.5
                            }
                        },
                        dataLabels: {
                            show: true,
                            name: {
                                show: true,
                                fontSize: "16px",
                                fontFamily: void 0,
                                fontWeight: 600,
                                color: void 0,
                                offsetY: 0,
                                /**
                                 * @param {any} val
                                 */
                                formatter(val) {
                                    return val;
                                }
                            },
                            value: {
                                show: true,
                                fontSize: "14px",
                                fontFamily: void 0,
                                fontWeight: 400,
                                color: void 0,
                                offsetY: 16,
                                /**
                                 * @param {any} val
                                 */
                                formatter(val) {
                                    return val + "%";
                                }
                            },
                            total: {
                                show: false,
                                label: "Total",
                                fontSize: "16px",
                                fontWeight: 600,
                                fontFamily: void 0,
                                color: void 0,
                                /**
                                 * @param {import('../../types/internal').ChartStateW} w
                                 */
                                formatter(w) {
                                    return (
                                        /**
                                         * @param {number} a
                                         * @param {number} b
                                         */
                                        w.globals.seriesTotals.reduce((a, b) => a + b, 0) / w.seriesData.series.length + "%"
                                    );
                                }
                            }
                        },
                        barLabels: {
                            enabled: false,
                            offsetX: 0,
                            offsetY: 0,
                            useSeriesColors: true,
                            fontFamily: void 0,
                            fontWeight: 600,
                            fontSize: "16px",
                            /**
                             * @param {any} val
                             */
                            formatter(val) {
                                return val;
                            },
                            onClick: void 0
                        }
                    },
                    pie: {
                        customScale: 1,
                        offsetX: 0,
                        offsetY: 0,
                        startAngle: 0,
                        endAngle: 360,
                        expandOnClick: true,
                        dataLabels: {
                            // These are the percentage values which are displayed on slice
                            offset: 0,
                            // offset by which labels will move outside
                            minAngleToShowLabel: 10
                        },
                        donut: {
                            size: "65%",
                            background: "transparent",
                            labels: {
                                // These are the inner labels appearing inside donut
                                show: false,
                                name: {
                                    show: true,
                                    fontSize: "16px",
                                    fontFamily: void 0,
                                    fontWeight: 600,
                                    color: void 0,
                                    offsetY: -10,
                                    /**
                                     * @param {any} val
                                     */
                                    formatter(val) {
                                        return val;
                                    }
                                },
                                value: {
                                    show: true,
                                    fontSize: "20px",
                                    fontFamily: void 0,
                                    fontWeight: 400,
                                    color: void 0,
                                    offsetY: 10,
                                    /**
                                     * @param {any} val
                                     */
                                    formatter(val) {
                                        return val;
                                    }
                                },
                                total: {
                                    show: false,
                                    showAlways: false,
                                    label: "Total",
                                    fontSize: "16px",
                                    fontWeight: 400,
                                    fontFamily: void 0,
                                    color: void 0,
                                    /**
                                     * @param {import('../../types/internal').ChartStateW} w
                                     */
                                    formatter(w) {
                                        return w.globals.seriesTotals.reduce((a, b) => a + b, 0);
                                    }
                                }
                            }
                        }
                    },
                    polarArea: {
                        rings: {
                            strokeWidth: 1,
                            strokeColor: "#e8e8e8"
                        },
                        spokes: {
                            strokeWidth: 1,
                            connectorColors: "#e8e8e8"
                        }
                    },
                    radar: {
                        size: void 0,
                        offsetX: 0,
                        offsetY: 0,
                        polygons: {
                            // strokeColor: '#e8e8e8', // should be deprecated in the minor version i.e 3.2
                            strokeWidth: 1,
                            strokeColors: "#e8e8e8",
                            connectorColors: "#e8e8e8",
                            fill: {
                                colors: void 0
                            }
                        }
                    }
                },
                colors: void 0,
                dataLabels: {
                    enabled: true,
                    enabledOnSeries: void 0,
                    /**
                     * @param {any} val
                     */
                    formatter(val) {
                        return val !== null ? val : "";
                    },
                    textAnchor: "middle",
                    distributed: false,
                    offsetX: 0,
                    offsetY: 0,
                    style: {
                        fontSize: "12px",
                        fontFamily: void 0,
                        fontWeight: 600,
                        colors: void 0
                    },
                    background: {
                        enabled: true,
                        foreColor: "#fff",
                        backgroundColor: void 0,
                        borderRadius: 2,
                        padding: 4,
                        opacity: 0.9,
                        borderWidth: 1,
                        borderColor: "#fff",
                        dropShadow: {
                            enabled: false,
                            top: 1,
                            left: 1,
                            blur: 1,
                            color: "#000",
                            opacity: 0.8
                        }
                    },
                    dropShadow: {
                        enabled: false,
                        top: 1,
                        left: 1,
                        blur: 1,
                        color: "#000",
                        opacity: 0.8
                    }
                },
                fill: {
                    type: "solid",
                    colors: void 0,
                    // array of colors
                    opacity: 0.85,
                    gradient: {
                        shade: "dark",
                        type: "horizontal",
                        shadeIntensity: 0.5,
                        gradientToColors: void 0,
                        inverseColors: true,
                        opacityFrom: 1,
                        opacityTo: 1,
                        stops: [0, 50, 100],
                        colorStops: []
                    },
                    image: {
                        src: [],
                        width: void 0,
                        // optional
                        height: void 0
                        // optional
                    },
                    pattern: {
                        style: "squares",
                        // String | Array of Strings
                        width: 6,
                        height: 6,
                        strokeWidth: 2
                    }
                },
                forecastDataPoints: {
                    count: 0,
                    fillOpacity: 0.5,
                    strokeWidth: void 0,
                    dashArray: 4
                },
                grid: {
                    show: true,
                    borderColor: "#e0e0e0",
                    strokeDashArray: 0,
                    position: "back",
                    xaxis: {
                        lines: {
                            show: false
                        }
                    },
                    yaxis: {
                        lines: {
                            show: true
                        }
                    },
                    row: {
                        colors: void 0,
                        // takes as array which will be repeated on rows
                        opacity: 0.5
                    },
                    column: {
                        colors: void 0,
                        // takes an array which will be repeated on columns
                        opacity: 0.5
                    },
                    padding: {
                        top: 0,
                        right: 10,
                        bottom: 0,
                        left: 12
                    }
                },
                labels: [],
                legend: {
                    show: true,
                    showForSingleSeries: false,
                    showForNullSeries: true,
                    showForZeroSeries: true,
                    floating: false,
                    position: "bottom",
                    // whether to position legends in 1 of 4
                    // direction - top, bottom, left, right
                    horizontalAlign: "center",
                    // when position top/bottom, you can specify whether to align legends left, right or center
                    inverseOrder: false,
                    fontSize: "12px",
                    fontFamily: void 0,
                    fontWeight: 400,
                    width: void 0,
                    height: void 0,
                    formatter: void 0,
                    tooltipHoverFormatter: void 0,
                    offsetX: -20,
                    offsetY: 4,
                    customLegendItems: [],
                    clusterGroupedSeries: true,
                    clusterGroupedSeriesOrientation: "vertical",
                    labels: {
                        colors: void 0,
                        useSeriesColors: false
                    },
                    markers: {
                        size: 7,
                        fillColors: void 0,
                        strokeWidth: 1,
                        shape: void 0,
                        offsetX: 0,
                        offsetY: 0,
                        customHTML: void 0,
                        onClick: void 0
                    },
                    itemMargin: {
                        horizontal: 5,
                        vertical: 4
                    },
                    onItemClick: {
                        toggleDataSeries: true
                    },
                    onItemHover: {
                        highlightDataSeries: true
                    }
                },
                markers: {
                    discrete: [],
                    size: 0,
                    colors: void 0,
                    strokeColors: "#fff",
                    strokeWidth: 2,
                    strokeOpacity: 0.9,
                    strokeDashArray: 0,
                    fillOpacity: 1,
                    shape: "circle",
                    offsetX: 0,
                    offsetY: 0,
                    showNullDataPoints: true,
                    onClick: void 0,
                    onDblClick: void 0,
                    hover: {
                        size: void 0,
                        sizeOffset: 3
                    }
                },
                noData: {
                    text: void 0,
                    align: "center",
                    offsetX: 0,
                    offsetY: 0,
                    style: {
                        color: void 0,
                        fontSize: "14px",
                        fontFamily: void 0
                    }
                },
                responsive: [],
                // breakpoints should follow ascending order 400, then 700, then 1000
                series: void 0,
                states: {
                    hover: {
                        filter: {
                            type: "lighten"
                        }
                    },
                    active: {
                        allowMultipleDataPointsSelection: false,
                        filter: {
                            type: "darken"
                        }
                    }
                },
                title: {
                    text: void 0,
                    align: "left",
                    margin: 5,
                    offsetX: 0,
                    offsetY: 0,
                    floating: false,
                    style: {
                        fontSize: "14px",
                        fontWeight: 900,
                        fontFamily: void 0,
                        color: void 0
                    }
                },
                subtitle: {
                    text: void 0,
                    align: "left",
                    margin: 5,
                    offsetX: 0,
                    offsetY: 30,
                    floating: false,
                    style: {
                        fontSize: "12px",
                        fontWeight: 400,
                        fontFamily: void 0,
                        color: void 0
                    }
                },
                stroke: {
                    show: true,
                    curve: "smooth",
                    // "smooth" / "straight" / "monotoneCubic" / "stepline" / "linestep"
                    lineCap: "butt",
                    // round, butt , square
                    width: 2,
                    colors: void 0,
                    // array of colors
                    dashArray: 0,
                    // single value or array of values
                    fill: {
                        type: "solid",
                        colors: void 0,
                        // array of colors
                        opacity: 0.85,
                        gradient: {
                            shade: "dark",
                            type: "horizontal",
                            shadeIntensity: 0.5,
                            gradientToColors: void 0,
                            inverseColors: true,
                            opacityFrom: 1,
                            opacityTo: 1,
                            stops: [0, 50, 100],
                            colorStops: []
                        }
                    }
                },
                tooltip: {
                    enabled: true,
                    enabledOnSeries: void 0,
                    shared: true,
                    hideEmptySeries: false,
                    followCursor: false,
                    // when disabled, the tooltip will show on top of the series instead of mouse position
                    intersect: false,
                    // when enabled, tooltip will only show when user directly hovers over point
                    inverseOrder: false,
                    arrow: true,
                    custom: void 0,
                    fillSeriesColor: false,
                    theme: "light",
                    cssClass: "",
                    style: {
                        fontSize: "12px",
                        fontFamily: void 0,
                        background: void 0
                    },
                    onDatasetHover: {
                        highlightDataSeries: false
                    },
                    x: {
                        // x value
                        show: true,
                        format: "dd MMM",
                        // dd/MM, dd MMM yy, dd MMM yyyy
                        formatter: void 0
                        // a custom user supplied formatter function
                    },
                    y: {
                        formatter: void 0,
                        title: {
                            /**
                             * @param {string} seriesName
                             */
                            formatter(seriesName) {
                                return seriesName ? seriesName + ": " : "";
                            }
                        }
                    },
                    z: {
                        formatter: void 0,
                        title: "Size: "
                    },
                    marker: {
                        show: true,
                        fillColors: void 0
                    },
                    items: {
                        display: "flex"
                    },
                    fixed: {
                        enabled: false,
                        position: "topRight",
                        // topRight, topLeft, bottomRight, bottomLeft
                        offsetX: 0,
                        offsetY: 0
                    }
                },
                xaxis: {
                    type: "category",
                    categories: [],
                    convertedCatToNumeric: false,
                    // internal property which should not be altered outside
                    offsetX: 0,
                    offsetY: 0,
                    overwriteCategories: void 0,
                    labels: {
                        show: true,
                        rotate: -45,
                        rotateAlways: false,
                        hideOverlappingLabels: true,
                        trim: false,
                        minHeight: void 0,
                        maxHeight: 120,
                        showDuplicates: true,
                        style: {
                            colors: [],
                            fontSize: "12px",
                            fontWeight: 400,
                            fontFamily: void 0,
                            cssClass: ""
                        },
                        offsetX: 0,
                        offsetY: 0,
                        format: void 0,
                        formatter: void 0,
                        // custom formatter function which will override format
                        datetimeUTC: true,
                        datetimeFormatter: {
                            // Base format per interval unit. TimeScale.formatDates folds in
                            // coarser context automatically when the data range spans it
                            // (e.g. month-scale across years → 'MMM yyyy', hour-scale across
                            // days → 'dd MMM HH:mm'). Customizing a base format that already
                            // includes the higher-unit token disables the auto-expansion for
                            // that level.
                            year: "yyyy",
                            month: "MMM",
                            day: "dd MMM",
                            hour: "HH:mm",
                            minute: "HH:mm",
                            second: "HH:mm:ss"
                        }
                    },
                    group: {
                        groups: [],
                        style: {
                            colors: [],
                            fontSize: "12px",
                            fontWeight: 400,
                            fontFamily: void 0,
                            cssClass: ""
                        }
                    },
                    axisBorder: {
                        show: true,
                        color: "#e0e0e0",
                        width: "100%",
                        height: 1,
                        offsetX: 0,
                        offsetY: 0
                    },
                    axisTicks: {
                        show: true,
                        color: "#e0e0e0",
                        height: 6,
                        offsetX: 0,
                        offsetY: 0
                    },
                    stepSize: void 0,
                    tickAmount: void 0,
                    tickPlacement: "on",
                    min: void 0,
                    max: void 0,
                    range: void 0,
                    floating: false,
                    decimalsInFloat: void 0,
                    position: "bottom",
                    title: {
                        text: void 0,
                        offsetX: 0,
                        offsetY: 0,
                        style: {
                            color: void 0,
                            fontSize: "12px",
                            fontWeight: 900,
                            fontFamily: void 0,
                            cssClass: ""
                        }
                    },
                    crosshairs: {
                        show: true,
                        width: 1,
                        // tickWidth/barWidth or an integer
                        position: "back",
                        opacity: 0.9,
                        stroke: {
                            color: "#b6b6b6",
                            width: 1,
                            dashArray: 3
                        },
                        fill: {
                            type: "solid",
                            // solid, gradient
                            color: "#B1B9C4",
                            gradient: {
                                colorFrom: "#D8E3F0",
                                colorTo: "#BED1E6",
                                stops: [0, 100],
                                opacityFrom: 0.4,
                                opacityTo: 0.5
                            }
                        },
                        dropShadow: {
                            enabled: false,
                            left: 0,
                            top: 0,
                            blur: 1,
                            opacity: 0.8
                        }
                    },
                    tooltip: {
                        enabled: true,
                        offsetY: 0,
                        formatter: void 0,
                        style: {
                            fontSize: "12px",
                            fontFamily: void 0
                        }
                    }
                },
                yaxis: this.yAxis,
                theme: {
                    mode: "",
                    palette: "palette1",
                    // If defined, it will overwrite globals.colors variable
                    monochrome: {
                        // monochrome allows you to select just 1 color and fill out the rest with light/dark shade (intensity can be selected)
                        enabled: false,
                        color: "#008FFB",
                        shadeTo: "light",
                        shadeIntensity: 0.65
                    },
                    accessibility: {
                        colorBlindMode: ""
                        // '' | 'deuteranopia' | 'protanopia' | 'tritanopia' | 'highContrast'
                    }
                }
            };
        }
    }
    class Config {
        /**
         * @param {Record<string, any>} opts
         */
        constructor(opts) {
            this.opts = opts;
        }
        /** @param {{responsiveOverride: any}} opts */
        init({
            responsiveOverride
        }) {
            var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
            let opts = this.opts;
            const options2 = new Options();
            const defaults = new Defaults(opts);
            opts = this.normalizeAliasedChartType(opts);
            this.chartType = opts.chart.type;
            opts = this.extendYAxis(opts);
            opts = this.extendAnnotations(opts);
            let config = options2.init();
            let newDefaults = {};
            if (opts && typeof opts === "object") {
                let chartDefaults = {};
                const chartTypes = [
                    "line",
                    "area",
                    "bar",
                    "candlestick",
                    "boxPlot",
                    "rangeBar",
                    "rangeArea",
                    "bubble",
                    "scatter",
                    "heatmap",
                    "treemap",
                    "pie",
                    "polarArea",
                    "donut",
                    "radar",
                    "radialBar"
                ];
                const requestedType = opts.chart.requestedType;
                if (requestedType === "funnel" || requestedType === "pyramid") {
                    chartDefaults = /** @type {any} */
                        defaults[requestedType]();
                } else if (requestedType === "gauge") {
                    chartDefaults = defaults.gauge();
                } else if (chartTypes.indexOf(opts.chart.type) !== -1) {
                    chartDefaults = /** @type {any} */
                        defaults[opts.chart.type]();
                } else {
                    chartDefaults = defaults.line();
                }
                if ((_b = (_a = opts.plotOptions) == null ? void 0 : _a.bar) == null ? void 0 : _b.isFunnel) {
                    chartDefaults = defaults.funnel();
                }
                if (opts.chart.stacked && opts.chart.type === "bar") {
                    chartDefaults = defaults.stackedBars();
                }
                if ((_c = opts.chart.brush) == null ? void 0 : _c.enabled) {
                    chartDefaults = defaults.brush(chartDefaults);
                }
                if ((_e = (_d = opts.plotOptions) == null ? void 0 : _d.line) == null ? void 0 : _e.isSlopeChart) {
                    chartDefaults = defaults.slope();
                }
                if (opts.chart.stacked && opts.chart.stackType === "100%") {
                    opts = defaults.stacked100(opts);
                }
                if ((_g = (_f = opts.plotOptions) == null ? void 0 : _f.bar) == null ? void 0 : _g.isDumbbell) {
                    opts = defaults.dumbbell(opts);
                }
                this.checkForDarkTheme(Environment.getApex());
                this.checkForDarkTheme(opts);
                opts.xaxis = opts.xaxis || Environment.getApex().xaxis || {};
                if (!responsiveOverride) {
                    opts.xaxis.convertedCatToNumeric = false;
                }
                opts = this.checkForCatToNumericXAxis(this.chartType, chartDefaults, opts);
                if (((_h = opts.chart.sparkline) == null ? void 0 : _h.enabled) || ((_j = (_i = Environment.getApex().chart) == null ? void 0 : _i.sparkline) == null ? void 0 : _j.enabled)) {
                    chartDefaults = defaults.sparkline(chartDefaults);
                }
                newDefaults = Utils$1.extend(config, chartDefaults);
            }
            const mergedWithDefaultConfig = Utils$1.extend(
                newDefaults,
                Environment.getApex()
            );
            config = Utils$1.extend(mergedWithDefaultConfig, opts);
            config = this.handleUserInputErrors(config);
            return config;
        }
        /**
         * Promoted chart-type aliases — `funnel`, `pyramid`, `gauge` — render via
         * the existing `bar` (with `isFunnel`) and `radialBar` pathways. To keep
         * the ~20 internal `chart.type === 'bar' | 'radialBar'` checks working
         * unchanged, we normalize `chart.type` to the base renderer name here and
         * preserve the user-facing name on `chart.requestedType` for the public
         * API and for default selection.
         *
         * @param {Record<string, any>} opts
         * @returns {Record<string, any>}
         */
        normalizeAliasedChartType(opts) {
            if (!opts || !opts.chart) return opts;
            const requested = opts.chart.type;
            if (requested !== "funnel" && requested !== "pyramid" && requested !== "gauge") {
                return opts;
            }
            opts.chart.requestedType = requested;
            if (requested === "funnel" || requested === "pyramid") {
                opts.plotOptions = opts.plotOptions || {};
                opts.plotOptions.bar = opts.plotOptions.bar || {};
                opts.plotOptions.bar.isFunnel = true;
                opts.plotOptions.bar.horizontal = true;
                opts.chart.type = "bar";
                if (requested === "pyramid") {
                    opts.plotOptions.bar.isPyramid = true;
                } else {
                    opts.plotOptions.bar.isPyramid = false;
                }
            } else if (requested === "gauge") {
                opts.chart.type = "radialBar";
            }
            return opts;
        }
        /**
         * @param {string} chartType
         * @param {Record<string, any>} chartDefaults
         * @param {Record<string, any>} opts
         */
        checkForCatToNumericXAxis(chartType, chartDefaults, opts) {
            var _a, _b;
            const defaults = new Defaults(opts);
            const isBarHorizontal = (chartType === "bar" || chartType === "boxPlot") && ((_b = (_a = opts.plotOptions) == null ? void 0 : _a.bar) == null ? void 0 : _b.horizontal);
            const unsupportedZoom = chartType === "pie" || chartType === "polarArea" || chartType === "donut" || chartType === "radar" || chartType === "radialBar" || chartType === "heatmap";
            const notNumericXAxis = opts.xaxis.type !== "datetime" && opts.xaxis.type !== "numeric";
            const tickPlacement = opts.xaxis.tickPlacement ? opts.xaxis.tickPlacement : chartDefaults.xaxis && chartDefaults.xaxis.tickPlacement;
            if (!isBarHorizontal && !unsupportedZoom && notNumericXAxis && tickPlacement !== "between") {
                opts = defaults.convertCatToNumeric(opts);
            }
            return opts;
        }
        /**
         * @param {Record<string, any>} opts
         * @param {import('../../types/internal').ChartStateW} [w]
         */
        extendYAxis(opts, w) {
            const options2 = new Options();
            if (typeof opts.yaxis === "undefined" || !opts.yaxis || Array.isArray(opts.yaxis) && opts.yaxis.length === 0) {
                opts.yaxis = {};
            }
            const globalApex = Environment.getApex();
            if (opts.yaxis.constructor !== Array && globalApex.yaxis && globalApex.yaxis.constructor !== Array) {
                opts.yaxis = Utils$1.extend(opts.yaxis, globalApex.yaxis);
            }
            if (opts.yaxis.constructor !== Array) {
                opts.yaxis = [Utils$1.extend(options2.yAxis, opts.yaxis)];
            } else {
                opts.yaxis = Utils$1.extendArray(opts.yaxis, options2.yAxis);
            }
            let isLogY = false;
            opts.yaxis.forEach((y) => {
                if (y.logarithmic) {
                    isLogY = true;
                }
            });
            let series = opts.series;
            if (w && !series) {
                series = w.config.series;
            }
            if (isLogY && series.length !== opts.yaxis.length && series.length) {
                opts.yaxis = series.map((s, i) => {
                    if (!s.name) {
                        series[i].name = `series-${i + 1}`;
                    }
                    if (opts.yaxis[i]) {
                        opts.yaxis[i].seriesName = series[i].name;
                        return opts.yaxis[i];
                    } else {
                        const newYaxis = Utils$1.extend(options2.yAxis, opts.yaxis[0]);
                        newYaxis.show = false;
                        return newYaxis;
                    }
                });
            }
            if (isLogY && series.length > 1 && series.length !== opts.yaxis.length) {
                console.warn(
                    "A multi-series logarithmic chart should have equal number of series and y-axes"
                );
            }
            return opts;
        }
        // annotations also accepts array, so we need to extend them manually
        /**
         * @param {Record<string, any>} opts
         */
        extendAnnotations(opts) {
            if (typeof opts.annotations === "undefined") {
                opts.annotations = {};
                opts.annotations.yaxis = [];
                opts.annotations.xaxis = [];
                opts.annotations.points = [];
            }
            opts = this.extendYAxisAnnotations(opts);
            opts = this.extendXAxisAnnotations(opts);
            opts = this.extendPointAnnotations(opts);
            return opts;
        }
        /**
         * @param {Record<string, any>} opts
         */
        extendYAxisAnnotations(opts) {
            const options2 = new Options();
            opts.annotations.yaxis = Utils$1.extendArray(
                typeof opts.annotations.yaxis !== "undefined" ? opts.annotations.yaxis : [],
                options2.yAxisAnnotation
            );
            return opts;
        }
        /**
         * @param {Record<string, any>} opts
         */
        extendXAxisAnnotations(opts) {
            const options2 = new Options();
            opts.annotations.xaxis = Utils$1.extendArray(
                typeof opts.annotations.xaxis !== "undefined" ? opts.annotations.xaxis : [],
                options2.xAxisAnnotation
            );
            return opts;
        }
        /**
         * @param {Record<string, any>} opts
         */
        extendPointAnnotations(opts) {
            const options2 = new Options();
            opts.annotations.points = Utils$1.extendArray(
                typeof opts.annotations.points !== "undefined" ? opts.annotations.points : [],
                options2.pointAnnotation
            );
            return opts;
        }
        /**
         * @param {Record<string, any>} opts
         */
        checkForDarkTheme(opts) {
            if (opts.theme && opts.theme.mode === "dark") {
                if (!opts.tooltip) {
                    opts.tooltip = {};
                }
                if (opts.tooltip.theme !== "light") {
                    opts.tooltip.theme = "dark";
                }
                if (!opts.chart.foreColor) {
                    opts.chart.foreColor = "#f6f7f8";
                }
                if (!opts.theme.palette) {
                    opts.theme.palette = "palette4";
                }
            }
        }
        /**
         * @param {any} opts
         */
        handleUserInputErrors(opts) {
            const config = opts;
            if (config.tooltip.shared && config.tooltip.intersect) {
                throw new Error(
                    "tooltip.shared cannot be enabled when tooltip.intersect is true. Turn off any other option by setting it to false."
                );
            }
            if (config.chart.type === "bar" && config.plotOptions.bar.horizontal) {
                if (config.yaxis.length > 1) {
                    throw new Error(
                        "Multiple Y Axis for bars are not supported. Switch to column chart by setting plotOptions.bar.horizontal=false"
                    );
                }
                if (config.yaxis[0].reversed) {
                    config.yaxis[0].opposite = true;
                }
                config.xaxis.tooltip.enabled = false;
                config.yaxis[0].tooltip.enabled = false;
                config.chart.zoom.enabled = false;
            }
            if (config.chart.type === "bar" || config.chart.type === "rangeBar") {
                if (config.tooltip.shared) {
                    if (config.xaxis.crosshairs.width === "barWidth" && config.series.length > 1) {
                        config.xaxis.crosshairs.width = "tickWidth";
                    }
                }
            }
            if (config.chart.type === "candlestick" || config.chart.type === "boxPlot") {
                if (config.yaxis[0].reversed) {
                    console.warn(
                        `Reversed y-axis in ${config.chart.type} chart is not supported.`
                    );
                    config.yaxis[0].reversed = false;
                }
            }
            return config;
        }
    }
    const LINE_HEIGHT_RATIO = 1.618;
    const NICE_SCALE_ALLOWED_MAG_MSD = [
        [1, 1, 2, 5, 5, 5, 10, 10, 10, 10, 10],
        [1, 1, 2, 5, 5, 5, 10, 10, 10, 10, 10]
    ];
    const NICE_SCALE_DEFAULT_TICKS = [
        1,
        2,
        4,
        4,
        6,
        6,
        6,
        6,
        6,
        6,
        6,
        6,
        6,
        6,
        6,
        6,
        6,
        6,
        12,
        12,
        12,
        12,
        12,
        12,
        12,
        12,
        12,
        24
    ];
    class Globals {
        /**
         * @param {any} gl
         */
        initGlobalVars(gl) {
            gl.series = [];
            gl.seriesCandleO = [];
            gl.seriesCandleH = [];
            gl.seriesCandleM = [];
            gl.seriesCandleL = [];
            gl.seriesCandleC = [];
            gl.seriesRangeStart = [];
            gl.seriesRangeEnd = [];
            gl.seriesRange = [];
            gl.seriesPercent = [];
            gl.seriesGoals = [];
            gl.seriesX = [];
            gl.seriesZ = [];
            gl.seriesNames = [];
            gl.seriesTotals = [];
            gl.seriesLog = [];
            gl.seriesColors = [];
            gl.stackedSeriesTotals = [];
            gl.seriesXvalues = [];
            gl.seriesYvalues = [];
            gl.dataWasParsed = false;
            gl.originalSeries = null;
            gl.maxValsInArrayIndex = 0;
            gl.yValueDecimal = 0;
            gl.allSeriesHasEqualX = true;
            gl.labels = [];
            gl.hasXaxisGroups = false;
            gl.groups = [];
            gl.barGroups = [];
            gl.lineGroups = [];
            gl.areaGroups = [];
            gl.hasSeriesGroups = false;
            gl.seriesGroups = [];
            gl.categoryLabels = [];
            gl.timescaleLabels = [];
            gl.noLabelsProvided = false;
            gl.isXNumeric = false;
            gl.skipLastTimelinelabel = false;
            gl.skipFirstTimelinelabel = false;
            gl.isDataXYZ = false;
            gl.isMultiLineX = false;
            gl.isMultipleYAxis = false;
            gl.maxY = -Number.MAX_VALUE;
            gl.minY = Number.MIN_VALUE;
            gl.minYArr = [];
            gl.maxYArr = [];
            gl.maxX = -Number.MAX_VALUE;
            gl.minX = Number.MAX_VALUE;
            gl.initialMaxX = -Number.MAX_VALUE;
            gl.initialMinX = Number.MAX_VALUE;
            gl.maxDate = 0;
            gl.minDate = Number.MAX_VALUE;
            gl.minZ = Number.MAX_VALUE;
            gl.maxZ = -Number.MAX_VALUE;
            gl.minXDiff = Number.MAX_VALUE;
            gl.yAxisScale = [];
            gl.xAxisScale = null;
            gl.xAxisTicksPositions = [];
            gl.xRange = 0;
            gl.yRange = [];
            gl.zRange = 0;
            gl.dataPoints = 0;
            gl.xTickAmount = 0;
            gl.multiAxisTickAmount = 0;
            gl.disableZoomIn = false;
            gl.disableZoomOut = false;
            gl.yLabelsCoords = [];
            gl.yTitleCoords = [];
            gl.barPadForNumericAxis = 0;
            gl.padHorizontal = 0;
            gl.rotateXLabels = false;
            gl.overlappingXLabels = false;
            gl.radialSize = 0;
            gl.barHeight = 0;
            gl.barWidth = 0;
            gl.animationEnded = false;
            gl.resizeTimer = null;
            gl.selectionResizeTimer = null;
            gl.lastWheelExecution = 0;
            gl.delayedElements = [];
            gl.pointsArray = [];
            gl.dataLabelsRects = [];
            gl.lastDrawnDataLabelsIndexes = [];
            gl.textRectsCache = /* @__PURE__ */ new Map();
            gl.domCache = /* @__PURE__ */ new Map();
            gl.dimensionCache = {};
            gl.cachedSelectors = {};
            if (!gl.seriesNS) {
                this._attachNamespaces(gl);
            }
        }
        /**
         * Attach domain-grouped namespace sub-objects onto gl.
         * Each sub-object is a plain object whose properties are defined as
         * getters/setters that read/write the canonical flat properties on gl.
         * This means there is exactly ONE storage location per value — no copies,
         * no sync needed.
         *
         * Namespaces:
         *   gl.series  — parsed series data and chart-type-specific arrays
         *   gl.axes    — axis bounds, scales, ranges, tick state
         *   gl.layout  — SVG/grid dimensions, translations, label sizes
         *   gl.cache   — DOM caches, timers, observers, drawing scratch space
         *
         * Note: interact state lives on w.interact (not gl) — see Base.js.
         * @param {any} gl
         */
        _attachNamespaces(gl) {
            const proxy = (ns, key, nsKey = key) => {
                Object.defineProperty(ns, nsKey, {
                    get() {
                        return gl[key];
                    },
                    set(v) {
                        gl[key] = v;
                    },
                    enumerable: true,
                    configurable: true
                });
            };
            const seriesNS = {};
            proxy(seriesNS, "series", "data");
            for (const key of [
                    "seriesNames",
                    "seriesX",
                    "seriesZ",
                    "seriesXvalues",
                    "seriesYvalues",
                    "seriesGoals",
                    "seriesLog",
                    "seriesColors",
                    "seriesPercent",
                    "seriesTotals",
                    "stackedSeriesTotals",
                    "seriesCandleO",
                    "seriesCandleH",
                    "seriesCandleM",
                    "seriesCandleL",
                    "seriesCandleC",
                    "seriesRangeStart",
                    "seriesRangeEnd",
                    "seriesRange",
                    "seriesYAxisMap",
                    "seriesYAxisReverseMap",
                    "seriesGroups",
                    "barGroups",
                    "lineGroups",
                    "areaGroups",
                    "originalSeries",
                    "collapsedSeries",
                    "collapsedSeriesIndices",
                    "ancillaryCollapsedSeries",
                    "ancillaryCollapsedSeriesIndices",
                    "allSeriesCollapsed",
                    "risingSeries",
                    "previousPaths",
                    "ignoreYAxisIndexes",
                    "labels",
                    "categoryLabels",
                    "timescaleLabels",
                    "groups"
                ]) {
                proxy(seriesNS, key);
            }
            Object.defineProperty(gl, "seriesNS", {
                value: seriesNS,
                writable: false,
                enumerable: false,
                configurable: true
            });
            const axesNS = {};
            for (const key of [
                    "minX",
                    "maxX",
                    "initialMinX",
                    "initialMaxX",
                    "minY",
                    "maxY",
                    "minYArr",
                    "maxYArr",
                    "minZ",
                    "maxZ",
                    "minDate",
                    "maxDate",
                    "minXDiff",
                    "xRange",
                    "yRange",
                    "zRange",
                    "xAxisScale",
                    "yAxisScale",
                    "xAxisTicksPositions",
                    "xTickAmount",
                    "multiAxisTickAmount",
                    "dataPoints",
                    "maxValsInArrayIndex",
                    "isXNumeric",
                    "isMultipleYAxis",
                    "isMultiLineX",
                    "isDataXYZ",
                    "dataFormatXNumeric",
                    "allSeriesHasEqualX",
                    "hasNullValues",
                    "dataWasParsed",
                    "hasXaxisGroups",
                    "hasSeriesGroups",
                    "skipFirstTimelinelabel",
                    "skipLastTimelinelabel",
                    "yValueDecimal",
                    "invalidLogScale",
                    "noLabelsProvided"
                ]) {
                proxy(axesNS, key);
            }
            Object.defineProperty(gl, "axes", {
                value: axesNS,
                writable: false,
                enumerable: false,
                configurable: true
            });
            const layoutNS = {};
            for (const key of [
                    "svgWidth",
                    "svgHeight",
                    "gridWidth",
                    "gridHeight",
                    "translateX",
                    "translateY",
                    "translateXAxisX",
                    "translateXAxisY",
                    "translateYAxisX",
                    "xAxisLabelsHeight",
                    "xAxisGroupLabelsHeight",
                    "xAxisLabelsWidth",
                    "yAxisLabelsWidth",
                    "yAxisWidths",
                    "yLabelsCoords",
                    "yTitleCoords",
                    "padHorizontal",
                    "barPadForNumericAxis",
                    "rotateXLabels",
                    "scaleX",
                    "scaleY",
                    "radialSize",
                    "defaultLabels",
                    "overlappingXLabels"
                ]) {
                proxy(layoutNS, key);
            }
            Object.defineProperty(gl, "layout", {
                value: layoutNS,
                writable: false,
                enumerable: false,
                configurable: true
            });
            const cacheNS = {};
            for (const key of [
                    "domCache",
                    "dimensionCache",
                    "cachedSelectors",
                    "textRectsCache",
                    "pointsArray",
                    "dataLabelsRects",
                    "lastDrawnDataLabelsIndexes",
                    "delayedElements",
                    "resizeTimer",
                    "selectionResizeTimer",
                    "resizeObserver"
                ]) {
                proxy(cacheNS, key);
            }
            Object.defineProperty(gl, "cache", {
                value: cacheNS,
                writable: false,
                enumerable: false,
                configurable: true
            });
        }
        /**
         * Persistent chart state — set ONCE at chart construction and intentionally NOT
         * reset by initGlobalVars.  These values must survive updateSeries / re-render.
         *
         * Rule: if a value is recalculated fresh on every render it belongs in
         * initGlobalVars instead, not here.
         * @returns {import('../../types/internal').ChartGlobals}
         * @param {Record<string, any>} config
         */
        globalVars(config) {
            const globals = {
                // ── Identity (set once, never changes) ───────────────────────────────────
                chartID: null,
                // full chart ID: "apexcharts-<cuid>"
                cuid: null,
                // random suffix only
                // ── Event registry (accumulates listeners, never reset) ───────────────────
                events: {
                    beforeMount: [],
                    mounted: [],
                    updated: [],
                    clicked: [],
                    selection: [],
                    dataPointSelection: [],
                    zoomed: [],
                    scrolled: []
                },
                // ── Theme colors (set by Theme module after config merge) ─────────────────
                colors: [],
                fill: {
                    colors: []
                },
                stroke: {
                    colors: []
                },
                dataLabels: {
                    style: {
                        colors: []
                    }
                },
                radarPolygons: {
                    fill: {
                        colors: []
                    }
                },
                markers: {
                    colors: [],
                    size: config.markers.size,
                    largestSize: 0
                },
                // ── Device / environment detected once at startup ─────────────────────────
                // Note: isTouchDevice lives on w.interact — see Base.js. Shim installed there.
                LINE_HEIGHT_RATIO,
                // ── Chart-type flags (derived from config, set during Core.mount) ─────────
                axisCharts: true,
                // false for pie/radial/treemap etc.
                isSlopeChart: config.plotOptions.line.isSlopeChart,
                comboCharts: false,
                // true when mixing line + column series
                // ── Config snapshots (backups for zoom-reset / updateOptions) ────────────
                initialConfig: null,
                // deep clone of the original user config
                initialSeries: [],
                lastXAxis: [],
                lastYAxis: [],
                // ── User interaction state (must survive re-renders) ──────────────────────
                // Note: zoomEnabled, panEnabled, selectionEnabled, zoomed, selection,
                //       visibleXRange, selectedDataPoints, mousedown, clientX, clientY,
                //       lastClientPosition, lastWheelExecution, capturedSeriesIndex,
                //       capturedDataPointIndex, disableZoomIn, disableZoomOut, isTouchDevice
                //       live on w.interact — see Base.js. Backward-compat shims installed there.
                // Series collapse state (user-driven, must persist across re-renders)
                allSeriesCollapsed: false,
                collapsedSeries: [],
                collapsedSeriesIndices: [],
                ancillaryCollapsedSeries: [],
                ancillaryCollapsedSeriesIndices: [],
                risingSeries: [],
                // series being re-shown after collapse
                ignoreYAxisIndexes: [],
                // y-axis indices excluded during series collapse
                // ── Lifecycle / update flags ──────────────────────────────────────────────
                isDirty: false,
                // true when user called an update method manually
                isExecCalled: false,
                // true when update came via exec()
                dataChanged: false,
                // true when series data was changed dynamically
                resized: false,
                // true after a container resize
                // ── Data format flags (derived from config/series, stable between renders) ─
                // Note: dataFormatXNumeric lives on w.axisFlags — see Base.js. Shim installed there.
                invalidLogScale: false,
                // true when log scale requested but data is invalid
                hasNullValues: false,
                // true when any series contains null values
                // Persistent data tracking
                columnSeries: null,
                // tracks which series are rendered as bars/columns
                yaxis: null,
                // resolved yaxis config array
                total: 0,
                // running total (used by pie/radial)
                // ── Animation control ─────────────────────────────────────────────────────
                shouldAnimate: true,
                previousPaths: [],
                // paths from previous render — source for enter animation
                // ── SVG viewport (set by Dimensions, but persistent as layout anchor) ─────
                svgWidth: 0,
                svgHeight: 0,
                // Note: gridWidth, gridHeight, translateX, translateY, translateXAxisX,
                // translateXAxisY, xAxisLabelsHeight, xAxisGroupLabelsHeight, xAxisLabelsWidth,
                // rotateXLabels, xAxisHeight, yLabelsCoords, yTitleCoords live on w.layout —
                // see Base.js. Backward-compat shims installed there.
                defaultLabels: false,
                // Note: formatter properties (xLabelFormatter, yLabelFormatters, etc.) live on
                // w.formatters — see Base.js. Backward-compat shims installed there.
                yAxisLabelsWidth: 0,
                scaleX: 1,
                scaleY: 1,
                translateYAxisX: [],
                yAxisWidths: [],
                // ── Instances (created once, replaced only on full re-init) ──────────────
                tooltip: null,
                resizeObserver: null,
                // ── Locale (loaded once; changes only via setLocale()) ───────────────────
                locale: {},
                // ── Method queue (deferred calls during async operations) ────────────────
                memory: {
                    methodsToExec: []
                },
                // ── Scale configuration constants — imported from utils/Constants.js ──────
                niceScaleAllowedMagMsd: NICE_SCALE_ALLOWED_MAG_MSD,
                niceScaleDefaultTicks: NICE_SCALE_DEFAULT_TICKS,
                // ── Multi-axis series mapping ─────────────────────────────────────────────
                seriesYAxisMap: [],
                // yAxis index → series indices[]
                seriesYAxisReverseMap: [],
                // series index → yAxis index
                noData: false
                // true when there is nothing to render
            };
            return (
                /** @type {import('../../types/internal').ChartGlobals} */
                /** @type {unknown} */
                globals
            );
        }
        /**
         * @param {Record<string, any>} config
         */
        init(config) {
            const globals = this.globalVars(config);
            this.initGlobalVars(globals);
            globals.initialConfig = Utils$1.extend({}, config);
            globals.initialSeries = Utils$1.clone(config.series);
            globals.lastXAxis = Utils$1.clone(
                /** @type {NonNullable<typeof globals.initialConfig>} */
                globals.initialConfig.xaxis
            );
            globals.lastYAxis = Utils$1.clone(
                /** @type {NonNullable<typeof globals.initialConfig>} */
                globals.initialConfig.yaxis
            );
            return globals;
        }
    }
    class Base {
        /**
         * @param {object} opts
         */
        constructor(opts) {
            this.opts = opts;
        }
        /**
         * Build and return the full chart state object `w`.
         * @returns {import('../types/internal').ChartStateW}
         */
        init() {
            const config = new Config(this.opts).init({
                responsiveOverride: false
            });
            const globals = new Globals().init(config);
            const w = {
                config,
                globals,
                dom: {},
                // DOM node cache — lives here, not inside globals
                interact: {
                    // Tool mode (derived from toolbar config at construction, updated by Toolbar)
                    zoomEnabled: config.chart.toolbar.autoSelected === "zoom" && config.chart.toolbar.tools.zoom && config.chart.zoom.enabled,
                    panEnabled: config.chart.toolbar.autoSelected === "pan" && config.chart.toolbar.tools.pan,
                    selectionEnabled: config.chart.toolbar.autoSelected === "selection" && config.chart.toolbar.tools.selection,
                    // Zoom / pan state (user-driven, must persist across re-renders)
                    zoomed: false,
                    selection: void 0,
                    visibleXRange: void 0,
                    selectedDataPoints: [],
                    // Mouse / pointer state
                    mousedown: false,
                    clientX: null,
                    clientY: null,
                    lastClientPosition: {},
                    lastWheelExecution: 0,
                    // Tooltip capture state
                    capturedSeriesIndex: -1,
                    capturedDataPointIndex: -1,
                    // Timescale zoom bounds (reset per render by TimeScale)
                    disableZoomIn: false,
                    disableZoomOut: false,
                    // Device detection (set once at construction)
                    isTouchDevice: Environment.isBrowser() ? "ontouchstart" in window || navigator.maxTouchPoints > 0 : false
                },
                formatters: {
                    // Populated by Formatters.setLabelFormatters() each render
                    xLabelFormatter: void 0,
                    yLabelFormatters: [],
                    xaxisTooltipFormatter: void 0,
                    ttKeyFormatter: void 0,
                    ttVal: void 0,
                    ttZFormatter: void 0,
                    legendFormatter: void 0
                },
                // Candlestick / boxplot OHLC arrays — written by Data.handleCandleStickBoxData()
                // each render; empty for all other chart types.
                candleData: {
                    seriesCandleO: [],
                    seriesCandleH: [],
                    seriesCandleM: [],
                    seriesCandleL: [],
                    seriesCandleC: []
                },
                // Range chart arrays — written by Data.handleRangeData() each render;
                // empty for all other chart types.
                rangeData: {
                    seriesRangeStart: [],
                    seriesRangeEnd: [],
                    seriesRange: []
                },
                // Label / category data — written by Data.parseData() and TimeScale each render.
                labelData: {
                    labels: [],
                    categoryLabels: [],
                    timescaleLabels: [],
                    // written by TimeScale.calculateTimeScaleMinMax()
                    hasXaxisGroups: false,
                    groups: [],
                    seriesGroups: []
                },
                // Axis / parsing behaviour flags — written by Data.parseData() each render.
                axisFlags: {
                    isXNumeric: false,
                    dataFormatXNumeric: false,
                    isDataXYZ: false,
                    isRangeData: false,
                    isRangeBar: false,
                    isMultiLineX: false,
                    noLabelsProvided: false,
                    dataWasParsed: false
                },
                // Parsed series data — written by Data.parseData() each render.
                // Note: initialSeries and originalSeries are intentionally excluded —
                // they are persistent (survive re-renders) and remain on w.globals.
                seriesData: {
                    series: [],
                    // main y-values array
                    seriesNames: [],
                    seriesX: [],
                    seriesZ: [],
                    seriesColors: [],
                    seriesGoals: [],
                    stackedSeriesTotals: [],
                    stackedSeriesTotalsByGroups: []
                },
                // Grid / axis layout computed by Dimensions.plotCoords() each render.
                // gridWidth/gridHeight/translateX/translateY are also used as starting
                // points by Dimensions on the next render (accumulated values), so the
                // shim must be bidirectional — reads and writes both route correctly.
                layout: {
                    gridHeight: 0,
                    gridWidth: 0,
                    translateX: 0,
                    translateY: 0,
                    translateXAxisX: 0,
                    translateXAxisY: 0,
                    rotateXLabels: false,
                    xAxisHeight: 0,
                    xAxisLabelsHeight: 0,
                    xAxisGroupLabelsHeight: 0,
                    xAxisLabelsWidth: 0,
                    yLabelsCoords: [],
                    yTitleCoords: []
                }
            };
            Object.defineProperty(globals, "dom", {
                get() {
                    return w.dom;
                },
                set(v) {
                    w.dom = v;
                },
                enumerable: false,
                configurable: true
            });
            for (const key of [
                    "xLabelFormatter",
                    "yLabelFormatters",
                    "xaxisTooltipFormatter",
                    "ttKeyFormatter",
                    "ttVal",
                    "ttZFormatter",
                    "legendFormatter"
                ]) {
                Object.defineProperty(globals, key, {
                    get() {
                        return (
                            /** @type {Record<string,any>} */
                            w.formatters[key]
                        );
                    },
                    set(v) {
                        w.formatters[key] = v;
                    },
                    enumerable: false,
                    configurable: true
                });
            }
            for (const key of [
                    "zoomEnabled",
                    "panEnabled",
                    "selectionEnabled",
                    "zoomed",
                    "selection",
                    "visibleXRange",
                    "selectedDataPoints",
                    "mousedown",
                    "clientX",
                    "clientY",
                    "lastClientPosition",
                    "lastWheelExecution",
                    "capturedSeriesIndex",
                    "capturedDataPointIndex",
                    "disableZoomIn",
                    "disableZoomOut",
                    "isTouchDevice"
                ]) {
                Object.defineProperty(globals, key, {
                    get() {
                        return (
                            /** @type {Record<string,any>} */
                            w.interact[key]
                        );
                    },
                    set(v) {
                        w.interact[key] = v;
                    },
                    enumerable: false,
                    configurable: true
                });
            }
            for (const key of [
                    "gridHeight",
                    "gridWidth",
                    "translateX",
                    "translateY",
                    "translateXAxisX",
                    "translateXAxisY",
                    "rotateXLabels",
                    "xAxisHeight",
                    "xAxisLabelsHeight",
                    "xAxisGroupLabelsHeight",
                    "xAxisLabelsWidth",
                    "yLabelsCoords",
                    "yTitleCoords"
                ]) {
                Object.defineProperty(globals, key, {
                    get() {
                        return (
                            /** @type {Record<string,any>} */
                            w.layout[key]
                        );
                    },
                    set(v) {
                        w.layout[key] = v;
                    },
                    enumerable: false,
                    configurable: true
                });
            }
            for (const key of [
                    "series",
                    "seriesNames",
                    "seriesX",
                    "seriesZ",
                    "seriesColors",
                    "seriesGoals",
                    "stackedSeriesTotals",
                    "stackedSeriesTotalsByGroups"
                ]) {
                Object.defineProperty(globals, key, {
                    get() {
                        return (
                            /** @type {Record<string,any>} */
                            w.seriesData[key]
                        );
                    },
                    set(v) {
                        w.seriesData[key] = v;
                    },
                    enumerable: false,
                    configurable: true
                });
            }
            for (const key of [
                    "isXNumeric",
                    "dataFormatXNumeric",
                    "isDataXYZ",
                    "isRangeData",
                    "isRangeBar",
                    "isMultiLineX",
                    "noLabelsProvided",
                    "dataWasParsed"
                ]) {
                Object.defineProperty(globals, key, {
                    get() {
                        return (
                            /** @type {Record<string,any>} */
                            w.axisFlags[key]
                        );
                    },
                    set(v) {
                        w.axisFlags[key] = v;
                    },
                    enumerable: false,
                    configurable: true
                });
            }
            for (const key of [
                    "labels",
                    "categoryLabels",
                    "timescaleLabels",
                    "hasXaxisGroups",
                    "groups",
                    "seriesGroups"
                ]) {
                Object.defineProperty(globals, key, {
                    get() {
                        return (
                            /** @type {Record<string,any>} */
                            w.labelData[key]
                        );
                    },
                    set(v) {
                        w.labelData[key] = v;
                    },
                    enumerable: false,
                    configurable: true
                });
            }
            for (const key of ["seriesRangeStart", "seriesRangeEnd", "seriesRange"]) {
                Object.defineProperty(globals, key, {
                    get() {
                        return (
                            /** @type {Record<string,any>} */
                            w.rangeData[key]
                        );
                    },
                    set(v) {
                        w.rangeData[key] = v;
                    },
                    enumerable: false,
                    configurable: true
                });
            }
            for (const key of [
                    "seriesCandleO",
                    "seriesCandleH",
                    "seriesCandleM",
                    "seriesCandleL",
                    "seriesCandleC"
                ]) {
                Object.defineProperty(globals, key, {
                    get() {
                        return (
                            /** @type {Record<string,any>} */
                            w.candleData[key]
                        );
                    },
                    set(v) {
                        w.candleData[key] = v;
                    },
                    enumerable: false,
                    configurable: true
                });
            }
            return (
                /** @type {import('../types/internal').ChartStateW} */
                /** @type {unknown} */
                w
            );
        }
    }
    class CoreUtils {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
        }
        /**
         * @param {any[]} series
         * @param {string} chartType
         */
        static checkComboSeries(series, chartType) {
            let comboCharts = false;
            let comboBarCount = 0;
            let comboCount = 0;
            if (chartType === void 0) {
                chartType = "line";
            }
            if (series.length && typeof series[0].type !== "undefined") {
                series.forEach((s) => {
                    if (s.type === "bar" || s.type === "column" || s.type === "candlestick" || s.type === "boxPlot") {
                        comboBarCount++;
                    }
                    if (typeof s.type !== "undefined" && s.type !== chartType) {
                        comboCount++;
                    }
                });
            }
            if (comboCount > 0) {
                comboCharts = true;
            }
            return {
                comboBarCount,
                comboCharts
            };
        }
        /**
         * @memberof CoreUtils
         * returns the sum of all individual values in a multiple stacked series
         * Eg. w.seriesData.series = [[32,33,43,12], [2,3,5,1]]
         *  @return [34,36,48,13]
         * @param {number[]} excludedSeriesIndices
         **/
        getStackedSeriesTotals(excludedSeriesIndices = []) {
            const w = this.w;
            const total = [];
            if (w.seriesData.series.length === 0) return total;
            for (let i = 0; i < w.seriesData.series[w.globals.maxValsInArrayIndex].length; i++) {
                let t = 0;
                for (let j = 0; j < w.seriesData.series.length; j++) {
                    if (typeof w.seriesData.series[j][i] !== "undefined" && excludedSeriesIndices.indexOf(j) === -1) {
                        t += w.seriesData.series[j][i];
                    }
                }
                total.push(t);
            }
            return total;
        }
        // get total of the all values inside all series
        /**
         * @param {number | null} [index]
         */
        getSeriesTotalByIndex(index = null) {
            if (index === null) {
                return (
                    /** @type {any[]} */
                    this.w.config.series.reduce(
                        (acc, cur) => acc + cur,
                        0
                    )
                );
            } else {
                const seriesAtIndex = this.w.seriesData.series[index];
                if (!Array.isArray(seriesAtIndex)) {
                    return seriesAtIndex != null ? seriesAtIndex : 0;
                }
                return seriesAtIndex.reduce(
                    (acc, cur) => acc + cur,
                    0
                );
            }
        }
        /**
         * @memberof CoreUtils
         * returns the sum of values in a multiple stacked grouped charts
         * Eg. w.seriesData.series = [[32,33,43,12], [2,3,5,1], [43, 23, 34, 22]]
         * series 1 and 2 are in a group, while series 3 is in another group
         *  @return [[34, 36, 48, 12], [43, 23, 34, 22]]
         **/
        getStackedSeriesTotalsByGroups() {
            const w = this.w;
            const total = [];
            w.labelData.seriesGroups.forEach((sg) => {
                const includedIndexes = [];
                w.config.series.forEach((s, si) => {
                    if (sg.indexOf(w.seriesData.seriesNames[si]) > -1) {
                        includedIndexes.push(si);
                    }
                });
                const excludedIndices = w.seriesData.series.map((_, fi) => includedIndexes.indexOf(fi) === -1 ? fi : -1).filter((f) => f !== -1);
                total.push(this.getStackedSeriesTotals(excludedIndices));
            });
            return total;
        }
        setSeriesYAxisMappings() {
            const gl = this.w.globals;
            const cnf = this.w.config;
            let axisSeriesMap = [];
            const seriesYAxisReverseMap = [];
            const unassignedSeriesIndices = [];
            const seriesNameArrayStyle = this.w.seriesData.series.length > cnf.yaxis.length ||
                /**
                 * @param {ApexYAxis} a
                 */
                cnf.yaxis.some((a) => Array.isArray(a.seriesName));
            cnf.series.forEach((_s, i) => {
                unassignedSeriesIndices.push(i);
                seriesYAxisReverseMap.push(null);
            });
            cnf.yaxis.forEach(
                (_yaxe, yi) => {
                    axisSeriesMap[yi] = [];
                }
            );
            const unassignedYAxisIndices = [];
            cnf.yaxis.forEach((yaxe, yi) => {
                let assigned = false;
                if (yaxe.seriesName) {
                    let seriesNames = [];
                    if (Array.isArray(yaxe.seriesName)) {
                        seriesNames = yaxe.seriesName;
                    } else {
                        seriesNames.push(yaxe.seriesName);
                    }
                    seriesNames.forEach((name2) => {
                        cnf.series.forEach((s, si) => {
                            if (
                                /** @type {any} */
                                s.name === name2
                            ) {
                                let remove = si;
                                if (yi === si || seriesNameArrayStyle) {
                                    if (!seriesNameArrayStyle || unassignedSeriesIndices.indexOf(si) > -1) {
                                        axisSeriesMap[yi].push([yi, si]);
                                    } else {
                                        console.warn(
                                            "Series '" + /** @type {any} */
                                            s.name + "' referenced more than once in what looks like the new style. That is, when using either seriesName: [], or when there are more series than yaxes."
                                        );
                                    }
                                } else {
                                    axisSeriesMap[si].push([si, yi]);
                                    remove = yi;
                                }
                                assigned = true;
                                remove = unassignedSeriesIndices.indexOf(remove);
                                if (remove !== -1) {
                                    unassignedSeriesIndices.splice(remove, 1);
                                }
                            }
                        });
                    });
                }
                if (!assigned) {
                    unassignedYAxisIndices.push(yi);
                }
            });
            axisSeriesMap = axisSeriesMap.map((yaxe) => {
                const ra = [];
                yaxe.forEach((sa) => {
                    seriesYAxisReverseMap[sa[1]] = sa[0];
                    ra.push(sa[1]);
                });
                return ra;
            });
            let lastUnassignedYAxis = cnf.yaxis.length - 1;
            for (let i = 0; i < unassignedYAxisIndices.length; i++) {
                lastUnassignedYAxis = unassignedYAxisIndices[i];
                axisSeriesMap[lastUnassignedYAxis] = [];
                if (unassignedSeriesIndices) {
                    const si = unassignedSeriesIndices[0];
                    unassignedSeriesIndices.shift();
                    axisSeriesMap[lastUnassignedYAxis].push(si);
                    seriesYAxisReverseMap[si] = lastUnassignedYAxis;
                } else {
                    break;
                }
            }
            unassignedSeriesIndices.forEach((i) => {
                axisSeriesMap[lastUnassignedYAxis].push(i);
                seriesYAxisReverseMap[i] = lastUnassignedYAxis;
            });
            gl.seriesYAxisMap = axisSeriesMap.map((x) => x);
            gl.seriesYAxisReverseMap = seriesYAxisReverseMap.map((x) => x);
            gl.seriesYAxisMap.forEach((axisSeries, ai) => {
                axisSeries.forEach((si) => {
                    if (
                        /** @type {any} */
                        cnf.series[si] && /** @type {any} */
                        cnf.series[si].group === void 0
                    ) {
                        const _series = (
                            /** @type {any} */
                            cnf.series[si]
                        );
                        _series.group = "apexcharts-axis-".concat(ai.toString());
                    }
                });
            });
        }
        /**
         * @param {number | null} [index]
         */
        isSeriesNull(index = null) {
            let r = [];
            const series = (
                /** @type {any[]} */
                this.w.config.series
            );
            if (index === null) {
                r = series.filter((d) => d !== null);
            } else if (series[index] && Array.isArray(series[index].data)) {
                r = series[index].data.filter((d) => d !== null);
            } else {
                r = series[index] !== null && series[index] !== void 0 ? [series[index]] : [];
            }
            return r.length === 0;
        }
        /**
         * @param {number} index
         */
        seriesHaveSameValues(index) {
            const seriesAtIndex = this.w.seriesData.series[index];
            if (!Array.isArray(seriesAtIndex)) {
                return true;
            }
            return seriesAtIndex.every(
                (val, i, arr) => val === arr[0]
            );
        }
        /**
         * @param {any[]} labels
         */
        getCategoryLabels(labels) {
            const w = this.w;
            let catLabels = labels.slice();
            if (w.config.xaxis.convertedCatToNumeric) {
                catLabels = labels.map((i) => {
                    return w.config.xaxis.labels.formatter(i - w.globals.minX + 1);
                });
            }
            return catLabels;
        }
        // maxValsInArrayIndex is the index of series[] which has the largest number of items
        getLargestSeries() {
            const w = this.w;
            w.globals.maxValsInArrayIndex = w.seriesData.series.map((a) => a.length).indexOf(
                Math.max.apply(
                    Math,
                    /**
                     * @param {number[]} a
                     */
                    w.seriesData.series.map((a) => a.length)
                )
            );
        }
        getLargestMarkerSize() {
            const w = this.w;
            let size = 0;
            w.globals.markers.size.forEach((m) => {
                size = Math.max(size, m);
            });
            if (w.config.markers.discrete && w.config.markers.discrete.length) {
                w.config.markers.discrete.forEach((m) => {
                    size = Math.max(size, m.size);
                });
            }
            if (size > 0) {
                if (w.config.markers.hover.size > 0) {
                    size = w.config.markers.hover.size;
                } else {
                    size += w.config.markers.hover.sizeOffset;
                }
            }
            w.globals.markers.largestSize = size;
            return size;
        }
        /**
         * @memberof Core
         * returns the sum of all values in a series
         * Eg. w.seriesData.series = [[32,33,43,12], [2,3,5,1]]
         *  @return [120, 11]
         **/
        getSeriesTotals() {
            const w = this.w;
            w.globals.seriesTotals = w.seriesData.series.map((ser) => {
                let total = 0;
                if (Array.isArray(ser)) {
                    for (let j = 0; j < ser.length; j++) {
                        total += ser[j];
                    }
                } else {
                    total += ser;
                }
                return total;
            });
        }
        /**
         * @param {number} minX
         * @param {number} maxX
         */
        getSeriesTotalsXRange(minX, maxX) {
            const w = this.w;
            const seriesTotalsXRange = w.seriesData.series.map((ser, index) => {
                let total = 0;
                for (let j = 0; j < ser.length; j++) {
                    if (w.seriesData.seriesX[index][j] > minX && w.seriesData.seriesX[index][j] < maxX) {
                        total += ser[j];
                    }
                }
                return total;
            });
            return seriesTotalsXRange;
        }
        /**
         * @memberof CoreUtils
         * returns the percentage value of all individual values which can be used in a 100% stacked series
         * Eg. w.seriesData.series = [[32, 33, 43, 12], [2, 3, 5, 1]]
         *  @return [[94.11, 91.66, 89.58, 92.30], [5.88, 8.33, 10.41, 7.7]]
         **/
        getPercentSeries() {
            const w = this.w;
            w.globals.seriesPercent = w.seriesData.series.map((ser) => {
                const seriesPercent = [];
                if (Array.isArray(ser)) {
                    for (let j = 0; j < ser.length; j++) {
                        const total = w.seriesData.stackedSeriesTotals[j];
                        let percent = 0;
                        if (total) {
                            percent = 100 * ser[j] / total;
                        }
                        seriesPercent.push(percent);
                    }
                } else {
                    const total = w.globals.seriesTotals.reduce((acc, val) => acc + val, 0);
                    const percent = 100 * ser / total;
                    seriesPercent.push(percent);
                }
                return seriesPercent;
            });
        }
        getCalculatedRatios() {
            const w = this.w;
            const gl = w.globals;
            const yRatio = [];
            let invertedYRatio = 0;
            let xRatio = 0;
            let invertedXRatio = 0;
            let zRatio = 0;
            let baseLineY = [];
            let baseLineInvertedY = 0.1;
            let baseLineX = 0;
            gl.yRange = [];
            if (gl.isMultipleYAxis) {
                for (let i = 0; i < gl.minYArr.length; i++) {
                    gl.yRange.push(Math.abs(gl.minYArr[i] - gl.maxYArr[i]));
                    baseLineY.push(0);
                }
            } else {
                gl.yRange.push(Math.abs(gl.minY - gl.maxY));
            }
            gl.xRange = Math.abs(gl.maxX - gl.minX);
            gl.zRange = Math.abs(gl.maxZ - gl.minZ);
            for (let i = 0; i < gl.yRange.length; i++) {
                yRatio.push(gl.yRange[i] / this.w.layout.gridHeight);
            }
            xRatio = gl.xRange / this.w.layout.gridWidth;
            invertedYRatio = /** @type {any} */
                gl.yRange / this.w.layout.gridWidth;
            invertedXRatio = gl.xRange / this.w.layout.gridHeight;
            zRatio = gl.zRange / this.w.layout.gridHeight * 16;
            if (!zRatio) {
                zRatio = 1;
            }
            if (gl.minY !== Number.MIN_VALUE && Math.abs(gl.minY) !== 0) {
                const _hasNegsGl = (
                    /** @type {any} */
                    gl
                );
                _hasNegsGl.hasNegs = true;
            }
            if (w.globals.seriesYAxisReverseMap.length > 0) {
                const scaleBaseLineYScale = (y, i) => {
                    const yAxis = w.config.yaxis[w.globals.seriesYAxisReverseMap[i]];
                    const sign = y < 0 ? -1 : 1;
                    y = Math.abs(y);
                    if (yAxis.logarithmic) {
                        y = this.getBaseLog(yAxis.logBase, y);
                    }
                    return -sign * y / yRatio[i];
                };
                if (gl.isMultipleYAxis) {
                    baseLineY = [];
                    for (let i = 0; i < yRatio.length; i++) {
                        baseLineY.push(scaleBaseLineYScale(gl.minYArr[i], i));
                    }
                } else {
                    baseLineY = [];
                    baseLineY.push(scaleBaseLineYScale(gl.minY, 0));
                    if (gl.minY !== Number.MIN_VALUE && Math.abs(gl.minY) !== 0) {
                        baseLineInvertedY = -gl.minY / invertedYRatio;
                        baseLineX = gl.minX / xRatio;
                    }
                }
            } else {
                baseLineY = [];
                baseLineY.push(0);
                baseLineInvertedY = 0;
                baseLineX = 0;
            }
            return {
                yRatio,
                invertedYRatio,
                zRatio,
                xRatio,
                invertedXRatio,
                baseLineInvertedY,
                baseLineY,
                baseLineX
            };
        }
        /**
         * @param {any[]} series
         */
        getLogSeries(series) {
            const w = this.w;
            w.globals.seriesLog = series.map((s, i) => {
                const yAxisIndex = w.globals.seriesYAxisReverseMap[i];
                if (w.config.yaxis[yAxisIndex] && w.config.yaxis[yAxisIndex].logarithmic) {
                    return s.map((d) => {
                        if (d === null) return null;
                        return this.getLogVal(w.config.yaxis[yAxisIndex].logBase, d, i);
                    });
                } else {
                    return s;
                }
            });
            return w.globals.invalidLogScale ? series : w.globals.seriesLog;
        }
        /**
         * @param {number} val
         * @param {number} seriesIndex
         * @returns {number}
         */
        getLogValAtSeriesIndex(val, seriesIndex) {
            if (val === null) return (
                /** @type {any} */
                null
            );
            const w = this.w;
            const yAxisIndex = w.globals.seriesYAxisReverseMap[seriesIndex];
            if (w.config.yaxis[yAxisIndex] && w.config.yaxis[yAxisIndex].logarithmic) {
                return this.getLogVal(
                    w.config.yaxis[yAxisIndex].logBase,
                    val,
                    seriesIndex
                );
            }
            return val;
        }
        /**
         * @param {number} base
         * @param {number} value
         */
        getBaseLog(base, value) {
            return Math.log(value) / Math.log(base);
        }
        /**
         * @param {number} b
         * @param {number} d
         * @param {number} seriesIndex
         */
        getLogVal(b, d, seriesIndex) {
            if (d <= 0) {
                return 0;
            }
            const w = this.w;
            const min_log_val = w.globals.minYArr[seriesIndex] === 0 ? -1 : this.getBaseLog(b, w.globals.minYArr[seriesIndex]);
            const max_log_val = w.globals.maxYArr[seriesIndex] === 0 ? 0 : this.getBaseLog(b, w.globals.maxYArr[seriesIndex]);
            const number_of_height_levels = max_log_val - min_log_val;
            if (d < 1) return d / number_of_height_levels;
            const log_height_value = this.getBaseLog(b, d) - min_log_val;
            return log_height_value / number_of_height_levels;
        }
        /**
         * @param {number[]} yRatio
         */
        getLogYRatios(yRatio) {
            const w = this.w;
            const gl = this.w.globals;
            const _gl = (
                /** @type {any} */
                gl
            );
            _gl.yLogRatio = yRatio.slice();
            _gl.logYRange = /** @type {any[]} */
                gl.yRange.map(
                    (_, i) => {
                        const yAxisIndex = w.globals.seriesYAxisReverseMap[i];
                        if (w.config.yaxis[yAxisIndex] && this.w.config.yaxis[yAxisIndex].logarithmic) {
                            let maxY = -Number.MAX_VALUE;
                            let minY = Number.MIN_VALUE;
                            let range = 1;
                            gl.seriesLog.forEach(
                                (s, si) => {
                                    s.forEach((v) => {
                                        if (w.config.yaxis[si] && w.config.yaxis[si].logarithmic) {
                                            maxY = Math.max(v, maxY);
                                            minY = Math.min(v, minY);
                                        }
                                    });
                                }
                            );
                            range = Math.pow(gl.yRange[i], Math.abs(minY - maxY) / gl.yRange[i]);
                            _gl.yLogRatio[i] = range / this.w.layout.gridHeight;
                            return range;
                        }
                    }
                );
            return _gl.invalidLogScale ? yRatio.slice() : _gl.yLogRatio;
        }
        // Some config objects can be array - and we need to extend them correctly
        /**
         * @param {any} configInstance
         * @param {Record<string, any>} options
         * @param {import('../types/internal').ChartStateW} w
         */
        static extendArrayProps(configInstance, options2, w) {
            var _a, _b;
            if (options2 == null ? void 0 : options2.yaxis) {
                options2 = configInstance.extendYAxis(options2, w);
            }
            if (options2 == null ? void 0 : options2.annotations) {
                if (options2.annotations.yaxis) {
                    options2 = configInstance.extendYAxisAnnotations(options2);
                }
                if ((_a = options2 == null ? void 0 : options2.annotations) == null ? void 0 : _a.xaxis) {
                    options2 = configInstance.extendXAxisAnnotations(options2);
                }
                if ((_b = options2 == null ? void 0 : options2.annotations) == null ? void 0 : _b.points) {
                    options2 = configInstance.extendPointAnnotations(options2);
                }
            }
            return options2;
        }
        // Series of the same group and type can be stacked together distinct from
        // other series of the same type on the same axis.
        /**
         * @param {Record<string, any>} typeSeries
         * @param {string[]} typeGroups
         * @param {string} type
         * @param {string} chartClass
         */
        drawSeriesByGroup(typeSeries, typeGroups, type, chartClass) {
            const w = this.w;
            const graph = [];
            if (typeSeries.series.length > 0) {
                typeGroups.forEach((gn) => {
                    const gs = [];
                    const gi = [];
                    typeSeries.i.forEach((i, ii) => {
                        if (
                            /** @type {Record<string,any>} */
                            w.config.series[i].group === gn
                        ) {
                            gs.push(typeSeries.series[ii]);
                            gi.push(i);
                        }
                    });
                    gs.length > 0 && graph.push(
                        /** @type {any} */
                        chartClass.draw(gs, type, gi)
                    );
                });
            }
            return graph;
        }
    }
    const SVGNS$1 = "http://www.w3.org/2000/svg";

    function easeOutCubic(t) {
        return 1 - Math.pow(1 - t, 3);
    }

    function easeOutBack(t) {
        const c1 = 1.70158;
        const c3 = c1 + 1;
        return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
    }
    let _reducedMotionMql = null;

    function prefersReducedMotion() {
        if (!Environment.isBrowser()) return false;
        try {
            if (!_reducedMotionMql) {
                _reducedMotionMql = window.matchMedia("(prefers-reduced-motion: reduce)");
            }
            return !!_reducedMotionMql.matches;
        } catch (_) {
            return false;
        }
    }

    function applyProgressiveReveal(el, x, w) {
        if (!Environment.isBrowser()) return false;
        if (w.globals.dataChanged || w.globals.resized) return false;
        const animCfg = w.config.chart.animations;
        if (!animCfg || animCfg.enabled === false) return false;
        const chartType = w.config.chart.type;
        if (chartType !== "line" && chartType !== "area" && chartType !== "rangeArea") {
            return false;
        }
        if (!(w.layout.gridWidth > 0)) return false;
        const drawSpeed = (animCfg.speed || 800) * 2;
        const xRatio = Math.max(0, Math.min(1, x / w.layout.gridWidth));
        const easedT = 1 - Math.cbrt(1 - xRatio);
        const revealDelay = easedT * drawSpeed;
        const node = el.node;
        const style = node.style;
        style.opacity = "0";
        let startAnchor = null;
        const tick = (now) => {
            if (startAnchor === null) startAnchor = now;
            if (now - startAnchor >= revealDelay) {
                style.opacity = "";
            } else {
                BrowserAPIs.requestAnimationFrame(tick);
            }
        };
        BrowserAPIs.requestAnimationFrame(tick);
        return true;
    }

    function applyAnimationPolicy(w) {
        const anim = w.config.chart.animations;
        if (!anim) return;
        if (anim.respectReducedMotion !== false && prefersReducedMotion()) {
            anim.enabled = false;
            if (anim.dynamicAnimation) anim.dynamicAnimation.enabled = false;
        }
    }

    function computeStagger(opts) {
        const style = opts.style;
        const index = opts.index || 0;
        const baseDelay = typeof opts.baseDelay === "number" ? opts.baseDelay : 40;
        const row = opts.row || 0;
        const col = opts.col || 0;
        const groupIndex = opts.groupIndex || 0;
        const perGroup = opts.perGroup || 1;
        const centerDistance = opts.centerDistance || 0;
        switch (style) {
            case "none":
                return 0;
            case "diagonal":
                return (row + col) * baseDelay;
            case "group":
                return groupIndex * baseDelay + index % perGroup * (baseDelay / 4);
            case "centroid":
                return centerDistance * baseDelay * (index + 1);
            case "sequential":
            default:
                return index * baseDelay;
        }
    }
    class Animations {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} [ctx]
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
        }
        /**
         * @param {any} el
         * @param {Record<string, any>} from
         * @param {Record<string, any>} to
         * @param {object} speed
         */
        animateLine(el, from, to, speed) {
            el.attr(from).animate(speed).attr(to);
        }
        /*
         ** Animate radius of a circle element
         * @param {any} el
         * @param {number} speed
         * @param {string} easing
         * @param {Function} cb
         */
        /** @param {any} el @param {any} speed @param {any} easing @param {any} cb */
        animateMarker(el, speed, easing, cb) {
            el.attr({
                opacity: 0
            }).animate(speed).attr({
                opacity: 1
            }).after(() => {
                cb();
            });
        }
        /**
         * Scale-up "pop" effect for scatter/bubble markers. Animates
         * `transform: scale(0 → 1)` (with `easeOutBack` overshoot) plus opacity,
         * around the marker's own center via `transform-box: fill-box`.
         *
         * Falls back to instant render in SSR / when shouldAnimate is false.
         *
         * @param {any} el
         * @param {{ speed: number, delay?: number, onComplete?: () => void }} params
         */
        animatePop(el, {
            speed,
            delay = 0,
            onComplete
        }) {
            const w = this.w;
            if (!Environment.isBrowser() || !w.globals.shouldAnimate || speed < 1) {
                if (onComplete) onComplete();
                return;
            }
            const node = el.node;
            const style = node.style;
            style.transformBox = "fill-box";
            style.transformOrigin = "center";
            style.transform = "scale(0)";
            style.opacity = "0";
            const startAt = performance.now() + delay;
            const step = (now) => {
                const t = Math.max(0, Math.min(1, (now - startAt) / speed));
                style.transform = `scale(${easeOutBack(t)})`;
                style.opacity = String(Math.min(1, t * 2));
                if (t < 1) {
                    BrowserAPIs.requestAnimationFrame(step);
                } else {
                    style.transform = "";
                    style.transformOrigin = "";
                    style.transformBox = "";
                    style.opacity = "";
                    if (onComplete) onComplete();
                }
            };
            BrowserAPIs.requestAnimationFrame(step);
        }
        /*
         ** Animate rect properties
         * @param {any} el
         * @param {any} from
         * @param {any} to
         * @param {number} speed
         * @param {Function} fn
         */
        /** @param {any} el @param {any} from @param {any} to @param {any} speed @param {any} fn @param {number} [delay] */
        animateRect(el, from, to, speed, fn, delay = 0) {
            el.attr(from).animate(speed, delay).attr(to).after(() => fn());
        }
        /**
         * @param {Record<string, any>} params
         */
        animatePathsGradually(params) {
            const {
                el,
                realIndex,
                j,
                fill,
                pathFrom,
                pathTo,
                speed,
                delay
            } = params;
            const me = this;
            const w = this.w;
            let delayFactor = 0;
            if (w.config.chart.animations.animateGradually.enabled) {
                delayFactor = w.config.chart.animations.animateGradually.delay;
            }
            if (w.config.chart.animations.dynamicAnimation.enabled && w.globals.dataChanged && w.config.chart.type !== "bar") {
                delayFactor = 0;
            }
            me.morphSVG(
                el,
                realIndex,
                j,
                w.config.chart.type === "line" && !w.globals.comboCharts ? "stroke" : fill,
                pathFrom,
                pathTo,
                speed,
                delay * delayFactor
            );
        }
        showDelayedElements() {
            this.w.globals.delayedElements.forEach((d) => {
                const ele = d.el;
                ele.classList.remove("apexcharts-element-hidden");
                ele.classList.add("apexcharts-hidden-element-shown");
            });
        }
        /**
         * @param {any} el
         */
        animationCompleted(el) {
            const w = this.w;
            if (w.globals.animationEnded) return;
            w.globals.animationEnded = true;
            this.showDelayedElements();
            if (typeof w.config.chart.events.animationEnd === "function") {
                w.config.chart.events.animationEnd(this.ctx, {
                    el,
                    w
                });
            }
        }
        /**
         * Initial-mount "pen-stroke" draw effect for line / area / rangeArea paths.
         *
         * Stroke paths animate `stroke-dashoffset` from total length → 0.
         * Fill paths animate the width of a per-series SVG `<mask>` rect from 0 → gridWidth,
         * which coexists with the existing `clip-path: gridRectMask` (mask + clip-path
         * are independent SVG attributes).
         *
         * For radar / radial shapes, pass `mask: { type: 'radial', cx, cy, r }` to
         * use a circular mask that blooms from center outward instead of the default
         * left-to-right rect wipe.
         *
         * @param {any} el            - SVG.js path element
         * @param {{realIndex: number, j?: number, isFill: boolean, isLast: boolean, speed: number, delay: number, mask?: {type: 'rect'|'radial', cx?: number, cy?: number, r?: number}}} params
         */
        animateDraw(el, {
            realIndex,
            j,
            isFill,
            isLast,
            speed,
            delay,
            mask: maskShape
        }) {
            const w = this.w;
            const me = this;
            const finalize = () => {
                if (isLast && w.globals.shouldAnimate) {
                    me.animationCompleted(el);
                }
                me.showDelayedElements();
            };
            if (!Environment.isBrowser() || !w.globals.shouldAnimate || speed < 1) {
                finalize();
                return;
            }
            const node = el.node;
            const runMaskReveal = () => {
                const pad = 4;
                const isRadial = maskShape && maskShape.type === "radial";
                const targetWidth = w.layout.gridWidth + pad * 2;
                const radialCx = maskShape && maskShape.cx || 0;
                const radialCy = maskShape && maskShape.cy || 0;
                const targetRadius = (maskShape && maskShape.r || w.layout.gridWidth / 2) + pad;
                const maskId = `apexDrawMask${w.globals.cuid}-${realIndex}-${j != null ? j : 0}-${isFill ? "f" : "s"}`;
                const mask = BrowserAPIs.createElementNS(SVGNS$1, "mask");
                mask.setAttribute("id", maskId);
                mask.setAttribute("maskUnits", "userSpaceOnUse");
                let revealEl;
                if (isRadial) {
                    const region = targetRadius;
                    mask.setAttribute("x", String(radialCx - region));
                    mask.setAttribute("y", String(radialCy - region));
                    mask.setAttribute("width", String(region * 2));
                    mask.setAttribute("height", String(region * 2));
                    revealEl = BrowserAPIs.createElementNS(SVGNS$1, "circle");
                    revealEl.setAttribute("cx", String(radialCx));
                    revealEl.setAttribute("cy", String(radialCy));
                    revealEl.setAttribute("r", "0");
                    revealEl.setAttribute("fill", "#fff");
                } else {
                    mask.setAttribute("x", String(-pad));
                    mask.setAttribute("y", String(-pad));
                    mask.setAttribute("width", String(targetWidth));
                    mask.setAttribute("height", String(w.layout.gridHeight + pad * 2));
                    revealEl = BrowserAPIs.createElementNS(SVGNS$1, "rect");
                    revealEl.setAttribute("x", String(-pad));
                    revealEl.setAttribute("y", String(-pad));
                    revealEl.setAttribute("width", "0");
                    revealEl.setAttribute("height", String(w.layout.gridHeight + pad * 2));
                    revealEl.setAttribute("fill", "#fff");
                }
                mask.appendChild(revealEl);
                w.dom.elDefs.node.appendChild(mask);
                node.setAttribute("mask", `url(#${maskId})`);
                const startAt = performance.now() + (delay || 0);
                const step = (now) => {
                    const t = Math.max(0, Math.min(1, (now - startAt) / speed));
                    const eased = easeOutCubic(t);
                    if (isRadial) {
                        revealEl.setAttribute("r", String(eased * targetRadius));
                    } else {
                        revealEl.setAttribute("width", String(eased * targetWidth));
                    }
                    if (t < 1) {
                        BrowserAPIs.requestAnimationFrame(step);
                    } else {
                        node.removeAttribute("mask");
                        if (mask.parentNode) mask.parentNode.removeChild(mask);
                        finalize();
                    }
                };
                BrowserAPIs.requestAnimationFrame(step);
            };
            const runStrokeDraw = (len) => {
                node.setAttribute("stroke-dasharray", String(len));
                node.setAttribute("stroke-dashoffset", String(len));
                const startAt = performance.now() + (delay || 0);
                const step = (now) => {
                    const t = Math.max(0, Math.min(1, (now - startAt) / speed));
                    node.setAttribute("stroke-dashoffset", String(len * (1 - easeOutCubic(t))));
                    if (t < 1) {
                        BrowserAPIs.requestAnimationFrame(step);
                    } else {
                        node.removeAttribute("stroke-dasharray");
                        node.removeAttribute("stroke-dashoffset");
                        finalize();
                    }
                };
                BrowserAPIs.requestAnimationFrame(step);
            };
            BrowserAPIs.requestAnimationFrame(() => {
                if (isFill) {
                    runMaskReveal();
                    return;
                }
                const existingDash = node.getAttribute("stroke-dasharray");
                const hasCustomDash = !!existingDash && existingDash !== "0" && existingDash !== "";
                if (hasCustomDash) {
                    runMaskReveal();
                    return;
                }
                let len = 0;
                try {
                    if (typeof node.getTotalLength === "function") {
                        len = node.getTotalLength();
                    }
                } catch (_) {
                    len = 0;
                }
                if (!len) {
                    finalize();
                    return;
                }
                runStrokeDraw(len);
            });
        }
        // SVG.js animation for morphing one path to another
        /**
         * @param {any} el
         * @param {number} realIndex
         * @param {number} j
         * @param {string} fill
         * @param {string} pathFrom
         * @param {string} pathTo
         * @param {number} speed
         * @param {number} delay
         */
        morphSVG(el, realIndex, j, fill, pathFrom, pathTo, speed, delay) {
            var _a, _b;
            const w = this.w;
            if (!pathFrom) {
                pathFrom = el.attr("pathFrom");
            }
            if (!pathTo) {
                pathTo = el.attr("pathTo");
            }
            const disableAnimationForCorrupPath = () => {
                if (w.config.chart.type === "radar") {
                    speed = 1;
                }
                return `M 0 ${w.layout.gridHeight}`;
            };
            if (!pathFrom || pathFrom.indexOf("undefined") > -1 || pathFrom.indexOf("NaN") > -1) {
                pathFrom = disableAnimationForCorrupPath();
            }
            if (!pathTo.trim() || pathTo.indexOf("undefined") > -1 || pathTo.indexOf("NaN") > -1) {
                pathTo = disableAnimationForCorrupPath();
            }
            if (!w.globals.shouldAnimate) {
                speed = 1;
            }
            const crossTypeMorph = ((_b = (_a = this.ctx) == null ? void 0 : _a.morphTypeChange) == null ? void 0 : _b.isActive()) === true;
            const morphAlgo = crossTypeMorph ? "polygons" : "commands";
            el.plot(pathFrom).animate(1, delay).plot(pathFrom).animate(speed, delay).plot(pathTo, morphAlgo).after(() => {
                if (Utils$1.isNumber(j)) {
                    if (j === w.seriesData.series[w.globals.maxValsInArrayIndex].length - 2 && w.globals.shouldAnimate) {
                        this.animationCompleted(el);
                    }
                } else if (fill !== "none" && w.globals.shouldAnimate) {
                    if (!w.globals.comboCharts && realIndex === w.seriesData.series.length - 1 || w.globals.comboCharts) {
                        this.animationCompleted(el);
                    }
                }
                this.showDelayedElements();
            });
        }
    }
    class Filters {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
        }
        // create a re-usable filter which can be appended other filter effects and applied to multiple elements
        /**
         * @param {any} el
         * @param {number} i
         */
        getDefaultFilter(el, i) {
            const w = this.w;
            if (el.unfilter) {
                el.unfilter(true);
            }
            if (w.config.chart.dropShadow.enabled) {
                this.dropShadow(el, w.config.chart.dropShadow, i);
            }
        }
        /**
         * @param {any} el
         * @param {number} i
         * @param {string} filterType
         */
        applyFilter(el, i, filterType) {
            var _a, _b, _c;
            const w = this.w;
            if (el.unfilter) {
                el.unfilter(true);
            }
            if (filterType === "none") {
                this.getDefaultFilter(el, i);
                return;
            }
            const shadowAttr = w.config.chart.dropShadow;
            const brightnessFactor = filterType === "lighten" ? 2 : 0.3;
            if (el.filterWith) {
                el.filterWith((add) => {
                    add.colorMatrix({
                        type: "matrix",
                        values: `
            ${brightnessFactor} 0 0 0 0
            0 ${brightnessFactor} 0 0 0
            0 0 ${brightnessFactor} 0 0
            0 0 0 1 0
          `,
                        in: "SourceGraphic",
                        result: "brightness"
                    });
                    if (shadowAttr.enabled) {
                        this.addShadow(add, i, shadowAttr, "brightness");
                    }
                });
                if (!shadowAttr.noUserSpaceOnUse) {
                    (_b = (_a = el.filterer()) == null ? void 0 : _a.node) == null ? void 0 : _b.setAttribute("filterUnits", "userSpaceOnUse");
                }
                this._scaleFilterSize((_c = el.filterer()) == null ? void 0 : _c.node);
            }
        }
        // appends dropShadow to the filter object which can be chained with other filter effects
        /**
         * @param {any} add
         * @param {number} i
         * @param {Record<string, any>} attrs
         * @param {string} source
         */
        addShadow(add, i, attrs, source) {
            var _a;
            const w = this.w;
            let {
                blur,
                top,
                left,
                color,
                opacity
            } = attrs;
            color = Array.isArray(color) ? color[i] : color;
            if (((_a = w.config.chart.dropShadow.enabledOnSeries) == null ? void 0 : _a.length) > 0) {
                if (w.config.chart.dropShadow.enabledOnSeries.indexOf(i) === -1) {
                    return add;
                }
            }
            add.offset({
                in: source,
                dx: left,
                dy: top,
                result: "offset"
            });
            add.gaussianBlur({
                in: "offset",
                stdDeviation: blur,
                result: "blur"
            });
            add.flood({
                "flood-color": color,
                "flood-opacity": opacity,
                result: "flood"
            });
            add.composite({
                in: "flood",
                in2: "blur",
                operator: "in",
                result: "shadow"
            });
            add.merge(["shadow", source]);
        }
        // directly adds dropShadow to the element and returns the same element.
        /**
         * @param {any} el
         * @param {Record<string, any>} attrs
         */
        dropShadow(el, attrs, i = 0) {
            var _a, _b, _c, _d, _e;
            const w = this.w;
            if (el.unfilter) {
                el.unfilter(true);
            }
            if (Utils$1.isMsEdge() && w.config.chart.type === "radialBar") {
                return el;
            }
            if (((_a = w.config.chart.dropShadow.enabledOnSeries) == null ? void 0 : _a.length) > 0) {
                if (((_b = w.config.chart.dropShadow.enabledOnSeries) == null ? void 0 : _b.indexOf(i)) === -1) {
                    return el;
                }
            }
            if (el.filterWith) {
                el.filterWith((add) => {
                    this.addShadow(add, i, attrs, "SourceGraphic");
                });
                if (!attrs.noUserSpaceOnUse) {
                    (_d = (_c = el.filterer()) == null ? void 0 : _c.node) == null ? void 0 : _d.setAttribute("filterUnits", "userSpaceOnUse");
                }
                this._scaleFilterSize((_e = el.filterer()) == null ? void 0 : _e.node);
            }
            return el;
        }
        /**
         * @param {any} el
         * @param {number} realIndex
         * @param {number} dataPointIndex
         */
        setSelectionFilter(el, realIndex, dataPointIndex) {
            const w = this.w;
            if (typeof w.interact.selectedDataPoints[realIndex] !== "undefined") {
                if (w.interact.selectedDataPoints[realIndex].indexOf(dataPointIndex) > -1) {
                    el.node.setAttribute("selected", true);
                    const activeFilter = w.config.states.active.filter;
                    if (activeFilter !== "none") {
                        this.applyFilter(el, realIndex, activeFilter.type);
                    }
                }
            }
        }
        /**
         * @param {any} el
         */
        _scaleFilterSize(el) {
            if (!el) return;
            const setAttributes = (attrs) => {
                for (const key in attrs) {
                    if (Object.prototype.hasOwnProperty.call(attrs, key)) {
                        el.setAttribute(key, attrs[key]);
                    }
                }
            };
            setAttributes({
                width: "200%",
                height: "200%",
                x: "-50%",
                y: "-50%"
            });
        }
    }
    class Graphics {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext | null} ctx
         */
        constructor(w, ctx = null) {
            this.w = w;
            this.ctx = ctx;
        }
        /*****************************************************************************
         *                                                                            *
         *  SVG Path Rounding Function                                                *
         *  Copyright (C) 2014 Yona Appletree                                         *
         *                                                                            *
         *  Licensed under the Apache License, Version 2.0 (the "License");           *
         *  you may not use this file except in compliance with the License.          *
         *  You may obtain a copy of the License at                                   *
         *                                                                            *
         *      http://www.apache.org/licenses/LICENSE-2.0                            *
         *                                                                            *
         *  Unless required by applicable law or agreed to in writing, software       *
         *  distributed under the License is distributed on an "AS IS" BASIS,         *
         *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
         *  See the License for the specific language governing permissions and       *
         *  limitations under the License.                                            *
         *                                                                            *
         *****************************************************************************/
        /**
         * SVG Path rounding function. Takes an input path string and outputs a path
         * string where all line-line corners have been rounded. Only supports absolute
         * commands at the moment.
         *
         * @param pathString The SVG input path
         * @param radius The amount to round the corners, either a value in the SVG
         *               coordinate space, or, if useFractionalRadius is true, a value
         *               from 0 to 1.
         * @returns A new SVG path string with the rounding
         * @param {string} pathString
         * @param {number} radius
         */
        roundPathCorners(pathString, radius) {
            if (pathString.indexOf("NaN") > -1) pathString = "";

            function moveTowardsLength(movingPoint, targetPoint, amount) {
                var width = targetPoint.x - movingPoint.x;
                var height = targetPoint.y - movingPoint.y;
                var distance = Math.sqrt(width * width + height * height);
                return moveTowardsFractional(
                    movingPoint,
                    targetPoint,
                    Math.min(1, amount / distance)
                );
            }

            function moveTowardsFractional(movingPoint, targetPoint, fraction) {
                return {
                    x: movingPoint.x + (targetPoint.x - movingPoint.x) * fraction,
                    y: movingPoint.y + (targetPoint.y - movingPoint.y) * fraction
                };
            }

            function adjustCommand(cmd, newPoint) {
                if (cmd.length > 2) {
                    cmd[cmd.length - 2] = newPoint.x;
                    cmd[cmd.length - 1] = newPoint.y;
                }
            }

            function pointForCommand(cmd) {
                return {
                    x: parseFloat(cmd[cmd.length - 2]),
                    y: parseFloat(cmd[cmd.length - 1])
                };
            }
            var pathParts = pathString.split(/[,\s]/).reduce(function(parts, part) {
                var match = part.match(/^([a-zA-Z])(.+)/);
                if (match) {
                    parts.push(match[1]);
                    parts.push(match[2]);
                } else {
                    parts.push(part);
                }
                return parts;
            }, []);
            var commands = pathParts.reduce(function(commands2, part) {
                if (parseFloat(part) == part && commands2.length) {
                    commands2[commands2.length - 1].push(part);
                } else {
                    commands2.push([part]);
                }
                return commands2;
            }, []);
            var resultCommands = [];
            if (commands.length > 1) {
                var startPoint = pointForCommand(commands[0]);
                var virtualCloseLine = null;
                if (commands[commands.length - 1][0] == "Z" && commands[0].length > 2) {
                    virtualCloseLine = ["L", startPoint.x, startPoint.y];
                    commands[commands.length - 1] = virtualCloseLine;
                }
                resultCommands.push(commands[0]);
                for (var cmdIndex = 1; cmdIndex < commands.length; cmdIndex++) {
                    var prevCmd = resultCommands[resultCommands.length - 1];
                    var curCmd = commands[cmdIndex];
                    var nextCmd = curCmd == virtualCloseLine ? commands[1] : commands[cmdIndex + 1];
                    if (nextCmd && prevCmd && prevCmd.length > 2 && curCmd[0] == "L" && nextCmd.length > 2 && nextCmd[0] == "L") {
                        var prevPoint = pointForCommand(prevCmd);
                        var curPoint = pointForCommand(curCmd);
                        var nextPoint = pointForCommand(nextCmd);
                        var curveStart, curveEnd;
                        curveStart = moveTowardsLength(curPoint, prevPoint, radius);
                        curveEnd = moveTowardsLength(curPoint, nextPoint, radius);
                        adjustCommand(curCmd, curveStart);
                        curCmd.origPoint = curPoint;
                        resultCommands.push(curCmd);
                        var startControl = moveTowardsFractional(curveStart, curPoint, 0.5);
                        var endControl = moveTowardsFractional(curPoint, curveEnd, 0.5);
                        var curveCmd = [
                            "C",
                            startControl.x,
                            startControl.y,
                            endControl.x,
                            endControl.y,
                            curveEnd.x,
                            curveEnd.y
                        ];
                        curveCmd.origPoint = curPoint;
                        resultCommands.push(curveCmd);
                    } else {
                        resultCommands.push(curCmd);
                    }
                }
                if (virtualCloseLine) {
                    var newStartPoint = pointForCommand(
                        resultCommands[resultCommands.length - 1]
                    );
                    resultCommands.push(["Z"]);
                    adjustCommand(resultCommands[0], newStartPoint);
                }
            } else {
                resultCommands = commands;
            }
            return resultCommands.reduce(function(str, c) {
                return str + c.join(" ") + " ";
            }, "");
        }
        /**
         * @param {number} x1
         * @param {number} y1
         * @param {number} x2
         * @param {number} y2
         * @param {number | null} [strokeWidth]
         */
        drawLine(x1, y1, x2, y2, lineColor = "#a8a8a8", dashArray = 0, strokeWidth = null, strokeLineCap = "butt") {
            const w = this.w;
            const line = w.dom.Paper.line().attr({
                x1,
                y1,
                x2,
                y2,
                stroke: lineColor,
                "stroke-dasharray": dashArray,
                "stroke-width": strokeWidth,
                "stroke-linecap": strokeLineCap
            });
            return line;
        }
        /**
         * @param {number | null} [strokeWidth]
         * @param {string | null} [strokeColor]
         */
        drawRect(x1 = 0, y1 = 0, x2 = 0, y2 = 0, radius = 0, color = "#fefefe", opacity = 1, strokeWidth = null, strokeColor = null, strokeDashArray = 0) {
            const w = this.w;
            const rect = w.dom.Paper.rect();
            rect.attr({
                x: x1,
                y: y1,
                width: x2 > 0 ? x2 : 0,
                height: y2 > 0 ? y2 : 0,
                rx: radius,
                ry: radius,
                opacity,
                "stroke-width": strokeWidth !== null ? strokeWidth : 0,
                stroke: strokeColor !== null ? strokeColor : "none",
                "stroke-dasharray": strokeDashArray
            });
            rect.node.setAttribute("fill", color);
            return rect;
        }
        /**
         * @param {string} polygonString
         */
        drawPolygon(polygonString, stroke = "#e1e1e1", strokeWidth = 1, fill = "none") {
            const w = this.w;
            const polygon = w.dom.Paper.polygon(polygonString).attr({
                fill,
                stroke,
                "stroke-width": strokeWidth
            });
            return polygon;
        }
        /**
         * @param {number} radius
         * @param {Record<string, any> | null} attrs
         */
        drawCircle(radius, attrs = null) {
            const w = this.w;
            if (radius < 0) radius = 0;
            const c = w.dom.Paper.circle(radius * 2);
            if (attrs !== null) {
                c.attr(attrs);
            }
            return c;
        }
        /** @param {{ d?: string, stroke?: string, strokeWidth?: number, fill: any, fillOpacity?: number, strokeOpacity?: number, classes?: any, strokeLinecap?: any, strokeDashArray?: number }} opts */
        drawPath({
            d = "",
            stroke = "#a8a8a8",
            strokeWidth = 1,
            fill,
            fillOpacity = 1,
            strokeOpacity = 1,
            classes,
            strokeLinecap = null,
            strokeDashArray = 0
        }) {
            const w = this.w;
            if (strokeLinecap === null) {
                strokeLinecap = w.config.stroke.lineCap;
            }
            if (d.indexOf("undefined") > -1 || d.indexOf("NaN") > -1) {
                d = `M 0 ${w.layout.gridHeight}`;
            }
            const p = w.dom.Paper.path(d).attr({
                fill,
                "fill-opacity": fillOpacity,
                stroke,
                "stroke-opacity": strokeOpacity,
                "stroke-linecap": strokeLinecap,
                "stroke-width": strokeWidth,
                "stroke-dasharray": strokeDashArray,
                class: classes
            });
            return p;
        }
        /**
         * @param {Record<string, any> | null} attrs
         */
        group(attrs = null) {
            const w = this.w;
            const g = w.dom.Paper.group();
            if (attrs !== null) {
                g.attr(attrs);
            }
            return g;
        }
        /**
         * @param {number} x
         * @param {number} y
         */
        move(x, y) {
            const move = ["M", x, y].join(" ");
            return move;
        }
        /**
         * @param {number | null} x
         * @param {number | null} y
         * @param {string | null} hORv
         * @returns {string}
         */
        line(x, y, hORv = null) {
            if (hORv === "H") return [" H", x].join(" ");
            if (hORv === "V") return [" V", y].join(" ");
            return [" L", x, y].join(" ");
        }
        /**
         * @param {number} x1
         * @param {number} y1
         * @param {number} x2
         * @param {number} y2
         * @param {number} x
         * @param {number} y
         */
        curve(x1, y1, x2, y2, x, y) {
            const curve = ["C", x1, y1, x2, y2, x, y].join(" ");
            return curve;
        }
        /**
         * @param {number} x1
         * @param {number} y1
         * @param {number} x
         * @param {number} y
         */
        quadraticCurve(x1, y1, x, y) {
            const curve = ["Q", x1, y1, x, y].join(" ");
            return curve;
        }
        /**
         * @param {number} rx
         * @param {number} ry
         * @param {number} axisRotation
         * @param {number} largeArcFlag
         * @param {number} sweepFlag
         * @param {number} x
         * @param {number} y
         */
        arc(rx, ry, axisRotation, largeArcFlag, sweepFlag, x, y, relative = false) {
            let coord = "A";
            if (relative) coord = "a";
            const arc = [
                coord,
                rx,
                ry,
                axisRotation,
                largeArcFlag,
                sweepFlag,
                x,
                y
            ].join(" ");
            return arc;
        }
        /**
         * @memberof Graphics
         * @param {Record<string, any>} opts
         *  i = series's index
         *  realIndex = realIndex is series's actual index when it was drawn time. After several redraws, the iterating "i" may change in loops, but realIndex doesn't
         *  pathFrom = existing pathFrom to animateTo
         *  pathTo = new Path to which d attr will be animated from pathFrom to pathTo
         *  stroke = line Color
         *  strokeWidth = width of path Line
         *  fill = it can be gradient, single color, pattern or image
         *  animationDelay = how much to delay when starting animation (in milliseconds)
         *  dataChangeSpeed = for dynamic animations, when data changes
         *  className = class attribute to add
         * @return {any} svg.js path object
         **/
        renderPaths({
            j,
            realIndex,
            pathFrom,
            pathTo,
            stroke,
            strokeWidth,
            strokeLinecap,
            fill,
            animationDelay,
            initialSpeed,
            dataChangeSpeed,
            className,
            chartType,
            shouldClipToGrid = true,
            bindEventsOnPaths = true,
            drawShadow = true,
            drawMask = null
        }) {
            var _a;
            const w = this.w;
            const filters = new Filters(this.w);
            const anim = new Animations(this.w, (_a = this.ctx) != null ? _a : void 0);
            const initialAnim = this.w.config.chart.animations.enabled;
            const dynamicAnim = initialAnim && this.w.config.chart.animations.dynamicAnimation.enabled;
            if (pathFrom && pathFrom.startsWith("M 0 0 ") && pathTo) {
                const moveCommand = pathTo.match(/^M\s+[\d.-]+\s+[\d.-]+/);
                if (moveCommand) {
                    pathFrom = pathFrom.replace(/^M\s+0\s+0/, moveCommand[0]);
                }
            }
            let d;
            const shouldAnimate = !!(initialAnim && !w.globals.resized || dynamicAnim && w.globals.dataChanged && w.globals.shouldAnimate);
            const isDrawableSeries = typeof className === "string" && (className.indexOf("apexcharts-line") > -1 || className.indexOf("apexcharts-area") > -1 || className.indexOf("apexcharts-rangeArea") > -1 || className.indexOf("apexcharts-radar") > -1);
            const useDrawMode = !!(initialAnim && !w.globals.resized && !w.globals.dataChanged && isDrawableSeries);
            if (shouldAnimate && !useDrawMode) {
                d = pathFrom;
            } else {
                d = pathTo;
                if (!shouldAnimate) {
                    w.globals.animationEnded = true;
                }
            }
            const strokeDashArrayOpt = w.config.stroke.dashArray;
            let strokeDashArray = 0;
            if (Array.isArray(strokeDashArrayOpt)) {
                strokeDashArray = strokeDashArrayOpt[realIndex];
            } else {
                strokeDashArray = w.config.stroke.dashArray;
            }
            const el = this.drawPath({
                d,
                stroke,
                strokeWidth,
                fill,
                fillOpacity: 1,
                classes: className,
                strokeLinecap,
                strokeDashArray
            });
            el.attr("index", realIndex);
            if (shouldClipToGrid) {
                if (chartType === "bar" && !w.globals.isBarHorizontal || w.globals.comboCharts) {
                    el.attr({
                        "clip-path": `url(#gridRectBarMask${w.globals.cuid})`
                    });
                } else {
                    el.attr({
                        "clip-path": `url(#gridRectMask${w.globals.cuid})`
                    });
                }
            }
            if (w.config.chart.dropShadow.enabled && drawShadow) {
                filters.dropShadow(el, w.config.chart.dropShadow, realIndex);
            }
            if (bindEventsOnPaths) {
                el.node.addEventListener("mouseenter", this.pathMouseEnter.bind(this, el));
                el.node.addEventListener("mouseleave", this.pathMouseLeave.bind(this, el));
                el.node.addEventListener("mousedown", this.pathMouseDown.bind(this, el));
            }
            el.attr({
                pathTo,
                pathFrom
            });
            const defaultAnimateOpts = {
                el,
                j,
                realIndex,
                pathFrom,
                pathTo,
                fill,
                strokeWidth,
                delay: animationDelay
            };
            if (initialAnim && !w.globals.resized && !w.globals.dataChanged) {
                if (useDrawMode) {
                    const drawSpeed = initialSpeed * 2;
                    const isFill = stroke === "none" || strokeWidth === 0;
                    const seriesCount = w.seriesData.series.length;
                    const isLast = w.globals.comboCharts ? true : realIndex === seriesCount - 1;
                    anim.animateDraw(el, {
                        realIndex,
                        j,
                        isFill,
                        isLast,
                        speed: drawSpeed,
                        delay: 0,
                        mask: drawMask
                    });
                } else {
                    anim.animatePathsGradually(__spreadProps(__spreadValues({}, defaultAnimateOpts), {
                        speed: initialSpeed
                    }));
                }
            } else {
                if (w.globals.resized || !w.globals.dataChanged) {
                    anim.showDelayedElements();
                }
            }
            if (w.globals.dataChanged && dynamicAnim && shouldAnimate) {
                anim.animatePathsGradually(__spreadProps(__spreadValues({}, defaultAnimateOpts), {
                    speed: dataChangeSpeed
                }));
            }
            return el;
        }
        /**
         * @param {string} style
         * @param {number} width
         * @param {number} height
         */
        drawPattern(style, width, height, stroke = "#a8a8a8", strokeWidth = 0) {
            const w = this.w;
            const p = w.dom.Paper.pattern(width, height, (add) => {
                if (style === "horizontalLines") {
                    add.line(0, 0, height, 0).stroke({
                        color: stroke,
                        width: strokeWidth + 1
                    });
                } else if (style === "verticalLines") {
                    add.line(0, 0, 0, width).stroke({
                        color: stroke,
                        width: strokeWidth + 1
                    });
                } else if (style === "slantedLines") {
                    add.line(0, 0, width, height).stroke({
                        color: stroke,
                        width: strokeWidth
                    });
                } else if (style === "squares") {
                    add.rect(width, height).fill("none").stroke({
                        color: stroke,
                        width: strokeWidth
                    });
                } else if (style === "circles") {
                    add.circle(width).fill("none").stroke({
                        color: stroke,
                        width: strokeWidth
                    });
                }
            });
            return p;
        }
        /**
         * @param {string} style
         * @param {string} gfrom
         * @param {string} gto
         * @param {number} opacityFrom
         * @param {number} opacityTo
         * @param {number | null} [size]
         * @param {number[] | null} stops
         * @param {any[]} colorStops
         */
        drawGradient(style, gfrom, gto, opacityFrom, opacityTo, size = null, stops = null, colorStops = [], i = 0) {
            const w = this.w;
            let g;
            if (gfrom.length < 9 && gfrom.indexOf("#") === 0) {
                gfrom = Utils$1.hexToRgba(gfrom, opacityFrom);
            }
            if (gto.length < 9 && gto.indexOf("#") === 0) {
                gto = Utils$1.hexToRgba(gto, opacityTo);
            }
            let stop1 = 0;
            let stop2 = 1;
            let stop3 = 1;
            let stop4 = null;
            if (stops !== null) {
                stop1 = typeof stops[0] !== "undefined" ? stops[0] / 100 : 0;
                stop2 = typeof stops[1] !== "undefined" ? stops[1] / 100 : 1;
                stop3 = typeof stops[2] !== "undefined" ? stops[2] / 100 : 1;
                stop4 = typeof stops[3] !== "undefined" ? stops[3] / 100 : null;
            }
            const radial = !!(w.config.chart.type === "donut" || w.config.chart.type === "pie" || w.config.chart.type === "polarArea" || w.config.chart.type === "bubble");
            if (!colorStops || colorStops.length === 0) {
                g = w.dom.Paper.gradient(
                    radial ? "radial" : "linear",
                    (add) => {
                        add.stop(stop1, gfrom, opacityFrom);
                        add.stop(stop2, gto, opacityTo);
                        add.stop(stop3, gto, opacityTo);
                        if (stop4 !== null) {
                            add.stop(stop4, gfrom, opacityFrom);
                        }
                    }
                );
            } else {
                g = w.dom.Paper.gradient(
                    radial ? "radial" : "linear",
                    (add) => {
                        const gradientStops = Array.isArray(colorStops[i]) ? colorStops[i] : colorStops;
                        gradientStops.forEach((s) => {
                            add.stop(s.offset / 100, s.color, s.opacity);
                        });
                    }
                );
            }
            if (!radial) {
                if (style === "vertical") {
                    g.from(0, 0).to(0, 1);
                } else if (style === "diagonal") {
                    g.from(0, 0).to(1, 1);
                } else if (style === "horizontal") {
                    g.from(0, 1).to(1, 1);
                } else if (style === "diagonal2") {
                    g.from(1, 0).to(0, 1);
                }
            } else {
                const offx = w.layout.gridWidth / 2;
                const offy = w.layout.gridHeight / 2;
                if (w.config.chart.type !== "bubble") {
                    g.attr({
                        gradientUnits: "userSpaceOnUse",
                        cx: offx,
                        cy: offy,
                        r: size
                    });
                } else {
                    g.attr({
                        cx: 0.5,
                        cy: 0.5,
                        r: 0.8,
                        fx: 0.2,
                        fy: 0.2
                    });
                }
            }
            return g;
        }
        /** @param {{ text: any, maxWidth: any, fontSize: any, fontFamily?: any }} opts */
        getTextBasedOnMaxWidth({
            text,
            maxWidth,
            fontSize,
            fontFamily
        }) {
            const tRects = this.getTextRects(text, fontSize, fontFamily, "");
            const wordWidth = tRects.width / text.length;
            const wordsBasedOnWidth = Math.floor(maxWidth / wordWidth);
            if (maxWidth < tRects.width) {
                return text.slice(0, wordsBasedOnWidth - 3) + "...";
            }
            return text;
        }
        /**
         * @param {{ x: any, y: any, text: any, textAnchor?: any, fontSize?: any, fontFamily?: any, fontWeight?: any, foreColor?: any, opacity?: any, maxWidth?: any, cssClass?: string, isPlainText?: boolean, dominantBaseline?: string }} opts
         */
        drawText({
            x,
            y,
            text,
            textAnchor,
            fontSize,
            fontFamily,
            fontWeight,
            foreColor,
            opacity,
            maxWidth,
            cssClass = "",
            isPlainText = true,
            dominantBaseline = "auto"
        }) {
            const w = this.w;
            if (typeof text === "undefined") text = "";
            let truncatedText = text;
            if (!textAnchor) {
                textAnchor = "start";
            }
            if (!foreColor || !foreColor.length) {
                foreColor = w.config.chart.foreColor;
            }
            fontFamily = fontFamily || w.config.chart.fontFamily;
            fontSize = fontSize || "11px";
            fontWeight = fontWeight || "regular";
            const commonProps = {
                maxWidth,
                fontSize,
                fontFamily
            };
            let elText;
            if (Array.isArray(text)) {
                elText = w.dom.Paper.text((add) => {
                    for (let i = 0; i < text.length; i++) {
                        truncatedText = text[i];
                        if (maxWidth) {
                            truncatedText = this.getTextBasedOnMaxWidth(__spreadValues({
                                text: text[i]
                            }, commonProps));
                        }
                        i === 0 ? add.tspan(truncatedText) : add.tspan(truncatedText).newLine();
                    }
                });
            } else {
                if (maxWidth) {
                    truncatedText = this.getTextBasedOnMaxWidth(__spreadValues({
                        text
                    }, commonProps));
                }
                elText = isPlainText ? w.dom.Paper.plain(text) : (
                    /**
                     * @param {any} add
                     */
                    w.dom.Paper.text((add) => add.tspan(truncatedText))
                );
            }
            elText.attr({
                x,
                y,
                "text-anchor": textAnchor,
                "dominant-baseline": dominantBaseline,
                "font-size": fontSize,
                "font-family": fontFamily,
                "font-weight": fontWeight,
                fill: foreColor,
                class: "apexcharts-text " + cssClass
            });
            elText.node.style.fontFamily = fontFamily;
            elText.node.style.opacity = opacity;
            return elText;
        }
        /**
         * @param {number} x
         * @param {number} y
         * @param {string} type
         * @param {number} size
         */
        getMarkerPath(x, y, type, size) {
            let d = "";
            switch (type) {
                case "cross":
                    size = size / 1.4;
                    d = `M ${x - size} ${y - size} L ${x + size} ${y + size}  M ${x - size} ${y + size} L ${x + size} ${y - size}`;
                    break;
                case "plus":
                    size = size / 1.12;
                    d = `M ${x - size} ${y} L ${x + size} ${y}  M ${x} ${y - size} L ${x} ${y + size}`;
                    break;
                case "star":
                case "sparkle": {
                    let points = 5;
                    size = size * 1.15;
                    if (type === "sparkle") {
                        size = size / 1.1;
                        points = 4;
                    }
                    const step = Math.PI / points;
                    for (let i = 0; i <= 2 * points; i++) {
                        const angle = i * step;
                        const radius = i % 2 === 0 ? size : size / 2;
                        const xPos = x + radius * Math.sin(angle);
                        const yPos = y - radius * Math.cos(angle);
                        d += (i === 0 ? "M" : "L") + xPos + "," + yPos;
                    }
                    d += "Z";
                    break;
                }
                case "triangle":
                    d = `M ${x} ${y - size} 
             L ${x + size} ${y + size} 
             L ${x - size} ${y + size} 
             Z`;
                    break;
                case "square":
                case "rect":
                    size = size / 1.125;
                    d = `M ${x - size} ${y - size} 
           L ${x + size} ${y - size} 
           L ${x + size} ${y + size} 
           L ${x - size} ${y + size} 
           Z`;
                    break;
                case "diamond":
                    size = size * 1.05;
                    d = `M ${x} ${y - size} 
             L ${x + size} ${y} 
             L ${x} ${y + size} 
             L ${x - size} ${y} 
            Z`;
                    break;
                case "line":
                    size = size / 1.1;
                    d = `M ${x - size} ${y} 
           L ${x + size} ${y}`;
                    break;
                case "circle":
                default:
                    size = size * 2;
                    d = `M ${x}, ${y} 
           m -${size / 2}, 0 
           a ${size / 2},${size / 2} 0 1,0 ${size},0 
           a ${size / 2},${size / 2} 0 1,0 -${size},0`;
                    break;
            }
            return d;
        }
        /**
         * @param {number} x - The x-coordinate of the marker
         * @param {number} y - The y-coordinate of the marker
         * @param {string} type - Marker shape type
         * @param {number} size - The size of the marker
         * @param {Record<string, any>} opts - The options for the marker
         * @returns {any} The created marker.
         */
        drawMarkerShape(x, y, type, size, opts) {
            const path = this.drawPath({
                d: this.getMarkerPath(x, y, type, size),
                stroke: opts.pointStrokeColor,
                strokeDashArray: opts.pointStrokeDashArray,
                strokeWidth: opts.pointStrokeWidth,
                fill: opts.pointFillColor,
                fillOpacity: opts.pointFillOpacity,
                strokeOpacity: opts.pointStrokeOpacity
            });
            path.attr({
                cx: x,
                cy: y,
                shape: opts.shape,
                class: opts.class ? opts.class : ""
            });
            return path;
        }
        /**
         * @param {number} x
         * @param {number} y
         * @param {Record<string, any>} opts
         */
        drawMarker(x, y, opts) {
            x = x || 0;
            let size = opts.pSize || 0;
            if (!Utils$1.isNumber(y)) {
                size = 0;
                y = 0;
            }
            return this.drawMarkerShape(x, y, opts == null ? void 0 : opts.shape, size, __spreadValues(__spreadValues({}, opts), opts.shape === "line" || opts.shape === "plus" || opts.shape === "cross" ? {
                pointStrokeColor: opts.pointFillColor,
                pointStrokeOpacity: opts.pointFillOpacity
            } : {}));
        }
        /**
         * @param {any} path
         * @param {Event | null} [e]
         */
        pathMouseEnter(path, e) {
            var _a, _b;
            const w = this.w;
            const filters = new Filters(this.w);
            const i = parseInt((_a = path.node.getAttribute("index")) != null ? _a : "", 10);
            const j = parseInt((_b = path.node.getAttribute("j")) != null ? _b : "", 10);
            if (isNaN(i) || isNaN(j)) return;
            if (typeof w.config.chart.events.dataPointMouseEnter === "function") {
                w.config.chart.events.dataPointMouseEnter(e, this.ctx, {
                    seriesIndex: i,
                    dataPointIndex: j,
                    w
                });
            }
            Graphics._fireEvent(w, "dataPointMouseEnter", [
                e,
                this.ctx,
                {
                    seriesIndex: i,
                    dataPointIndex: j,
                    w
                }
            ]);
            if (w.config.states.active.filter.type !== "none") {
                if (path.node.getAttribute("selected") === "true") {
                    return;
                }
            }
            if (w.config.states.hover.filter.type !== "none") {
                if (!w.interact.isTouchDevice) {
                    const hoverFilter = w.config.states.hover.filter;
                    filters.applyFilter(path, i, hoverFilter.type);
                }
            }
        }
        /**
         * @param {any} path
         * @param {Event | null} [e]
         */
        pathMouseLeave(path, e) {
            var _a, _b;
            const w = this.w;
            const filters = new Filters(this.w);
            const i = parseInt((_a = path.node.getAttribute("index")) != null ? _a : "", 10);
            const j = parseInt((_b = path.node.getAttribute("j")) != null ? _b : "", 10);
            if (isNaN(i) || isNaN(j)) return;
            if (typeof w.config.chart.events.dataPointMouseLeave === "function") {
                w.config.chart.events.dataPointMouseLeave(e, this.ctx, {
                    seriesIndex: i,
                    dataPointIndex: j,
                    w
                });
            }
            Graphics._fireEvent(w, "dataPointMouseLeave", [
                e,
                this.ctx,
                {
                    seriesIndex: i,
                    dataPointIndex: j,
                    w
                }
            ]);
            if (w.config.states.active.filter.type !== "none") {
                if (path.node.getAttribute("selected") === "true") {
                    return;
                }
            }
            if (w.config.states.hover.filter.type !== "none") {
                filters.getDefaultFilter(path, i);
            }
        }
        /**
         * @param {any} path
         * @param {Event | null} e
         */
        pathMouseDown(path, e) {
            var _a, _b;
            const w = this.w;
            const filters = new Filters(this.w);
            const i = parseInt((_a = path.node.getAttribute("index")) != null ? _a : "", 10);
            const j = parseInt((_b = path.node.getAttribute("j")) != null ? _b : "", 10);
            if (isNaN(i) || isNaN(j)) return;
            let selected = "false";
            if (path.node.getAttribute("selected") === "true") {
                path.node.setAttribute("selected", "false");
                const index = w.interact.selectedDataPoints[i].indexOf(j);
                if (index > -1) {
                    w.interact.selectedDataPoints[i].splice(index, 1);
                }
            } else {
                if (!w.config.states.active.allowMultipleDataPointsSelection && w.interact.selectedDataPoints.length > 0) {
                    w.interact.selectedDataPoints = [];
                    const elPaths = w.dom.Paper.find(
                        ".apexcharts-series path:not(.apexcharts-decoration-element)"
                    );
                    const elCircles = w.dom.Paper.find(
                        ".apexcharts-series circle:not(.apexcharts-decoration-element), .apexcharts-series rect:not(.apexcharts-decoration-element)"
                    );
                    const deSelect = (els) => {
                        Array.prototype.forEach.call(els, (el) => {
                            el.node.setAttribute("selected", "false");
                            filters.getDefaultFilter(el, i);
                        });
                    };
                    deSelect(elPaths);
                    deSelect(elCircles);
                }
                path.node.setAttribute("selected", "true");
                selected = "true";
                if (typeof w.interact.selectedDataPoints[i] === "undefined") {
                    w.interact.selectedDataPoints[i] = [];
                }
                w.interact.selectedDataPoints[i].push(j);
            }
            if (selected === "true") {
                const activeFilter = w.config.states.active.filter;
                if (activeFilter !== "none") {
                    filters.applyFilter(path, i, activeFilter.type);
                } else {
                    if (w.config.states.hover.filter !== "none") {
                        if (!w.interact.isTouchDevice) {
                            const hoverFilter = w.config.states.hover.filter;
                            filters.applyFilter(path, i, hoverFilter.type);
                        }
                    }
                }
            } else {
                if (w.config.states.active.filter.type !== "none") {
                    if (w.config.states.hover.filter.type !== "none" && !w.interact.isTouchDevice) {
                        const hoverFilter = w.config.states.hover.filter;
                        filters.applyFilter(path, i, hoverFilter.type);
                    } else {
                        filters.getDefaultFilter(path, i);
                    }
                }
            }
            if (typeof w.config.chart.events.dataPointSelection === "function") {
                w.config.chart.events.dataPointSelection(e, this.ctx, {
                    selectedDataPoints: w.interact.selectedDataPoints,
                    seriesIndex: i,
                    dataPointIndex: j,
                    w
                });
            }
            if (e) {
                Graphics._fireEvent(w, "dataPointSelection", [
                    e,
                    this.ctx,
                    {
                        selectedDataPoints: w.interact.selectedDataPoints,
                        seriesIndex: i,
                        dataPointIndex: j,
                        w
                    }
                ]);
            }
        }
        /**
         * @param {any} el
         * @returns {{ x: number, y: number }}
         */
        rotateAroundCenter(el) {
            let coord = (
                /** @type {any} */
                {}
            );
            if (el && typeof el.getBBox === "function") {
                coord = el.getBBox();
            }
            const x = coord.x + coord.width / 2;
            const y = coord.y + coord.height / 2;
            return {
                x,
                y
            };
        }
        /**
         * Sets up event delegation on a parent group element.
         * Uses mouseover/mouseout (which bubble) to simulate mouseenter/mouseleave
         * on matching child elements, reducing per-element listener overhead.
         * @param {any} parentGroup
         * @param {string} targetSelector
         */
        setupEventDelegation(parentGroup, targetSelector) {
            let currentHovered = null;
            parentGroup.node.addEventListener("mouseover", (e) => {
                const targetNode = Graphics._findDelegateTarget(
                    e.target,
                    parentGroup.node,
                    targetSelector
                );
                if (!targetNode || targetNode === currentHovered) return;
                if (currentHovered && /** @type {any} */
                    currentHovered.instance) {
                    this.pathMouseLeave(
                        /** @type {any} */
                        currentHovered.instance,
                        e
                    );
                }
                currentHovered = targetNode;
                if (targetNode.instance) {
                    this.pathMouseEnter(targetNode.instance, e);
                }
            });
            parentGroup.node.addEventListener("mouseout", (e) => {
                if (!currentHovered) return;
                const relatedNode = e.relatedTarget ? Graphics._findDelegateTarget(
                    e.relatedTarget,
                    parentGroup.node,
                    targetSelector
                ) : null;
                if (relatedNode !== currentHovered) {
                    if (currentHovered && /** @type {any} */
                        currentHovered.instance) {
                        this.pathMouseLeave(
                            /** @type {any} */
                            currentHovered.instance,
                            e
                        );
                    }
                    currentHovered = null;
                }
            });
            parentGroup.node.addEventListener("mousedown", (e) => {
                const targetNode = Graphics._findDelegateTarget(
                    e.target,
                    parentGroup.node,
                    targetSelector
                );
                if (targetNode && targetNode.instance) {
                    this.pathMouseDown(targetNode.instance, e);
                }
            });
        }
        // Fire a named event from w.globals.events without requiring a ctx reference.
        // Mirrors Events.fireEvent() but reads the registry directly from w so that
        // pathMouseEnter/Leave/Down work even when this.ctx is null (Graphics instances
        // created without a ctx arg for drawing-only use cases).
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {string} name
         * @param {any[]} args
         */
        static _fireEvent(w, name2, args) {
            const evs = w.globals.events;
            if (!evs || !Object.prototype.hasOwnProperty.call(evs, name2)) return;
            const handlers = (
                /** @type {Record<string,any>} */
                evs[name2]
            );
            for (let i = 0; i < handlers.length; i++) {
                handlers[i].apply(null, args);
            }
        }
        /**
         * @param {any} node
         * @param {Record<string, any>} boundary
         * @param {string} selector
         */
        static _findDelegateTarget(node, boundary, selector) {
            while (node && node !== boundary && node !== document) {
                if (node.matches && node.matches(selector)) return node;
                node = node.parentNode;
            }
            return null;
        }
        /**
         * @param {any} el
         * @param {Record<string, any>} attrs
         */
        static setAttrs(el, attrs) {
            for (const key in attrs) {
                if (Object.prototype.hasOwnProperty.call(attrs, key)) {
                    el.setAttribute(key, attrs[key]);
                }
            }
        }
        /**
         * @param {string} text
         * @param {string} fontSize
         * @param {string | null | undefined} [fontFamily]
         * @param {string} [transform]
         * @returns {{ width: number, height: number }}
         */
        getTextRects(text, fontSize, fontFamily, transform, useBBox = true) {
            const w = this.w;
            const cacheKey = [text, fontSize, fontFamily, transform, useBBox].join("\0");
            const cache = w.globals.textRectsCache;
            if (cache && cache.has(cacheKey)) {
                return (
                    /** @type {{ width: number, height: number }} */
                    cache.get(cacheKey)
                );
            }
            const virtualText = this.drawText({
                x: -200,
                y: -200,
                text,
                textAnchor: "start",
                fontSize,
                fontFamily,
                foreColor: "#fff",
                opacity: 0
            });
            if (transform) {
                virtualText.attr("transform", transform);
            }
            w.dom.Paper.add(virtualText);
            let rect = virtualText.bbox();
            const bboxY = rect.y;
            if (!useBBox) {
                rect = virtualText.node.getBoundingClientRect();
            }
            virtualText.remove();
            const result = {
                width: rect.width,
                height: rect.height,
                // Offset from the text element's `y` (alphabetic baseline) to the
                // bbox vertical center. For most fonts this is NEGATIVE (bbox center
                // sits above the baseline because the ascender is taller than the
                // descender). Use as: `text_y = desired_visual_center_y - centerOffset`.
                // Only populated when useBBox=true (the default).
                centerOffset: useBBox ? bboxY + rect.height / 2 - -200 : 0
            };
            if (cache) {
                cache.set(cacheKey, result);
            }
            return result;
        }
        /**
         * append ... to long text
         * http://stackoverflow.com/questions/9241315/trimming-text-to-a-given-pixel-width-in-svg
         * @memberof Graphics
         * @param {Record<string, any>} textObj
         * @param {string} textString
         * @param {number} width
         **/
        placeTextWithEllipsis(textObj, textString, width) {
            if (typeof textObj.getComputedTextLength !== "function") return;
            textObj.textContent = textString;
            if (textString.length > 0) {
                if (textObj.getComputedTextLength() >= width / 1.1) {
                    for (let x = textString.length - 3; x > 0; x -= 3) {
                        if (textObj.getSubStringLength(0, x) <= width / 1.1) {
                            textObj.textContent = textString.substring(0, x) + "...";
                            return;
                        }
                    }
                    textObj.textContent = ".";
                }
            }
        }
    }
    const SVGNS = "http://www.w3.org/2000/svg";
    class Point {
        /**
         * @param {number|{x:number,y:number}} x
         * @param {number} [y]
         */
        constructor(x, y) {
            if (typeof x === "object") {
                this.x = x.x;
                this.y = x.y;
            } else {
                this.x = x || 0;
                this.y = y || 0;
            }
        }
        /**
         * @param {Matrix} matrix
         */
        transform(matrix) {
            return matrix.apply(this);
        }
        clone() {
            return new Point(this.x, this.y);
        }
    }
    class Matrix {
        /**
         * Defaults to the identity matrix when called with no args.
         * @param {number} [a]
         * @param {number} [b]
         * @param {number} [c]
         * @param {number} [d]
         * @param {number} [e]
         * @param {number} [f]
         */
        constructor(a, b, c, d, e, f) {
            this.a = a != null ? a : 1;
            this.b = b != null ? b : 0;
            this.c = c != null ? c : 0;
            this.d = d != null ? d : 1;
            this.e = e != null ? e : 0;
            this.f = f != null ? f : 0;
        }
        /**
         * @param {number} deg
         */
        rotate(deg) {
            const rad = deg * Math.PI / 180;
            const cos = Math.cos(rad);
            const sin = Math.sin(rad);
            return this.multiply(new Matrix(cos, sin, -sin, cos, 0, 0));
        }
        /**
         * @param {number} sx
         * @param {number} sy
         */
        scale(sx, sy) {
            return this.multiply(new Matrix(sx, 0, 0, sy != null ? sy : sx, 0, 0));
        }
        /**
         * @param {Matrix} m
         */
        multiply(m) {
            return new Matrix(
                this.a * m.a + this.c * m.b,
                this.b * m.a + this.d * m.b,
                this.a * m.c + this.c * m.d,
                this.b * m.c + this.d * m.d,
                this.a * m.e + this.c * m.f + this.e,
                this.b * m.e + this.d * m.f + this.f
            );
        }
        /**
         * @param {Point} point
         */
        apply(point) {
            return new Point(
                this.a * point.x + this.c * point.y + this.e,
                this.b * point.x + this.d * point.y + this.f
            );
        }
    }
    class Box {
        /**
         * @param {number} x
         * @param {number} y
         * @param {number} w
         * @param {number} h
         */
        constructor(x, y, w, h) {
            this.x = x;
            this.y = y;
            this.w = w;
            this.h = h;
            this.width = w;
            this.height = h;
            this.x2 = x + w;
            this.y2 = y + h;
        }
    }
    class Fill {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
            this.opts = null;
            this.seriesIndex = 0;
            this.patternIDs = [];
        }
        /**
         * @param {Record<string, any>} params
         */
        clippedImgArea(params) {
            const w = this.w;
            const cnf = w.config;
            const svgW = parseInt(String(w.layout.gridWidth), 10);
            const svgH = parseInt(String(w.layout.gridHeight), 10);
            const size = svgW > svgH ? svgW : svgH;
            const fillImg = params.image;
            let imgWidth = 0;
            let imgHeight = 0;
            if (typeof params.width === "undefined" && typeof params.height === "undefined") {
                if (cnf.fill.image.width !== void 0 && cnf.fill.image.height !== void 0) {
                    imgWidth = cnf.fill.image.width + 1;
                    imgHeight = cnf.fill.image.height;
                } else {
                    imgWidth = size + 1;
                    imgHeight = size;
                }
            } else {
                imgWidth = params.width;
                imgHeight = params.height;
            }
            const elPattern = BrowserAPIs.createElementNS(SVGNS, "pattern");
            Graphics.setAttrs(elPattern, {
                id: params.patternID,
                patternUnits: params.patternUnits ? params.patternUnits : "userSpaceOnUse",
                width: imgWidth + "px",
                height: imgHeight + "px"
            });
            const elImage = BrowserAPIs.createElementNS(SVGNS, "image");
            elPattern.appendChild(elImage);
            const SVGLib = Environment.isBrowser() ? (
                /** @type {any} */
                window.SVG
            ) : (
                /** @type {any} */
                global.SVG
            );
            elImage.setAttributeNS(SVGLib.xlink, "href", fillImg);
            Graphics.setAttrs(elImage, {
                x: 0,
                y: 0,
                preserveAspectRatio: "none",
                width: imgWidth + "px",
                height: imgHeight + "px"
            });
            elImage.style.opacity = params.opacity;
            w.dom.elDefs.node.appendChild(elPattern);
        }
        /**
         * @param {Record<string, any>} opts
         */
        getSeriesIndex(opts) {
            const w = this.w;
            const cType = w.config.chart.type;
            if ((cType === "bar" || cType === "rangeBar") && w.config.plotOptions.bar.distributed || cType === "heatmap" || cType === "treemap") {
                this.seriesIndex = opts.seriesNumber;
            } else {
                this.seriesIndex = opts.seriesNumber % w.seriesData.series.length;
            }
            return this.seriesIndex;
        }
        /**
         * @param {number[]} data
         * @param {Record<string, any>} multiColorConfig
         */
        computeColorStops(data, multiColorConfig) {
            const w = this.w;
            let maxPositive = null;
            let minNegative = null;
            for (const value of data) {
                if (value >= multiColorConfig.threshold) {
                    if (maxPositive === null || value > maxPositive) {
                        maxPositive = value;
                    }
                } else {
                    if (minNegative === null || value < minNegative) {
                        minNegative = value;
                    }
                }
            }
            if (maxPositive === null) {
                maxPositive = multiColorConfig.threshold;
            }
            if (minNegative === null) {
                minNegative = multiColorConfig.threshold;
            }
            let totalRange = maxPositive - multiColorConfig.threshold + (multiColorConfig.threshold - minNegative);
            if (totalRange === 0) {
                totalRange = 1;
            }
            const negativePercentage = (multiColorConfig.threshold - minNegative) / totalRange * 100;
            let offset = 100 - negativePercentage;
            offset = Math.max(0, Math.min(offset, 100));
            return [{
                    offset,
                    color: multiColorConfig.colorAboveThreshold,
                    opacity: w.config.fill.opacity
                },
                {
                    offset: 0,
                    color: multiColorConfig.colorBelowThreshold,
                    opacity: w.config.fill.opacity
                }
            ];
        }
        /**
         * @param {Record<string, any>} opts
         */
        fillPath(opts) {
            var _a, _b, _c, _d;
            const w = this.w;
            this.opts = opts;
            const cnf = this.w.config;
            let pathFill;
            let patternFill, gradientFill;
            this.seriesIndex = this.getSeriesIndex(opts);
            const drawMultiColorLine = cnf.plotOptions.line.colors.colorAboveThreshold && cnf.plotOptions.line.colors.colorBelowThreshold;
            const fillColors = this.getFillColors();
            let fillColor = fillColors[this.seriesIndex];
            if (w.seriesData.seriesColors[this.seriesIndex] !== void 0) {
                fillColor = w.seriesData.seriesColors[this.seriesIndex];
            }
            if (typeof fillColor === "function") {
                fillColor = fillColor({
                    seriesIndex: this.seriesIndex,
                    dataPointIndex: opts.dataPointIndex,
                    value: opts.value,
                    w
                });
            }
            const fillType = opts.fillType ? opts.fillType : this.getFillType(this.seriesIndex);
            let fillOpacity = Array.isArray(cnf.fill.opacity) ? cnf.fill.opacity[this.seriesIndex] : cnf.fill.opacity;
            const useGradient = fillType === "gradient" || drawMultiColorLine;
            if (opts.color) {
                fillColor = opts.color;
            }
            const seriesItem = (
                /** @type {Record<string,any>} */
                w.config.series[this.seriesIndex]
            );
            if ((_b = (_a = seriesItem == null ? void 0 : seriesItem.data) == null ? void 0 : _a[opts.dataPointIndex]) == null ? void 0 : _b.fillColor) {
                fillColor = (_d = (_c = seriesItem == null ? void 0 : seriesItem.data) == null ? void 0 : _c[opts.dataPointIndex]) == null ? void 0 : _d.fillColor;
            }
            if (!fillColor) {
                fillColor = "#fff";
                console.warn("undefined color - ApexCharts");
            }
            if (opts.opacity !== void 0 && opts.opacity !== null) fillOpacity = opts.opacity;
            let defaultColor = fillColor;
            if (Utils$1.isCSSVariable(fillColor)) {
                defaultColor = Utils$1.applyOpacityToColor(fillColor, fillOpacity);
            } else if (fillColor.indexOf("rgb") === -1) {
                if (fillColor.indexOf("#") === -1) {
                    defaultColor = fillColor;
                } else if (fillColor.length < 9) {
                    defaultColor = Utils$1.hexToRgba(fillColor, fillOpacity);
                }
            } else {
                if (fillColor.indexOf("rgba") > -1) {
                    fillOpacity = Utils$1.getOpacityFromRGBA(fillColor);
                } else {
                    defaultColor = Utils$1.hexToRgba(Utils$1.rgb2hex(fillColor), fillOpacity);
                }
            }
            const resolvedFillColor = Utils$1.isCSSVariable(fillColor) ? Utils$1.getThemeColor(fillColor) : fillColor;
            if (fillType === "pattern") {
                patternFill = this.handlePatternFill({
                    fillConfig: opts.fillConfig,
                    patternFill,
                    fillColor: resolvedFillColor,
                    defaultColor
                });
            }
            if (useGradient) {
                const colorStops = cnf.fill.gradient.colorStops ? [...cnf.fill.gradient.colorStops] : [];
                let type = cnf.fill.gradient.type;
                if (drawMultiColorLine) {
                    colorStops[this.seriesIndex] = this.computeColorStops(
                        w.seriesData.series[this.seriesIndex],
                        cnf.plotOptions.line.colors
                    );
                    type = "vertical";
                }
                gradientFill = this.handleGradientFill({
                    type,
                    fillConfig: opts.fillConfig,
                    fillColor: resolvedFillColor,
                    fillOpacity,
                    colorStops,
                    i: this.seriesIndex
                });
            }
            if (fillType === "image") {
                const imgSrc = cnf.fill.image.src;
                const patternID = opts.patternID ? opts.patternID : "";
                const patternKey = `pattern${w.globals.cuid}${opts.seriesNumber + 1}${patternID}`;
                if (this.patternIDs.indexOf(patternKey) === -1) {
                    this.clippedImgArea({
                        opacity: fillOpacity,
                        image: Array.isArray(imgSrc) ? opts.seriesNumber < imgSrc.length ? imgSrc[opts.seriesNumber] : imgSrc[0] : imgSrc,
                        width: opts.width ? opts.width : void 0,
                        height: opts.height ? opts.height : void 0,
                        patternUnits: opts.patternUnits,
                        patternID: patternKey
                    });
                    this.patternIDs.push(patternKey);
                }
                pathFill = `url(#${patternKey})`;
            } else if (useGradient) {
                pathFill = gradientFill;
            } else if (fillType === "pattern") {
                pathFill = patternFill;
            } else {
                pathFill = defaultColor;
            }
            if (opts.solid) {
                pathFill = defaultColor;
            }
            return pathFill;
        }
        /**
         * @param {number} seriesIndex
         */
        getFillType(seriesIndex) {
            const w = this.w;
            if (Array.isArray(w.config.fill.type)) {
                return w.config.fill.type[seriesIndex];
            } else {
                return w.config.fill.type;
            }
        }
        getFillColors() {
            const w = this.w;
            const cnf = w.config;
            const opts = this.opts;
            let fillColors = [];
            if (w.globals.comboCharts) {
                if (
                    /** @type {Record<string,any>} */
                    w.config.series[this.seriesIndex].type === "line"
                ) {
                    if (Array.isArray(w.globals.stroke.colors)) {
                        fillColors = w.globals.stroke.colors;
                    } else {
                        fillColors.push(w.globals.stroke.colors);
                    }
                } else {
                    if (Array.isArray(w.globals.fill.colors)) {
                        fillColors = w.globals.fill.colors;
                    } else {
                        fillColors.push(w.globals.fill.colors);
                    }
                }
            } else {
                if (cnf.chart.type === "line") {
                    if (Array.isArray(w.globals.stroke.colors)) {
                        fillColors = w.globals.stroke.colors;
                    } else {
                        fillColors.push(w.globals.stroke.colors);
                    }
                } else {
                    if (Array.isArray(w.globals.fill.colors)) {
                        fillColors = w.globals.fill.colors;
                    } else {
                        fillColors.push(w.globals.fill.colors);
                    }
                }
            }
            if (typeof opts.fillColors !== "undefined") {
                fillColors = [];
                if (Array.isArray(opts.fillColors)) {
                    fillColors = opts.fillColors.slice();
                } else {
                    fillColors.push(opts.fillColors);
                }
            }
            return fillColors;
        }
        /** @param {{fillConfig: any, patternFill: any, fillColor: any, defaultColor: any}} opts */
        handlePatternFill({
            fillConfig,
            patternFill,
            fillColor,
            defaultColor
        }) {
            let fillCnf = this.w.config.fill;
            if (fillConfig) {
                fillCnf = fillConfig;
            }
            const opts = this.opts;
            const graphics = new Graphics(this.w);
            const patternStrokeWidth = Array.isArray(fillCnf.pattern.strokeWidth) ? fillCnf.pattern.strokeWidth[this.seriesIndex] : fillCnf.pattern.strokeWidth;
            const patternLineColor = fillColor;
            if (Array.isArray(fillCnf.pattern.style)) {
                if (typeof fillCnf.pattern.style[opts.seriesNumber] !== "undefined") {
                    const pf = graphics.drawPattern(
                        fillCnf.pattern.style[opts.seriesNumber],
                        fillCnf.pattern.width,
                        fillCnf.pattern.height,
                        patternLineColor,
                        patternStrokeWidth
                    );
                    patternFill = pf;
                } else {
                    patternFill = defaultColor;
                }
            } else {
                patternFill = graphics.drawPattern(
                    fillCnf.pattern.style,
                    fillCnf.pattern.width,
                    fillCnf.pattern.height,
                    patternLineColor,
                    patternStrokeWidth
                );
            }
            return patternFill;
        }
        handleGradientFill({
            type,
            fillColor,
            fillOpacity,
            fillConfig,
            colorStops,
            i
        }) {
            let fillCnf = this.w.config.fill;
            if (fillConfig) {
                fillCnf = __spreadValues(__spreadValues({}, fillCnf), fillConfig);
            }
            const opts = this.opts;
            const graphics = new Graphics(this.w);
            const utils = new Utils$1();
            type = type || fillCnf.gradient.type;
            let gradientFrom = fillColor;
            let gradientTo;
            let opacityFrom = fillCnf.gradient.opacityFrom === void 0 ? fillOpacity : Array.isArray(fillCnf.gradient.opacityFrom) ? fillCnf.gradient.opacityFrom[i] : fillCnf.gradient.opacityFrom;
            if (gradientFrom.indexOf("rgba") > -1) {
                opacityFrom = Utils$1.getOpacityFromRGBA(gradientFrom);
            }
            let opacityTo = fillCnf.gradient.opacityTo === void 0 ? fillOpacity : Array.isArray(fillCnf.gradient.opacityTo) ? fillCnf.gradient.opacityTo[i] : fillCnf.gradient.opacityTo;
            if (fillCnf.gradient.gradientToColors === void 0 || fillCnf.gradient.gradientToColors.length === 0) {
                if (fillCnf.gradient.shade === "dark") {
                    gradientTo = utils.shadeColor(
                        parseFloat(fillCnf.gradient.shadeIntensity) * -1,
                        fillColor.indexOf("rgb") > -1 ? Utils$1.rgb2hex(fillColor) : fillColor
                    );
                } else {
                    gradientTo = utils.shadeColor(
                        parseFloat(fillCnf.gradient.shadeIntensity),
                        fillColor.indexOf("rgb") > -1 ? Utils$1.rgb2hex(fillColor) : fillColor
                    );
                }
            } else {
                if (fillCnf.gradient.gradientToColors[opts.seriesNumber]) {
                    const gToColor = fillCnf.gradient.gradientToColors[opts.seriesNumber];
                    gradientTo = gToColor;
                    if (gToColor.indexOf("rgba") > -1) {
                        opacityTo = Utils$1.getOpacityFromRGBA(gToColor);
                    }
                } else {
                    gradientTo = fillColor;
                }
            }
            if (fillCnf.gradient.gradientFrom) {
                gradientFrom = fillCnf.gradient.gradientFrom;
            }
            if (fillCnf.gradient.gradientTo) {
                gradientTo = fillCnf.gradient.gradientTo;
            }
            if (fillCnf.gradient.inverseColors) {
                const t = gradientFrom;
                gradientFrom = gradientTo;
                gradientTo = t;
            }
            if (gradientFrom.indexOf("rgb") > -1) {
                gradientFrom = Utils$1.rgb2hex(gradientFrom);
            }
            if (gradientTo.indexOf("rgb") > -1) {
                gradientTo = Utils$1.rgb2hex(gradientTo);
            }
            return graphics.drawGradient(
                type,
                gradientFrom,
                gradientTo,
                opacityFrom,
                opacityTo,
                opts.size,
                fillCnf.gradient.stops,
                colorStops,
                i
            );
        }
    }
    class Markers {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this._filters = new Filters(this.w);
            this._graphics = new Graphics(this.w, this.ctx);
        }
        setGlobalMarkerSize() {
            const w = this.w;
            w.globals.markers.size = Array.isArray(w.config.markers.size) ? w.config.markers.size : [w.config.markers.size];
            if (w.globals.markers.size.length > 0) {
                if (w.globals.markers.size.length < w.seriesData.series.length + 1) {
                    for (let i = 0; i <= w.seriesData.series.length; i++) {
                        if (typeof w.globals.markers.size[i] === "undefined") {
                            w.globals.markers.size.push(w.globals.markers.size[0]);
                        }
                    }
                }
            } else {
                w.globals.markers.size = w.config.series.map(
                    () => (
                        /** @type {number} */
                        w.config.markers.size
                    )
                );
            }
        }
        /** @param {{ pointsPos?: any, seriesIndex?: any, j?: any, pSize?: any, alwaysDrawMarker?: boolean, isVirtualPoint?: boolean }} opts */
        plotChartMarkers({
            pointsPos,
            seriesIndex,
            j,
            pSize,
            alwaysDrawMarker = false,
            isVirtualPoint = false
        }) {
            const w = this.w;
            const i = seriesIndex;
            const p = pointsPos;
            let elMarkersWrap = null;
            const graphics = new Graphics(this.w);
            const hasDiscreteMarkers = w.config.markers.discrete && w.config.markers.discrete.length;
            if (Array.isArray(p.x)) {
                for (let q = 0; q < p.x.length; q++) {
                    let markerElement;
                    let dataPointIndex = j;
                    let invalidMarker = !Utils$1.isNumber(p.y[q]);
                    if (w.globals.markers.largestSize === 0 && w.globals.hasNullValues && w.seriesData.series[i][j + 1] !== null && !isVirtualPoint) {
                        invalidMarker = true;
                    }
                    if (j === 1 && q === 0) dataPointIndex = 0;
                    if (j === 1 && q === 1) dataPointIndex = 1;
                    let markerClasses = "apexcharts-marker";
                    if ((w.config.chart.type === "line" || w.config.chart.type === "area") && !w.globals.comboCharts && !w.config.tooltip.intersect) {
                        markerClasses += " no-pointer-events";
                    }
                    const shouldMarkerDraw = Array.isArray(w.config.markers.size) ? w.globals.markers.size[seriesIndex] > 0 : w.config.markers.size > 0;
                    if (shouldMarkerDraw || alwaysDrawMarker || hasDiscreteMarkers) {
                        if (!invalidMarker) {
                            markerClasses += ` w${Utils$1.randomId()}`;
                        }
                        const opts = this.getMarkerConfig({
                            cssClass: markerClasses,
                            seriesIndex,
                            dataPointIndex
                        });
                        const _si = (
                            /** @type {Record<string,any>} */
                            w.config.series[i]
                        );
                        if (_si.data[dataPointIndex]) {
                            if (_si.data[dataPointIndex].fillColor) {
                                opts.pointFillColor = _si.data[dataPointIndex].fillColor;
                            }
                            if (_si.data[dataPointIndex].strokeColor) {
                                opts.pointStrokeColor = _si.data[dataPointIndex].strokeColor;
                            }
                        }
                        if (typeof pSize !== "undefined") {
                            opts.pSize = pSize;
                        }
                        if (p.x[q] < -w.globals.markers.largestSize || p.x[q] > w.layout.gridWidth + w.globals.markers.largestSize || p.y[q] < -w.globals.markers.largestSize || p.y[q] > w.layout.gridHeight + w.globals.markers.largestSize) {
                            opts.pSize = 0;
                        }
                        if (!invalidMarker) {
                            const shouldCreateMarkerWrap = w.globals.markers.size[seriesIndex] > 0 || alwaysDrawMarker || hasDiscreteMarkers;
                            if (shouldCreateMarkerWrap && !elMarkersWrap) {
                                elMarkersWrap = graphics.group({
                                    class: alwaysDrawMarker || hasDiscreteMarkers ? "" : "apexcharts-series-markers"
                                });
                                elMarkersWrap.attr(
                                    "clip-path",
                                    `url(#gridRectMarkerMask${w.globals.cuid})`
                                );
                                this.setupMarkerDelegation(elMarkersWrap);
                            }
                            markerElement = graphics.drawMarker(p.x[q], p.y[q], opts);
                            markerElement.attr("rel", dataPointIndex);
                            markerElement.attr("j", dataPointIndex);
                            markerElement.attr("index", seriesIndex);
                            markerElement.node.setAttribute("default-marker-size", opts.pSize);
                            applyProgressiveReveal(markerElement, p.x[q], w);
                            this._filters.setSelectionFilter(
                                markerElement,
                                seriesIndex,
                                dataPointIndex
                            );
                            if (elMarkersWrap) {
                                elMarkersWrap.add(markerElement);
                            }
                        }
                    } else {
                        if (typeof w.globals.pointsArray[seriesIndex] === "undefined")
                            w.globals.pointsArray[seriesIndex] = [];
                        w.globals.pointsArray[seriesIndex].push([p.x[q], p.y[q]]);
                    }
                }
            }
            return elMarkersWrap;
        }
        /** @param {{cssClass: any, seriesIndex: any, dataPointIndex?: any, radius?: any, size?: any, strokeWidth?: any}} opts */
        getMarkerConfig({
            cssClass,
            seriesIndex,
            dataPointIndex = null,
            radius = null,
            size = null,
            strokeWidth = null
        }) {
            const w = this.w;
            const pStyle = this.getMarkerStyle(seriesIndex);
            let pSize = size === null ? w.globals.markers.size[seriesIndex] : size;
            const m = w.config.markers;
            if (dataPointIndex !== null && m.discrete.length) {
                m.discrete.map((marker) => {
                    if (marker.seriesIndex === seriesIndex && marker.dataPointIndex === dataPointIndex) {
                        pStyle.pointStrokeColor = marker.strokeColor;
                        pStyle.pointFillColor = marker.fillColor;
                        pSize = marker.size;
                        pStyle.pointShape = marker.shape;
                    }
                });
            }
            return {
                pSize: radius === null ? pSize : radius,
                pRadius: radius !== null ? radius : m.radius,
                pointStrokeWidth: strokeWidth !== null ? strokeWidth : Array.isArray(m.strokeWidth) ? m.strokeWidth[seriesIndex] : m.strokeWidth,
                pointStrokeColor: pStyle.pointStrokeColor,
                pointFillColor: pStyle.pointFillColor,
                shape: pStyle.pointShape || (Array.isArray(m.shape) ? m.shape[seriesIndex] : m.shape),
                class: cssClass,
                pointStrokeOpacity: Array.isArray(m.strokeOpacity) ? m.strokeOpacity[seriesIndex] : m.strokeOpacity,
                pointStrokeDashArray: Array.isArray(m.strokeDashArray) ? m.strokeDashArray[seriesIndex] : m.strokeDashArray,
                pointFillOpacity: Array.isArray(m.fillOpacity) ? m.fillOpacity[seriesIndex] : m.fillOpacity,
                seriesIndex
            };
        }
        /**
         * @param {any} parentGroup
         */
        setupMarkerDelegation(parentGroup) {
            const w = this.w;
            const selector = ".apexcharts-marker";
            this._graphics.setupEventDelegation(parentGroup, selector);
            parentGroup.node.addEventListener("click", (e) => {
                if (w.config.markers.onClick) {
                    const targetNode = Graphics._findDelegateTarget(
                        e.target,
                        parentGroup.node,
                        selector
                    );
                    if (targetNode) w.config.markers.onClick(e);
                }
            });
            parentGroup.node.addEventListener("dblclick", (e) => {
                if (w.config.markers.onDblClick) {
                    const targetNode = Graphics._findDelegateTarget(
                        e.target,
                        parentGroup.node,
                        selector
                    );
                    if (targetNode) w.config.markers.onDblClick(e);
                }
            });
            parentGroup.node.addEventListener(
                "touchstart",
                (e) => {
                    const targetNode = Graphics._findDelegateTarget(
                        e.target,
                        parentGroup.node,
                        selector
                    );
                    if (targetNode && targetNode.instance) {
                        this._graphics.pathMouseDown(targetNode.instance, e);
                    }
                }, {
                    passive: true
                }
            );
        }
        /**
         * @param {any} marker
         */
        addEvents(marker) {
            const w = this.w;
            marker.node.addEventListener(
                "mouseenter",
                this._graphics.pathMouseEnter.bind(this.ctx, marker)
            );
            marker.node.addEventListener(
                "mouseleave",
                this._graphics.pathMouseLeave.bind(this.ctx, marker)
            );
            marker.node.addEventListener(
                "mousedown",
                this._graphics.pathMouseDown.bind(this.ctx, marker)
            );
            marker.node.addEventListener("click", w.config.markers.onClick);
            marker.node.addEventListener("dblclick", w.config.markers.onDblClick);
            marker.node.addEventListener(
                "touchstart",
                this._graphics.pathMouseDown.bind(this.ctx, marker), {
                    passive: true
                }
            );
        }
        /**
         * @returns {any}
         * @param {number} seriesIndex
         */
        getMarkerStyle(seriesIndex) {
            const w = this.w;
            const colors = w.globals.markers.colors;
            const strokeColors = w.config.markers.strokeColor || w.config.markers.strokeColors;
            const pointStrokeColor = Array.isArray(strokeColors) ? strokeColors[seriesIndex] : strokeColors;
            const pointFillColor = Array.isArray(colors) ? colors[seriesIndex] : colors;
            return {
                pointStrokeColor,
                pointFillColor
            };
        }
    }
    class Scatter {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.ctx = ctx;
            this.w = w;
            this.initialAnim = this.w.config.chart.animations.enabled;
            this.anim = new Animations(this.w);
            this.filters = new Filters(this.w);
            this.fill = new Fill(this.w);
            this.markers = new Markers(this.w, this.ctx);
            this.graphics = new Graphics(this.w);
        }
        /**
         * @param {Element} elSeries
         * @param {number} j
         * @param {Record<string, any>} opts
         */
        draw(elSeries, j, opts) {
            const w = this.w;
            const graphics = this.graphics;
            const realIndex = opts.realIndex;
            const pointsPos = opts.pointsPos;
            const zRatio = opts.zRatio;
            const elPointsMain = opts.elParent;
            const elPointsWrap = graphics.group({
                class: `apexcharts-series-markers apexcharts-series-${w.config.chart.type}`
            });
            elPointsWrap.attr("clip-path", `url(#gridRectMarkerMask${w.globals.cuid})`);
            this.markers.setupMarkerDelegation(elPointsWrap);
            if (Array.isArray(pointsPos.x)) {
                for (let q = 0; q < pointsPos.x.length; q++) {
                    let dataPointIndex = j + 1;
                    let shouldDraw = true;
                    if (j === 0 && q === 0) dataPointIndex = 0;
                    if (j === 0 && q === 1) dataPointIndex = 1;
                    let radius = w.globals.markers.size[realIndex];
                    if (zRatio !== Infinity) {
                        const bubble = w.config.plotOptions.bubble;
                        radius = w.seriesData.seriesZ[realIndex][dataPointIndex];
                        if (bubble.zScaling) {
                            radius /= zRatio;
                        }
                        if (bubble.minBubbleRadius && radius < bubble.minBubbleRadius) {
                            radius = bubble.minBubbleRadius;
                        }
                        if (bubble.maxBubbleRadius && radius > bubble.maxBubbleRadius) {
                            radius = bubble.maxBubbleRadius;
                        }
                    }
                    const x = pointsPos.x[q];
                    const y = pointsPos.y[q];
                    radius = radius || 0;
                    if (y === null || typeof w.seriesData.series[realIndex][dataPointIndex] === "undefined") {
                        shouldDraw = false;
                    }
                    if (shouldDraw) {
                        const point = this.drawPoint(
                            x,
                            y,
                            radius,
                            realIndex,
                            dataPointIndex,
                            j
                        );
                        elPointsWrap.add(point);
                    }
                    elPointsMain.add(elPointsWrap);
                }
            }
        }
        /**
         * @param {number} x
         * @param {number} y
         * @param {number} radius
         * @param {number} realIndex
         * @param {number} dataPointIndex
         * @param {number} j
         */
        drawPoint(x, y, radius, realIndex, dataPointIndex, j) {
            const w = this.w;
            const i = realIndex;
            const anim = this.anim;
            const filters = this.filters;
            const fill = this.fill;
            const markers = this.markers;
            const graphics = this.graphics;
            const markerConfig = markers.getMarkerConfig({
                cssClass: "apexcharts-marker",
                seriesIndex: i,
                dataPointIndex,
                radius: w.config.chart.type === "bubble" || w.globals.comboCharts && w.config.series[realIndex] && /** @type {Record<string,any>} */
                    w.config.series[realIndex].type === "bubble" ? radius : null
            });
            let pathFillCircle = fill.fillPath({
                seriesNumber: realIndex,
                dataPointIndex,
                color: markerConfig.pointFillColor,
                patternUnits: "objectBoundingBox",
                value: w.seriesData.series[realIndex][j]
            });
            const el = graphics.drawMarker(x, y, markerConfig);
            const _si = (
                /** @type {Record<string,any>} */
                w.config.series[i]
            );
            if (_si.data[dataPointIndex]) {
                if (_si.data[dataPointIndex].fillColor) {
                    pathFillCircle = _si.data[dataPointIndex].fillColor;
                }
            }
            el.attr({
                fill: pathFillCircle
            });
            if (w.config.chart.dropShadow.enabled) {
                const dropShadow = w.config.chart.dropShadow;
                filters.dropShadow(el, dropShadow, realIndex);
            }
            if (this.initialAnim && !w.globals.dataChanged && !w.globals.resized) {
                const animCfg = w.config.chart.animations;
                const popSpeed = animCfg.speed;
                const totalPoints = w.globals.dataPoints || 1;
                const gradCfg = animCfg.animateGradually;
                const gradEnabled = gradCfg && gradCfg.enabled !== false;
                const baseDelay = gradEnabled ? Math.min(20, popSpeed * 0.5 / Math.max(1, totalPoints)) : 0;
                const delay = computeStagger({
                    style: baseDelay > 0 ? "sequential" : "none",
                    index: dataPointIndex,
                    baseDelay
                });
                anim.animatePop(el, {
                    speed: popSpeed,
                    delay,
                    onComplete: () => anim.animationCompleted(el)
                });
            } else {
                w.globals.animationEnded = true;
            }
            el.attr({
                rel: dataPointIndex,
                j: dataPointIndex,
                index: realIndex,
                "default-marker-size": markerConfig.pSize
            });
            filters.setSelectionFilter(el, realIndex, dataPointIndex);
            el.node.classList.add("apexcharts-marker");
            return el;
        }
        /**
         * @param {number} y
         */
        centerTextInBubble(y) {
            const w = this.w;
            y = y + parseInt(w.config.dataLabels.style.fontSize, 10) / 4;
            return {
                y
            };
        }
    }
    class DataLabels {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext | null} ctx
         */
        constructor(w, ctx = null) {
            this.w = w;
            this.ctx = ctx;
        }
        // When there are many datalabels to be printed, and some of them overlaps each other in the same series, this method will take care of that
        // Also, when datalabels exceeds the drawable area and get clipped off, we need to adjust and move some pixels to make them visible again
        /**
         * @param {number} x
         * @param {number} y
         * @param {any} val
         * @param {number} i
         * @param {number} dataPointIndex
         * @param {boolean} alwaysDrawDataLabel
         * @param {string} fontSize
         */
        dataLabelsCorrection(x, y, val, i, dataPointIndex, alwaysDrawDataLabel, fontSize) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            let drawnextLabel = false;
            const textRects = (
                /** @type {any} */
                graphics.getTextRects(val, fontSize)
            );
            const width = textRects.width;
            const height = textRects.height;
            if (y < 0) y = 0;
            if (y > w.layout.gridHeight + height) y = w.layout.gridHeight + height / 2;
            if (typeof /** @type {any} */ w.globals.dataLabelsRects[i] === "undefined") {
                w.globals.dataLabelsRects[i] = [];
            }
            w.globals.dataLabelsRects[i].push({
                x,
                y,
                width,
                height
            });
            const len = (
                /** @type {any} */
                w.globals.dataLabelsRects[i].length - 2
            );
            const lastDrawnIndex = typeof w.globals.lastDrawnDataLabelsIndexes[i] !== "undefined" ? w.globals.lastDrawnDataLabelsIndexes[i][w.globals.lastDrawnDataLabelsIndexes[i].length - 1] : 0;
            if (typeof /** @type {any} */ w.globals.dataLabelsRects[i][len] !== "undefined") {
                const lastDataLabelRect = (
                    /** @type {any} */
                    w.globals.dataLabelsRects[i][lastDrawnIndex]
                );
                if (
                    // next label forward and x not intersecting
                    x > lastDataLabelRect.x + lastDataLabelRect.width || y > lastDataLabelRect.y + lastDataLabelRect.height || y + height < lastDataLabelRect.y || x + width < lastDataLabelRect.x
                ) {
                    drawnextLabel = true;
                }
            }
            if (dataPointIndex === 0 || alwaysDrawDataLabel) {
                drawnextLabel = true;
            }
            return {
                x,
                y,
                textRects,
                drawnextLabel
            };
        }
        /** @param {{type: any, pos: any, i: any, j: any, isRangeStart: any, strokeWidth?: any}} opts */
        drawDataLabel({
            type,
            pos,
            i,
            j,
            isRangeStart,
            strokeWidth = 2
        }) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const dataLabelsConfig = w.config.dataLabels;
            let x = 0;
            let y = 0;
            let dataPointIndex = j;
            let elDataLabelsWrap = null;
            const seriesCollapsed = w.globals.collapsedSeriesIndices.indexOf(i) !== -1;
            if (seriesCollapsed || !dataLabelsConfig.enabled || !Array.isArray(pos.x)) {
                return elDataLabelsWrap;
            }
            elDataLabelsWrap = graphics.group({
                class: "apexcharts-data-labels"
            });
            for (let q = 0; q < pos.x.length; q++) {
                x = pos.x[q] + dataLabelsConfig.offsetX;
                y = pos.y[q] + dataLabelsConfig.offsetY + strokeWidth;
                if (!isNaN(x)) {
                    if (j === 1 && q === 0) dataPointIndex = 0;
                    if (j === 1 && q === 1) dataPointIndex = 1;
                    let val = w.seriesData.series[i][dataPointIndex];
                    if (type === "rangeArea") {
                        if (isRangeStart) {
                            val = w.rangeData.seriesRangeStart[i][dataPointIndex];
                        } else {
                            val = w.rangeData.seriesRangeEnd[i][dataPointIndex];
                        }
                    }
                    let text = "";
                    const getText = (v) => {
                        return w.config.dataLabels.formatter(v, {
                            seriesIndex: i,
                            dataPointIndex,
                            w
                        });
                    };
                    if (w.config.chart.type === "bubble") {
                        val = w.seriesData.seriesZ[i][dataPointIndex];
                        text = getText(val);
                        y = pos.y[q];
                        const scatter = new Scatter(
                            this.w,
                            /** @type {import('../types/internal').ChartContext} */
                            this.ctx
                        );
                        const centerTextInBubbleCoords = scatter.centerTextInBubble(y);
                        y = centerTextInBubbleCoords.y;
                    } else {
                        if (typeof val !== "undefined") {
                            text = getText(val);
                        }
                    }
                    let textAnchor = w.config.dataLabels.textAnchor;
                    if (w.globals.isSlopeChart) {
                        if (dataPointIndex === 0) {
                            textAnchor = "end";
                        } else if (dataPointIndex === /** @type {Record<string,any>} */
                            w.config.series[i].data.length - 1) {
                            textAnchor = "start";
                        } else {
                            textAnchor = "middle";
                        }
                    }
                    this.plotDataLabelsText({
                        x,
                        y,
                        text,
                        i,
                        j: dataPointIndex,
                        parent: elDataLabelsWrap,
                        offsetCorrection: true,
                        dataLabelsConfig: w.config.dataLabels,
                        textAnchor
                    });
                }
            }
            return elDataLabelsWrap;
        }
        /**
         * @param {Record<string, any>} opts
         */
        plotDataLabelsText(opts) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            let {
                x,
                y,
                i,
                j,
                text,
                textAnchor,
                fontSize,
                parent,
                dataLabelsConfig,
                color,
                alwaysDrawDataLabel,
                offsetCorrection,
                className
            } = opts;
            let dataLabelText = null;
            if (Array.isArray(w.config.dataLabels.enabledOnSeries)) {
                if (w.config.dataLabels.enabledOnSeries.indexOf(i) < 0) {
                    return dataLabelText;
                }
            }
            let correctedLabels = {
                x,
                y,
                drawnextLabel: true,
                textRects: null
            };
            if (offsetCorrection) {
                correctedLabels = this.dataLabelsCorrection(
                    x,
                    y,
                    text,
                    i,
                    j,
                    alwaysDrawDataLabel,
                    parseInt(
                        /** @type {any} */
                        dataLabelsConfig.style.fontSize,
                        10
                    ).toString()
                );
            }
            if (!w.interact.zoomed) {
                x = correctedLabels.x;
                y = correctedLabels.y;
            }
            if (correctedLabels.textRects) {
                const barPad = w.globals.barPadForNumericAxis || 0;
                if (x < -(barPad + 20) - /** @type {any} */
                    correctedLabels.textRects.width || x > w.layout.gridWidth + /** @type {any} */
                    correctedLabels.textRects.width + barPad + 30) {
                    text = "";
                }
            }
            let dataLabelColor = w.globals.dataLabels.style.colors[i];
            if ((w.config.chart.type === "bar" || w.config.chart.type === "rangeBar") && w.config.plotOptions.bar.distributed || w.config.dataLabels.distributed) {
                dataLabelColor = w.globals.dataLabels.style.colors[j];
            }
            if (typeof dataLabelColor === "function") {
                dataLabelColor = /** @type {any} */
                    dataLabelColor({
                        series: w.seriesData.series,
                        seriesIndex: i,
                        dataPointIndex: j,
                        w
                    });
            }
            if (color) {
                dataLabelColor = color;
            }
            let offX = dataLabelsConfig.offsetX;
            let offY = dataLabelsConfig.offsetY;
            if (w.config.chart.type === "bar" || w.config.chart.type === "rangeBar") {
                offX = 0;
                offY = 0;
            }
            if (w.globals.isSlopeChart) {
                if (j !== 0) {
                    offX = dataLabelsConfig.offsetX * -2 + 5;
                }
                if (j !== 0 && j !== /** @type {Record<string,any>} */
                    w.config.series[i].data.length - 1) {
                    offX = 0;
                }
            }
            if (correctedLabels.drawnextLabel) {
                if (textAnchor === "middle") {
                    if (x === w.layout.gridWidth) {
                        textAnchor = "end";
                    }
                }
                dataLabelText = graphics.drawText({
                    x: x + offX,
                    y: y + offY,
                    foreColor: dataLabelColor,
                    textAnchor: textAnchor || dataLabelsConfig.textAnchor,
                    text,
                    fontSize: fontSize || dataLabelsConfig.style.fontSize,
                    fontFamily: dataLabelsConfig.style.fontFamily,
                    fontWeight: dataLabelsConfig.style.fontWeight || "normal"
                });
                dataLabelText.attr({
                    class: className || "apexcharts-datalabel",
                    cx: x,
                    cy: y
                });
                if (dataLabelsConfig.dropShadow.enabled) {
                    const textShadow = dataLabelsConfig.dropShadow;
                    const filters = new Filters(this.w);
                    filters.dropShadow(dataLabelText, textShadow);
                }
                parent.add(dataLabelText);
                applyProgressiveReveal(dataLabelText, x, w);
                if (typeof w.globals.lastDrawnDataLabelsIndexes[i] === "undefined") {
                    w.globals.lastDrawnDataLabelsIndexes[i] = [];
                }
                w.globals.lastDrawnDataLabelsIndexes[i].push(j);
            }
            return dataLabelText;
        }
        /**
         * @param {Element} el
         * @param {{x: number, y: number, width: number, height: number}} coords
         */
        addBackgroundToDataLabel(el, coords) {
            const w = this.w;
            const bCnf = w.config.dataLabels.background;
            const paddingH = bCnf.padding;
            const paddingV = bCnf.padding / 2;
            const width = coords.width;
            const height = coords.height;
            const graphics = new Graphics(this.w);
            const elRect = graphics.drawRect(
                coords.x - paddingH,
                coords.y - paddingV / 2,
                width + paddingH * 2,
                height + paddingV,
                bCnf.borderRadius,
                w.config.chart.background === "transparent" || !w.config.chart.background ? "#fff" : w.config.chart.background,
                bCnf.opacity,
                bCnf.borderWidth,
                bCnf.borderColor
            );
            if (bCnf.dropShadow.enabled) {
                const filters = new Filters(this.w);
                filters.dropShadow(elRect, bCnf.dropShadow);
            }
            return elRect;
        }
        dataLabelsBackground() {
            var _a;
            const w = this.w;
            if (w.config.chart.type === "bubble") return;
            const elDataLabels = w.dom.baseEl.querySelectorAll(
                ".apexcharts-datalabels text"
            );
            for (let i = 0; i < elDataLabels.length; i++) {
                const el = elDataLabels[i];
                const coords = (
                    /** @type {SVGGraphicsElement} */
                    el.getBBox()
                );
                let elRect = null;
                if (coords.width && coords.height) {
                    elRect = this.addBackgroundToDataLabel(el, coords);
                }
                if (elRect) {
                    (_a = el.parentNode) == null ? void 0 : _a.insertBefore(elRect.node, el);
                    const background = w.config.dataLabels.background.backgroundColor || el.getAttribute("fill");
                    const shouldAnim = w.config.chart.animations.enabled && !w.globals.resized && !w.globals.dataChanged;
                    if (shouldAnim) {
                        elRect.animate().attr({
                            fill: background
                        });
                    } else {
                        elRect.attr({
                            fill: background
                        });
                    }
                    el.setAttribute("fill", w.config.dataLabels.background.foreColor);
                    const cxAttr = el.getAttribute("cx");
                    if (cxAttr !== null) {
                        applyProgressiveReveal(elRect, parseFloat(cxAttr), w);
                    }
                }
            }
        }
        bringForward() {
            const w = this.w;
            const elDataLabelsNodes = w.dom.baseEl.querySelectorAll(
                ".apexcharts-datalabels"
            );
            const elSeries = w.dom.baseEl.querySelector(
                ".apexcharts-plot-series:last-child"
            );
            for (let i = 0; i < elDataLabelsNodes.length; i++) {
                if (elSeries) {
                    elSeries.insertBefore(elDataLabelsNodes[i], elSeries.nextSibling);
                }
            }
        }
    }
    class PerformanceCache {
        /**
         * Invalidate all caches
         * @param {import('../types/internal').ChartStateW} w - ApexCharts state object
         */
        static invalidateAll(w) {
            if (!w || !w.globals) return;
            if (w.globals.cachedSelectors) {
                w.globals.cachedSelectors = {};
            }
            if (w.globals.domCache) {
                w.globals.domCache.clear();
            }
            w.globals.dimensionCache = {};
        }
        /**
         * Invalidate dimension cache only
         * @param {import('../types/internal').ChartStateW} w - ApexCharts state object
         */
        static invalidateDimensions(w) {
            if (!w || !w.globals) return;
            w.globals.dimensionCache = {};
        }
        /**
         * Invalidate selector cache only
         * @param {import('../types/internal').ChartStateW} w - ApexCharts state object
         */
        static invalidateSelectors(w) {
            if (!w || !w.globals) return;
            if (w.globals.cachedSelectors) {
                w.globals.cachedSelectors = {};
            }
        }
        /**
         * Get cached selector result or compute and cache it
         * @param {import('../types/internal').ChartStateW} w - ApexCharts state object
         * @param {string} key - Cache key
         * @param {Function} queryFn - Function to execute if not cached
         * @returns {*} Cached or newly computed result
         */
        static getCachedSelector(w, key, queryFn) {
            if (!w || !w.globals) return queryFn();
            if (!w.globals.cachedSelectors) {
                w.globals.cachedSelectors = {};
            }
            if (!w.globals.cachedSelectors[key]) {
                w.globals.cachedSelectors[key] = queryFn();
            }
            return w.globals.cachedSelectors[key];
        }
        /**
         * Get cached dimension or compute and cache it
         * @param {import('../types/internal').ChartStateW} w - ApexCharts state object
         * @param {string} key - Cache key
         * @param {Function} computeFn - Function to compute dimensions
         * @param {number} maxAge - Maximum cache age in milliseconds (default: 1000ms)
         * @returns {*} Cached or newly computed dimensions
         */
        static getCachedDimension(w, key, computeFn, maxAge = 1e3) {
            if (!w || !w.globals) return computeFn();
            if (!w.globals.dimensionCache) {
                w.globals.dimensionCache = {};
            }
            const cache = w.globals.dimensionCache[key];
            const now = Date.now();
            if (cache && cache.lastUpdate && now - cache.lastUpdate < maxAge) {
                return cache.value;
            }
            const value = computeFn();
            w.globals.dimensionCache[key] = {
                value,
                lastUpdate: now
            };
            return value;
        }
        /**
         * Cache a DOM element reference
         * @param {import('../types/internal').ChartStateW} w - ApexCharts state object
         * @param {string} key - Cache key
         * @param {Element} element - DOM element to cache
         */
        static cacheDOMElement(w, key, element) {
            if (!w || !w.globals) return;
            if (!w.globals.domCache) {
                w.globals.domCache = /* @__PURE__ */ new Map();
            }
            w.globals.domCache.set(key, element);
        }
        /**
         * Get cached DOM element
         * @param {import('../types/internal').ChartStateW} w - ApexCharts state object
         * @param {string} key - Cache key
         * @returns {Element|null} Cached element or null
         */
        static getCachedDOMElement(w, key) {
            if (!w || !w.globals || !w.globals.domCache) return null;
            return w.globals.domCache.get(key) || null;
        }
    }
    class AxesUtils {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         */
        constructor(w, {
            theme = null,
            timeScale = null
        } = {}) {
            this.w = w;
            this.theme = theme;
            this.timeScale = timeScale;
        }
        // Based on the formatter function, get the label text and position
        /**
         * @param {any[]} labels
         * @param {Array<Record<string, any>>} timescaleLabels
         * @param {number} x
         * @param {number} i
         * @param {any[]} drawnLabels
         */
        getLabel(labels, timescaleLabels, x, i, drawnLabels = [], fontSize = "12px", isLeafGroup = true) {
            const w = this.w;
            const rawLabel = typeof labels[i] === "undefined" ? "" : labels[i];
            let label = rawLabel;
            const xlbFormatter = w.formatters.xLabelFormatter;
            const customFormatter = w.config.xaxis.labels.formatter;
            const xFormat = new Formatters(this.w);
            const timestamp = rawLabel;
            if (isLeafGroup) {
                label = /** @type {any} */
                    xFormat.xLabelFormat(
                        xlbFormatter,
                        rawLabel,
                        timestamp, {
                            i,
                            dateFormatter: new DateTime(this.w).formatDate,
                            w
                        }
                    );
                if (customFormatter !== void 0) {
                    label = customFormatter(rawLabel, labels[i], {
                        i,
                        dateFormatter: new DateTime(this.w).formatDate,
                        w
                    });
                }
            }
            if (timescaleLabels.length > 0) {
                x = timescaleLabels[i].position;
                label = timescaleLabels[i].value;
            } else {
                if (w.config.xaxis.type === "datetime" && customFormatter === void 0) {
                    label = "";
                }
            }
            if (typeof label === "undefined") label = "";
            label = Array.isArray(label) ? label : label.toString();
            const graphics = new Graphics(this.w);
            let textRect = {};
            if (w.layout.rotateXLabels && isLeafGroup) {
                textRect = graphics.getTextRects(
                    label,
                    parseInt(fontSize, 10).toString(),
                    null,
                    `rotate(${w.config.xaxis.labels.rotate} 0 0)`,
                    false
                );
            } else {
                textRect = graphics.getTextRects(label, parseInt(fontSize, 10).toString());
            }
            const allowDuplicatesInTimeScale = !w.config.xaxis.labels.showDuplicates && this.timeScale;
            if (!Array.isArray(label) && (String(label) === "NaN" || drawnLabels.indexOf(label) >= 0 && allowDuplicatesInTimeScale)) {
                label = "";
            }
            return {
                x,
                text: label,
                textRect
            };
        }
        /**
         * @param {number} i
         * @param {any} label
         * @param {number} labelsLen
         */
        checkLabelBasedOnTickamount(i, label, labelsLen) {
            const w = this.w;
            let ticks = w.config.xaxis.tickAmount;
            if (ticks === "dataPoints") ticks = Math.round(w.layout.gridWidth / 120);
            if (ticks > labelsLen) return label;
            const tickMultiple = Math.round(labelsLen / (ticks + 1));
            if (i % tickMultiple === 0) {
                return label;
            } else {
                label.text = "";
            }
            return label;
        }
        /**
         * @param {number} i
         * @param {any} label
         * @param {number} labelsLen
         * @param {any[]} drawnLabels
         * @param {Array<Record<string, any>>} drawnLabelsRects
         */
        checkForOverflowingLabels(i, label, labelsLen, drawnLabels, drawnLabelsRects) {
            const w = this.w;
            if (i === 0) {
                if (w.globals.skipFirstTimelinelabel) {
                    label.text = "";
                }
            }
            if (i === labelsLen - 1) {
                if (w.globals.skipLastTimelinelabel) {
                    label.text = "";
                }
            }
            if (w.config.xaxis.labels.hideOverlappingLabels && drawnLabels.length > 0) {
                const prev = drawnLabelsRects[drawnLabelsRects.length - 1];
                if (w.config.xaxis.labels.trim && w.config.xaxis.type !== "datetime") {
                    return label;
                }
                if (
                    /** @type {any} */
                    label.x < prev.textRect.width / (w.layout.rotateXLabels ? Math.abs(w.config.xaxis.labels.rotate) / 12 : 1.01) + prev.x
                ) {
                    label.text = "";
                }
            }
            return label;
        }
        /**
         * @param {number} i
         * @param {any[]} labels
         */
        checkForReversedLabels(i, labels) {
            const w = this.w;
            if (w.config.yaxis[i] && w.config.yaxis[i].reversed) {
                labels.reverse();
            }
            return labels;
        }
        /**
         * @param {number} index
         */
        yAxisAllSeriesCollapsed(index) {
            const gl = this.w.globals;
            return !gl.seriesYAxisMap[index].some((si) => {
                return gl.collapsedSeriesIndices.indexOf(si) === -1;
            });
        }
        // Method to translate annotation.yAxisIndex values from
        // seriesName-as-a-string values to seriesName-as-an-array values (old style
        // series mapping to new style).
        /**
         * @param {number} index
         */
        translateYAxisIndex(index) {
            const w = this.w;
            const gl = w.globals;
            const yaxis = w.config.yaxis;
            const newStyle = w.seriesData.series.length > yaxis.length ||
                /**
                 * @param {Record<string, any>} a
                 */
                yaxis.some((a) => Array.isArray(a.seriesName));
            if (newStyle) {
                return index;
            } else {
                return gl.seriesYAxisReverseMap[index];
            }
        }
        /**
         * @param {number} index
         */
        isYAxisHidden(index) {
            const w = this.w;
            const yaxis = w.config.yaxis[index];
            if (!yaxis.show || this.yAxisAllSeriesCollapsed(index)) {
                return true;
            }
            if (!yaxis.showForNullSeries) {
                const seriesIndices = w.globals.seriesYAxisMap[index];
                const coreUtils = new CoreUtils(this.w);
                return seriesIndices.every((si) => coreUtils.isSeriesNull(si));
            }
            return false;
        }
        // get the label color for y-axis
        // realIndex is the actual series index, while i is the tick Index
        /**
         * @param {string[]} yColors
         * @param {number} realIndex
         */
        getYAxisForeColor(yColors, realIndex) {
            var _a;
            const w = this.w;
            if (Array.isArray(yColors) && w.globals.yAxisScale[realIndex]) {
                (_a = this.theme) == null ? void 0 : _a.pushExtraColors(
                    yColors,
                    w.globals.yAxisScale[realIndex].result.length,
                    false
                );
            }
            return yColors;
        }
        /**
         * @param {number} x
         * @param {number} tickAmount
         * @param {Record<string, any>} axisBorder
         * @param {Record<string, any>} axisTicks
         * @param {number} realIndex
         * @param {any} labelsDivider
         * @param {any} elYaxis
         */
        drawYAxisTicks(x, tickAmount, axisBorder, axisTicks, realIndex, labelsDivider, elYaxis) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            let tY = w.layout.translateY + w.config.yaxis[realIndex].labels.offsetY;
            if (w.globals.isBarHorizontal) {
                tY = 0;
            } else if (w.config.chart.type === "heatmap") {
                tY += labelsDivider / 2;
            }
            if (axisTicks.show && tickAmount > 0) {
                if (w.config.yaxis[realIndex].opposite === true) x = x + axisTicks.width;
                for (let i = tickAmount; i >= 0; i--) {
                    const elTick = graphics.drawLine(
                        x + axisBorder.offsetX - axisTicks.width + axisTicks.offsetX,
                        tY + axisTicks.offsetY,
                        x + axisBorder.offsetX + axisTicks.offsetX,
                        tY + axisTicks.offsetY,
                        axisTicks.color
                    );
                    elYaxis.add(elTick);
                    tY += labelsDivider;
                }
            }
        }
    }
    class XAxis {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {import('../../types/internal').ChartContext} ctx
         * @param {any} [elgrid]
         */
        constructor(w, ctx, elgrid) {
            this.w = w;
            this.ctx = ctx;
            this.elgrid = elgrid;
            this.axesUtils = new AxesUtils(w, {
                theme: ctx.theme,
                timeScale: ctx.timeScale
            });
            this.xaxisLabels = w.labelData.labels.slice();
            if (w.labelData.timescaleLabels.length > 0 && !w.globals.isBarHorizontal) {
                this.xaxisLabels = w.labelData.timescaleLabels.slice();
            }
            if (w.config.xaxis.overwriteCategories) {
                this.xaxisLabels = w.config.xaxis.overwriteCategories;
            }
            this.drawnLabels = [];
            this.drawnLabelsRects = [];
            if (w.config.xaxis.position === "top") {
                this.offY = 0;
            } else {
                this.offY = w.layout.gridHeight;
            }
            this.offY = this.offY + w.config.xaxis.axisBorder.offsetY;
            this.isCategoryBarHorizontal = w.config.chart.type === "bar" && w.config.plotOptions.bar.horizontal;
            this.xaxisFontSize = w.config.xaxis.labels.style.fontSize;
            this.xaxisFontFamily = w.config.xaxis.labels.style.fontFamily;
            this.xaxisForeColors = w.config.xaxis.labels.style.colors;
            this.xaxisBorderWidth = w.config.xaxis.axisBorder.width;
            if (this.isCategoryBarHorizontal) {
                this.xaxisBorderWidth = w.config.yaxis[0].axisBorder.width.toString();
            }
            if (String(this.xaxisBorderWidth).indexOf("%") > -1) {
                this.xaxisBorderWidth = w.layout.gridWidth * parseInt(this.xaxisBorderWidth, 10) / 100;
            } else {
                this.xaxisBorderWidth = parseInt(this.xaxisBorderWidth, 10);
            }
            this.xaxisBorderHeight = w.config.xaxis.axisBorder.height;
            this.yaxis = w.config.yaxis[0];
        }
        drawXaxis() {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const elXaxis = graphics.group({
                class: "apexcharts-xaxis",
                transform: `translate(${w.config.xaxis.offsetX}, ${w.config.xaxis.offsetY})`
            });
            const elXaxisTexts = graphics.group({
                class: "apexcharts-xaxis-texts-g",
                transform: `translate(${w.layout.translateXAxisX}, ${w.layout.translateXAxisY})`
            });
            elXaxis.add(elXaxisTexts);
            let labels = [];
            for (let i = 0; i < this.xaxisLabels.length; i++) {
                labels.push(this.xaxisLabels[i]);
            }
            this.drawXAxisLabelAndGroup(
                true,
                graphics,
                elXaxisTexts,
                labels,
                w.axisFlags.isXNumeric,
                (i, colWidth) => colWidth
            );
            if (w.labelData.hasXaxisGroups) {
                const labelsGroup = w.labelData.groups;
                labels = [];
                for (let i = 0; i < labelsGroup.length; i++) {
                    labels.push(labelsGroup[i].title);
                }
                const overwriteStyles = (
                    /** @type {any} */
                    {}
                );
                if (w.config.xaxis.group.style) {
                    overwriteStyles.xaxisFontSize = w.config.xaxis.group.style.fontSize;
                    overwriteStyles.xaxisFontFamily = w.config.xaxis.group.style.fontFamily;
                    overwriteStyles.xaxisForeColors = w.config.xaxis.group.style.colors;
                    overwriteStyles.fontWeight = w.config.xaxis.group.style.fontWeight;
                    overwriteStyles.cssClass = w.config.xaxis.group.style.cssClass;
                }
                this.drawXAxisLabelAndGroup(
                    false,
                    graphics,
                    elXaxisTexts,
                    labels,
                    false,
                    (i, colWidth) => labelsGroup[i].cols * colWidth,
                    overwriteStyles
                );
            }
            if (w.config.xaxis.title.text !== void 0) {
                const elXaxisTitle = graphics.group({
                    class: "apexcharts-xaxis-title"
                });
                const elXAxisTitleText = graphics.drawText({
                    x: w.layout.gridWidth / 2 + w.config.xaxis.title.offsetX,
                    y: this.offY + parseFloat(this.xaxisFontSize) + (w.config.xaxis.position === "bottom" ? w.layout.xAxisLabelsHeight : -w.layout.xAxisLabelsHeight - 10) + w.config.xaxis.title.offsetY,
                    text: w.config.xaxis.title.text,
                    textAnchor: "middle",
                    fontSize: w.config.xaxis.title.style.fontSize,
                    fontFamily: w.config.xaxis.title.style.fontFamily,
                    fontWeight: w.config.xaxis.title.style.fontWeight,
                    foreColor: w.config.xaxis.title.style.color,
                    cssClass: "apexcharts-xaxis-title-text " + w.config.xaxis.title.style.cssClass
                });
                elXaxisTitle.add(elXAxisTitleText);
                elXaxis.add(elXaxisTitle);
            }
            if (w.config.xaxis.axisBorder.show) {
                const offX = w.globals.barPadForNumericAxis;
                const elHorzLine = graphics.drawLine(
                    w.globals.padHorizontal + w.config.xaxis.axisBorder.offsetX - offX,
                    this.offY,
                    this.xaxisBorderWidth + offX,
                    this.offY,
                    w.config.xaxis.axisBorder.color,
                    0,
                    this.xaxisBorderHeight
                );
                if (this.elgrid && this.elgrid.elGridBorders && w.config.grid.show) {
                    this.elgrid.elGridBorders.add(elHorzLine);
                } else {
                    elXaxis.add(elHorzLine);
                }
            }
            return elXaxis;
        }
        /**
         * @param {Record<string, any>} [overwriteStyles]
         * @param {boolean} isLeafGroup
         * @param {import('../Graphics').default} graphics
         * @param {any} elXaxisTexts
         * @param {any[]} labels
         * @param {boolean} isXNumeric
         * @param {any} colWidthCb
         */
        drawXAxisLabelAndGroup(isLeafGroup, graphics, elXaxisTexts, labels, isXNumeric, colWidthCb, overwriteStyles = {}) {
            var _a, _b;
            const drawnLabels = [];
            const drawnLabelsRects = [];
            const w = this.w;
            const xaxisFontSize = overwriteStyles.xaxisFontSize || this.xaxisFontSize;
            const xaxisFontFamily = overwriteStyles.xaxisFontFamily || this.xaxisFontFamily;
            const xaxisForeColors = overwriteStyles.xaxisForeColors || this.xaxisForeColors;
            const fontWeight = overwriteStyles.fontWeight || w.config.xaxis.labels.style.fontWeight;
            const cssClass = overwriteStyles.cssClass || w.config.xaxis.labels.style.cssClass;
            let colWidth;
            let xPos = w.globals.padHorizontal;
            const labelsLen = labels.length;
            let dataPoints = w.config.xaxis.type === "category" ? w.globals.dataPoints : labelsLen;
            if (dataPoints === 0 && labelsLen > dataPoints) dataPoints = labelsLen;
            if (isXNumeric) {
                const len = Math.max(
                    Number(w.config.xaxis.tickAmount) || 1,
                    dataPoints > 1 ? dataPoints - 1 : dataPoints
                );
                colWidth = w.layout.gridWidth / Math.min(len, labelsLen - 1);
                xPos = xPos + colWidthCb(0, colWidth) / 2 + w.config.xaxis.labels.offsetX;
            } else {
                colWidth = w.layout.gridWidth / dataPoints;
                xPos = xPos + colWidthCb(0, colWidth) + w.config.xaxis.labels.offsetX;
            }
            for (let i = 0; i <= labelsLen - 1; i++) {
                let x = xPos - colWidthCb(i, colWidth) / 2 + w.config.xaxis.labels.offsetX;
                if (i === 0 && labelsLen === 1 && colWidth / 2 === xPos && dataPoints === 1) {
                    x = w.layout.gridWidth / 2;
                }
                let label = this.axesUtils.getLabel(
                    labels,
                    w.labelData.timescaleLabels,
                    x,
                    i,
                    drawnLabels,
                    xaxisFontSize,
                    isLeafGroup
                );
                let offsetYCorrection = 28;
                if (w.layout.rotateXLabels && isLeafGroup) {
                    offsetYCorrection = 22;
                }
                if (w.config.xaxis.title.text && w.config.xaxis.position === "top") {
                    offsetYCorrection += parseFloat(w.config.xaxis.title.style.fontSize) + 2;
                }
                if (!isLeafGroup) {
                    offsetYCorrection = offsetYCorrection + parseFloat(xaxisFontSize) + (w.layout.xAxisLabelsHeight - w.layout.xAxisGroupLabelsHeight) + (w.layout.rotateXLabels ? 10 : 0);
                }
                const isCategoryTickAmounts = typeof w.config.xaxis.tickAmount !== "undefined" && w.config.xaxis.tickAmount !== "dataPoints" && w.config.xaxis.type !== "datetime";
                if (isCategoryTickAmounts) {
                    label = this.axesUtils.checkLabelBasedOnTickamount(i, label, labelsLen);
                } else {
                    label = this.axesUtils.checkForOverflowingLabels(
                        i,
                        label,
                        labelsLen,
                        drawnLabels,
                        drawnLabelsRects
                    );
                }
                const getCatForeColor = () => {
                    return isLeafGroup && w.config.xaxis.convertedCatToNumeric ? xaxisForeColors[w.globals.minX + i - 1] : xaxisForeColors[i];
                };
                const labelRectWidth = (
                    /** @type {any} */
                    (_b = (_a = label.textRect) == null ? void 0 : _a.width) != null ? _b : 0
                );
                const halfWidth = labelRectWidth / 2;
                const fullyOutsideGrid = label.x + halfWidth < 0;
                if (w.config.xaxis.labels.show && !fullyOutsideGrid) {
                    const elText = graphics.drawText({
                        x: label.x,
                        y: this.offY + w.config.xaxis.labels.offsetY + offsetYCorrection - (w.config.xaxis.position === "top" ? w.layout.xAxisHeight + w.config.xaxis.axisTicks.height - 2 : 0),
                        text: label.text,
                        textAnchor: "middle",
                        fontWeight,
                        fontSize: xaxisFontSize,
                        fontFamily: xaxisFontFamily,
                        foreColor: Array.isArray(xaxisForeColors) ? getCatForeColor() : xaxisForeColors,
                        isPlainText: false,
                        cssClass: (isLeafGroup ? "apexcharts-xaxis-label " : "apexcharts-xaxis-group-label ") + cssClass
                    });
                    elXaxisTexts.add(elText);
                    elText.on("click", (e) => {
                        if (typeof w.config.chart.events.xAxisLabelClick === "function") {
                            const opts = Object.assign({}, w, {
                                labelIndex: i
                            });
                            w.config.chart.events.xAxisLabelClick(e, this.ctx, opts);
                        }
                    });
                    if (isLeafGroup) {
                        const elTooltipTitle = BrowserAPIs.createElementNS(SVGNS, "title");
                        elTooltipTitle.textContent = Array.isArray(label.text) ? label.text.join(" ") : label.text;
                        elText.node.appendChild(elTooltipTitle);
                        if (label.text !== "") {
                            drawnLabels.push(label.text);
                            drawnLabelsRects.push(label);
                        }
                    }
                }
                if (i < labelsLen - 1) {
                    xPos = xPos + colWidthCb(i + 1, colWidth);
                }
            }
        }
        // this actually becomes the vertical axis (for bar charts)
        /**
         * @param {number} realIndex
         */
        drawXaxisInversed(realIndex) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const translateYAxisX = w.config.yaxis[0].opposite ? w.globals.translateYAxisX[realIndex] : 0;
            const elYaxis = graphics.group({
                class: "apexcharts-yaxis apexcharts-xaxis-inversed",
                rel: realIndex
            });
            const elYaxisTexts = graphics.group({
                class: "apexcharts-yaxis-texts-g apexcharts-xaxis-inversed-texts-g",
                transform: "translate(" + translateYAxisX + ", 0)"
            });
            elYaxis.add(elYaxisTexts);
            const labels = [];
            if (w.config.yaxis[realIndex].show) {
                for (let i = 0; i < this.xaxisLabels.length; i++) {
                    labels.push(this.xaxisLabels[i]);
                }
            }
            const colHeight = w.layout.gridHeight / labels.length;
            let yPos = -(colHeight / 2.2);
            const lbFormatter = w.formatters.yLabelFormatters[0];
            const ylabels = w.config.yaxis[0].labels;
            if (ylabels.show) {
                for (let i = 0; i <= labels.length - 1; i++) {
                    let label = typeof labels[i] === "undefined" ? "" : labels[i];
                    label = lbFormatter(label, {
                        seriesIndex: realIndex,
                        dataPointIndex: i,
                        w
                    });
                    const yColors = this.axesUtils.getYAxisForeColor(
                        ylabels.style.colors,
                        realIndex
                    );
                    const getForeColor = () => {
                        return Array.isArray(yColors) ? yColors[i] : yColors;
                    };
                    let multiY = 0;
                    if (Array.isArray(label)) {
                        multiY = label.length / 2 * parseInt(ylabels.style.fontSize, 10);
                    }
                    let offsetX = ylabels.offsetX - 15;
                    let textAnchor = "end";
                    if (this.yaxis.opposite) {
                        textAnchor = "start";
                    }
                    if (w.config.yaxis[0].labels.align === "left") {
                        offsetX = ylabels.offsetX;
                        textAnchor = "start";
                    } else if (w.config.yaxis[0].labels.align === "center") {
                        offsetX = ylabels.offsetX;
                        textAnchor = "middle";
                    } else if (w.config.yaxis[0].labels.align === "right") {
                        textAnchor = "end";
                    }
                    const elLabel = graphics.drawText({
                        x: offsetX,
                        y: yPos + colHeight + ylabels.offsetY - multiY,
                        text: label,
                        textAnchor,
                        foreColor: getForeColor(),
                        fontSize: ylabels.style.fontSize,
                        fontFamily: ylabels.style.fontFamily,
                        fontWeight: ylabels.style.fontWeight,
                        isPlainText: false,
                        cssClass: "apexcharts-yaxis-label " + ylabels.style.cssClass,
                        maxWidth: ylabels.maxWidth
                    });
                    elYaxisTexts.add(elLabel);
                    elLabel.on("click", (e) => {
                        if (typeof w.config.chart.events.xAxisLabelClick === "function") {
                            const opts = Object.assign({}, w, {
                                labelIndex: i
                            });
                            w.config.chart.events.xAxisLabelClick(e, this.ctx, opts);
                        }
                    });
                    const elTooltipTitle = BrowserAPIs.createElementNS(SVGNS, "title");
                    elTooltipTitle.textContent = Array.isArray(label) ? label.join(" ") : label;
                    elLabel.node.appendChild(elTooltipTitle);
                    if (w.config.yaxis[realIndex].labels.rotate !== 0) {
                        const labelRotatingCenter = graphics.rotateAroundCenter(elLabel.node);
                        elLabel.node.setAttribute(
                            "transform",
                            `rotate(${w.config.yaxis[realIndex].labels.rotate} 0 ${labelRotatingCenter.y})`
                        );
                    }
                    yPos = yPos + colHeight;
                }
            }
            if (w.config.yaxis[0].title.text !== void 0) {
                const elXaxisTitle = graphics.group({
                    class: "apexcharts-yaxis-title apexcharts-xaxis-title-inversed",
                    transform: "translate(" + translateYAxisX + ", 0)"
                });
                const elXAxisTitleText = graphics.drawText({
                    x: w.config.yaxis[0].title.offsetX,
                    y: w.layout.gridHeight / 2 + w.config.yaxis[0].title.offsetY,
                    text: w.config.yaxis[0].title.text,
                    textAnchor: "middle",
                    foreColor: w.config.yaxis[0].title.style.color,
                    fontSize: w.config.yaxis[0].title.style.fontSize,
                    fontWeight: w.config.yaxis[0].title.style.fontWeight,
                    fontFamily: w.config.yaxis[0].title.style.fontFamily,
                    cssClass: "apexcharts-yaxis-title-text " + w.config.yaxis[0].title.style.cssClass
                });
                elXaxisTitle.add(elXAxisTitleText);
                elYaxis.add(elXaxisTitle);
            }
            let offX = 0;
            if (this.isCategoryBarHorizontal && w.config.yaxis[0].opposite) {
                offX = w.layout.gridWidth;
            }
            const axisBorder = w.config.xaxis.axisBorder;
            if (axisBorder.show) {
                const elVerticalLine = graphics.drawLine(
                    w.globals.padHorizontal + axisBorder.offsetX + offX,
                    1 + axisBorder.offsetY,
                    w.globals.padHorizontal + axisBorder.offsetX + offX,
                    w.layout.gridHeight + axisBorder.offsetY,
                    axisBorder.color,
                    0
                );
                if (this.elgrid && this.elgrid.elGridBorders && w.config.grid.show) {
                    this.elgrid.elGridBorders.add(elVerticalLine);
                } else {
                    elYaxis.add(elVerticalLine);
                }
            }
            if (w.config.yaxis[0].axisTicks.show) {
                this.axesUtils.drawYAxisTicks(
                    offX,
                    labels.length,
                    w.config.yaxis[0].axisBorder,
                    w.config.yaxis[0].axisTicks,
                    0,
                    colHeight,
                    elYaxis
                );
            }
            return elYaxis;
        }
        /**
         * @param {number} x1
         * @param {number} y2
         * @param {any} appendToElement
         */
        drawXaxisTicks(x1, y2, appendToElement) {
            const w = this.w;
            const x2 = x1;
            if (x1 < 0 || x1 - 2 > w.layout.gridWidth) return;
            const y1 = this.offY + w.config.xaxis.axisTicks.offsetY;
            y2 = y2 + y1 + w.config.xaxis.axisTicks.height;
            if (w.config.xaxis.position === "top") {
                y2 = y1 - w.config.xaxis.axisTicks.height;
            }
            if (w.config.xaxis.axisTicks.show) {
                const graphics = new Graphics(this.w);
                const line = graphics.drawLine(
                    x1 + w.config.xaxis.axisTicks.offsetX,
                    y1 + w.config.xaxis.offsetY,
                    x2 + w.config.xaxis.axisTicks.offsetX,
                    y2 + w.config.xaxis.offsetY,
                    w.config.xaxis.axisTicks.color
                );
                appendToElement.add(line);
                line.node.classList.add("apexcharts-xaxis-tick");
            }
        }
        getXAxisTicksPositions() {
            const w = this.w;
            const xAxisTicksPositions = [];
            const xCount = this.xaxisLabels.length;
            let x1 = w.globals.padHorizontal;
            if (w.labelData.timescaleLabels.length > 0) {
                for (let i = 0; i < xCount; i++) {
                    x1 = this.xaxisLabels[i].position;
                    xAxisTicksPositions.push(x1);
                }
            } else {
                const xCountForCategoryCharts = xCount;
                for (let i = 0; i < xCountForCategoryCharts; i++) {
                    let x1Count = xCountForCategoryCharts;
                    if (w.axisFlags.isXNumeric && w.config.chart.type !== "bar") {
                        x1Count -= 1;
                    }
                    x1 = x1 + w.layout.gridWidth / x1Count;
                    xAxisTicksPositions.push(x1);
                }
            }
            return xAxisTicksPositions;
        }
        // to rotate x-axis labels or to put ... for longer text in xaxis
        xAxisLabelCorrections() {
            var _a, _b, _c;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const xAxis = w.dom.baseEl.querySelector(".apexcharts-xaxis-texts-g");
            const xAxisTexts = w.dom.baseEl.querySelectorAll(
                ".apexcharts-xaxis-texts-g text:not(.apexcharts-xaxis-group-label)"
            );
            const yAxisTextsInversed = w.dom.baseEl.querySelectorAll(
                ".apexcharts-yaxis-inversed text"
            );
            const xAxisTextsInversed = w.dom.baseEl.querySelectorAll(
                ".apexcharts-xaxis-inversed-texts-g text tspan"
            );
            if (w.layout.rotateXLabels || w.config.xaxis.labels.rotateAlways) {
                for (let xat = 0; xat < xAxisTexts.length; xat++) {
                    const textRotatingCenter = graphics.rotateAroundCenter(xAxisTexts[xat]);
                    textRotatingCenter.y = textRotatingCenter.y - 1;
                    textRotatingCenter.x = textRotatingCenter.x + 1;
                    xAxisTexts[xat].setAttribute(
                        "transform",
                        `rotate(${w.config.xaxis.labels.rotate} ${textRotatingCenter.x} ${textRotatingCenter.y})`
                    );
                    xAxisTexts[xat].setAttribute("text-anchor", `end`);
                    xAxis == null ? void 0 : xAxis.setAttribute("transform", `translate(0, ${-10})`);
                    const tSpan = xAxisTexts[xat].childNodes;
                    if (w.config.xaxis.labels.trim) {
                        Array.prototype.forEach.call(tSpan, (ts) => {
                            graphics.placeTextWithEllipsis(
                                ts,
                                ts.textContent,
                                w.layout.xAxisLabelsHeight - (w.config.legend.position === "bottom" ? 20 : 10)
                            );
                        });
                    }
                }
            } else {
                const width = w.layout.gridWidth / (w.labelData.labels.length + 1);
                for (let xat = 0; xat < xAxisTexts.length; xat++) {
                    const tSpan = xAxisTexts[xat].childNodes;
                    if (w.config.xaxis.labels.trim && w.config.xaxis.type !== "datetime") {
                        Array.prototype.forEach.call(tSpan, (ts) => {
                            graphics.placeTextWithEllipsis(ts, ts.textContent, width);
                        });
                    }
                }
            }
            if (yAxisTextsInversed.length > 0) {
                const firstLabelPosX = (
                    /** @type {SVGGraphicsElement} */
                    yAxisTextsInversed[yAxisTextsInversed.length - 1].getBBox()
                );
                const lastLabelPosX = (
                    /** @type {SVGGraphicsElement} */
                    yAxisTextsInversed[0].getBBox()
                );
                if (firstLabelPosX.x < -20) {
                    (_a = yAxisTextsInversed[yAxisTextsInversed.length - 1].parentNode) == null ? void 0 : _a.removeChild(
                        yAxisTextsInversed[yAxisTextsInversed.length - 1]
                    );
                }
                if (lastLabelPosX.x + lastLabelPosX.width > w.layout.gridWidth && !w.globals.isBarHorizontal) {
                    (_b = yAxisTextsInversed[0].parentNode) == null ? void 0 : _b.removeChild(yAxisTextsInversed[0]);
                }
                for (let xat = 0; xat < xAxisTextsInversed.length; xat++) {
                    graphics.placeTextWithEllipsis(
                        xAxisTextsInversed[xat],
                        (_c = xAxisTextsInversed[xat].textContent) != null ? _c : "",
                        w.config.yaxis[0].labels.maxWidth - (w.config.yaxis[0].title.text ? parseFloat(w.config.yaxis[0].title.style.fontSize) * 2 : 0) - 15
                    );
                }
            }
        }
        // renderXAxisBands() {
        //   let w = this.w;
        //   let plotBand = document.createElementNS(SVGNS, 'rect')
        //   w.dom.elGraphical.add(plotBand)
        // }
    }
    class Grid {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {import('../../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this.xaxisLabels = w.labelData.labels.slice();
            this.axesUtils = new AxesUtils(ctx.w, {
                theme: ctx.theme,
                timeScale: ctx.timeScale
            });
            this.isRangeBar = w.rangeData.seriesRange.length && w.globals.isBarHorizontal;
            if (w.labelData.timescaleLabels.length > 0) {
                this.xaxisLabels = w.labelData.timescaleLabels.slice();
            }
        }
        /**
         * @param {any} elGrid
         */
        drawGridArea(elGrid = null) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            if (!elGrid) {
                elGrid = graphics.group({
                    class: "apexcharts-grid"
                });
            }
            const elVerticalLine = graphics.drawLine(
                w.globals.padHorizontal,
                1,
                w.globals.padHorizontal,
                w.layout.gridHeight,
                "transparent"
            );
            const elHorzLine = graphics.drawLine(
                w.globals.padHorizontal,
                w.layout.gridHeight,
                w.layout.gridWidth,
                w.layout.gridHeight,
                "transparent"
            );
            elGrid.add(elHorzLine);
            elGrid.add(elVerticalLine);
            return elGrid;
        }
        drawGrid() {
            const gl = this.w.globals;
            if (gl.axisCharts) {
                const elgrid = this.renderGrid();
                this.drawGridArea(elgrid.el);
                return elgrid;
            }
            return null;
        }
        createGridMask() {
            const w = this.w;
            const gl = w.globals;
            const graphics = new Graphics(this.w);
            const strokeSize = Array.isArray(w.config.stroke.width) ? Math.max(...w.config.stroke.width) : w.config.stroke.width;
            const createClipPath = (id) => {
                const clipPath = BrowserAPIs.createElementNS(SVGNS, "clipPath");
                clipPath.setAttribute("id", id);
                return clipPath;
            };
            w.dom.elGridRectMask = createClipPath(`gridRectMask${gl.cuid}`);
            w.dom.elGridRectBarMask = createClipPath(`gridRectBarMask${gl.cuid}`);
            w.dom.elGridRectMarkerMask = createClipPath(`gridRectMarkerMask${gl.cuid}`);
            w.dom.elForecastMask = createClipPath(`forecastMask${gl.cuid}`);
            w.dom.elNonForecastMask = createClipPath(`nonForecastMask${gl.cuid}`);
            const hasBar = ["bar", "rangeBar", "candlestick", "boxPlot"].includes(
                w.config.chart.type
            ) || w.globals.comboBarCount > 0;
            let barWidthLeft = 0;
            let barWidthRight = 0;
            if (hasBar && w.axisFlags.isXNumeric && !w.globals.isBarHorizontal) {
                barWidthLeft = Math.max(
                    w.config.grid.padding.left,
                    gl.barPadForNumericAxis
                );
                barWidthRight = Math.max(
                    w.config.grid.padding.right,
                    gl.barPadForNumericAxis
                );
            }
            w.dom.elGridRect = graphics.drawRect(
                -strokeSize / 2 - 2,
                -strokeSize / 2 - 2,
                w.layout.gridWidth + strokeSize + 4,
                w.layout.gridHeight + strokeSize + 4,
                0,
                "#fff"
            );
            w.dom.elGridRectBar = graphics.drawRect(
                -strokeSize / 2 - barWidthLeft - 2,
                -strokeSize / 2 - 2,
                w.layout.gridWidth + strokeSize + barWidthRight + barWidthLeft + 4,
                w.layout.gridHeight + strokeSize + 4,
                0,
                "#fff"
            );
            const markerSize = w.globals.markers.largestSize;
            w.dom.elGridRectMarker = graphics.drawRect(
                Math.min(-strokeSize / 2 - barWidthLeft - 2, -markerSize),
                -markerSize,
                w.layout.gridWidth + Math.max(strokeSize + barWidthRight + barWidthLeft + 4, markerSize * 2),
                w.layout.gridHeight + markerSize * 2,
                0,
                "#fff"
            );
            w.dom.elGridRectMask.appendChild(w.dom.elGridRect.node);
            w.dom.elGridRectBarMask.appendChild(w.dom.elGridRectBar.node);
            w.dom.elGridRectMarkerMask.appendChild(w.dom.elGridRectMarker.node);
            const defs = w.dom.elDefs.node;
            defs.appendChild(w.dom.elGridRectMask);
            defs.appendChild(w.dom.elGridRectBarMask);
            defs.appendChild(w.dom.elGridRectMarkerMask);
            defs.appendChild(w.dom.elForecastMask);
            defs.appendChild(w.dom.elNonForecastMask);
        }
        /** @param {{i: any, x1: any, y1: any, x2: any, y2: any, xCount: any, parent: any}} opts */
        _drawGridLines({
            i,
            x1,
            y1,
            x2,
            y2,
            xCount,
            parent
        }) {
            const w = this.w;
            const shouldDraw = () => {
                if (i === 0 && w.globals.skipFirstTimelinelabel) return false;
                if (i === xCount - 1 && w.globals.skipLastTimelinelabel && !w.config.xaxis.labels.formatter)
                    return false;
                if (w.config.chart.type === "radar") return false;
                return true;
            };
            if (shouldDraw()) {
                if (w.config.grid.xaxis.lines.show) {
                    this._drawGridLine({
                        i,
                        x1,
                        y1,
                        x2,
                        y2,
                        xCount,
                        parent
                    });
                }
                let y_2 = 0;
                if (w.labelData.hasXaxisGroups && w.config.xaxis.tickPlacement === "between") {
                    const groups = w.labelData.groups;
                    if (groups) {
                        let gacc = 0;
                        for (let gi = 0; gacc < i && gi < groups.length; gi++) {
                            gacc += groups[gi].cols;
                        }
                        if (gacc === i) {
                            y_2 = w.layout.xAxisLabelsHeight * 0.6;
                        }
                    }
                }
                const xAxis = new XAxis(this.w, this.ctx);
                xAxis.drawXaxisTicks(x1, y_2, w.dom.elGraphical);
            }
        }
        /** @param {{i: any, x1: any, y1: any, x2: any, y2: any, xCount: any, parent: any}} opts */
        _drawGridLine({
            i,
            x1,
            y1,
            x2,
            y2,
            xCount,
            parent
        }) {
            const w = this.w;
            const isHorzLine = parent.node.classList.contains(
                "apexcharts-gridlines-horizontal"
            );
            const offX = w.globals.barPadForNumericAxis;
            const excludeBorders = y1 === 0 && y2 === 0 || x1 === 0 && x2 === 0 || y1 === w.layout.gridHeight && y2 === w.layout.gridHeight || w.globals.isBarHorizontal && (i === 0 || i === xCount - 1);
            const graphics = new Graphics(this.w);
            const line = graphics.drawLine(
                x1 - (isHorzLine ? offX : 0),
                y1,
                x2 + (isHorzLine ? offX : 0),
                y2,
                w.config.grid.borderColor,
                w.config.grid.strokeDashArray
            );
            line.node.classList.add("apexcharts-gridline");
            if (excludeBorders && w.config.grid.show) {
                this.elGridBorders.add(line);
            } else {
                parent.add(line);
            }
        }
        /** @param {{c: any, x1: any, y1: any, x2: any, y2: any, type: any}} opts */
        _drawGridBandRect({
            c,
            x1,
            y1,
            x2,
            y2,
            type
        }) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const offX = w.globals.barPadForNumericAxis;
            const color = w.config.grid[type].colors[c];
            const rect = graphics.drawRect(
                x1 - (type === "row" ? offX : 0),
                y1,
                x2 + (type === "row" ? offX * 2 : 0),
                y2,
                0,
                color,
                w.config.grid[type].opacity
            );
            this.elg.add(rect);
            rect.attr("clip-path", `url(#gridRectMask${w.globals.cuid})`);
            rect.node.classList.add(`apexcharts-grid-${type}`);
        }
        /** @param {{xCount: any, tickAmount: any}} opts */
        _drawXYLines({
            xCount,
            tickAmount
        }) {
            var _a;
            const w = this.w;
            const datetimeLines = ({
                xC,
                x1,
                y1,
                x2,
                y2
            }) => {
                for (let i = 0; i < xC; i++) {
                    x1 = /** @type {any} */
                        this.xaxisLabels[i].position;
                    x2 = /** @type {any} */
                        this.xaxisLabels[i].position;
                    this._drawGridLines({
                        i,
                        x1,
                        y1,
                        x2,
                        y2,
                        xCount,
                        parent: this.elgridLinesV
                    });
                }
            };
            const categoryLines = ({
                xC,
                x1,
                y1,
                x2,
                y2
            }) => {
                for (let i = 0; i < xC + (w.axisFlags.isXNumeric ? 0 : 1); i++) {
                    if (i === 0 && xC === 1 && w.globals.dataPoints === 1) {
                        x1 = w.layout.gridWidth / 2;
                        x2 = x1;
                    }
                    this._drawGridLines({
                        i,
                        x1,
                        y1,
                        x2,
                        y2,
                        xCount,
                        parent: this.elgridLinesV
                    });
                    x1 += w.layout.gridWidth / (w.axisFlags.isXNumeric ? xC - 1 : xC);
                    x2 = x1;
                }
            };
            if (w.config.grid.xaxis.lines.show || w.config.xaxis.axisTicks.show) {
                const x1 = w.globals.padHorizontal;
                const y1 = 0;
                let x2;
                const y2 = w.layout.gridHeight;
                if (w.labelData.timescaleLabels.length) {
                    datetimeLines({
                        xC: xCount,
                        x1,
                        y1,
                        x2,
                        y2
                    });
                } else {
                    if (w.axisFlags.isXNumeric) {
                        xCount = (_a = w.globals.xAxisScale) == null ? void 0 : _a.result.length;
                    }
                    categoryLines({
                        xC: xCount,
                        x1,
                        y1,
                        x2,
                        y2
                    });
                }
            }
            if (w.config.grid.yaxis.lines.show) {
                const x1 = 0;
                let y1 = 0;
                let y2 = 0;
                const x2 = w.layout.gridWidth;
                let tA = tickAmount + 1;
                if (this.isRangeBar) {
                    tA = w.labelData.labels.length;
                }
                for (let i = 0; i < tA + (this.isRangeBar ? 1 : 0); i++) {
                    this._drawGridLine({
                        i,
                        xCount: tA + (this.isRangeBar ? 1 : 0),
                        x1,
                        y1,
                        x2,
                        y2,
                        parent: this.elgridLinesH
                    });
                    y1 += w.layout.gridHeight / (this.isRangeBar ? tA : tickAmount);
                    y2 = y1;
                }
            }
        }
        /** @param {{ xCount?: any, tickAmount?: any }} opts */
        _drawInvertedXYLines({
            xCount
        }) {
            const w = this.w;
            if (w.config.grid.xaxis.lines.show || w.config.xaxis.axisTicks.show) {
                let x1 = w.globals.padHorizontal;
                const y1 = 0;
                let x2;
                const y2 = w.layout.gridHeight;
                for (let i = 0; i < xCount + 1; i++) {
                    if (w.config.grid.xaxis.lines.show) {
                        this._drawGridLine({
                            i,
                            xCount: xCount + 1,
                            x1,
                            y1,
                            x2,
                            y2,
                            parent: this.elgridLinesV
                        });
                    }
                    const xAxis = new XAxis(this.w, this.ctx);
                    xAxis.drawXaxisTicks(x1, 0, w.dom.elGraphical);
                    x1 += w.layout.gridWidth / xCount;
                    x2 = x1;
                }
            }
            if (w.config.grid.yaxis.lines.show) {
                const x1 = 0;
                let y1 = 0;
                let y2 = 0;
                const x2 = w.layout.gridWidth;
                for (let i = 0; i < w.globals.dataPoints + 1; i++) {
                    this._drawGridLine({
                        i,
                        xCount: w.globals.dataPoints + 1,
                        x1,
                        y1,
                        x2,
                        y2,
                        parent: this.elgridLinesH
                    });
                    y1 += w.layout.gridHeight / w.globals.dataPoints;
                    y2 = y1;
                }
            }
        }
        renderGrid() {
            var _a, _b, _c;
            const w = this.w;
            const gl = w.globals;
            const graphics = new Graphics(this.w);
            this.elg = graphics.group({
                class: "apexcharts-grid"
            });
            this.elgridLinesH = graphics.group({
                class: "apexcharts-gridlines-horizontal"
            });
            this.elgridLinesV = graphics.group({
                class: "apexcharts-gridlines-vertical"
            });
            this.elGridBorders = graphics.group({
                class: "apexcharts-grid-borders"
            });
            this.elg.add(this.elgridLinesH);
            this.elg.add(this.elgridLinesV);
            if (!w.config.grid.show) {
                this.elgridLinesV.hide();
                this.elgridLinesH.hide();
                this.elGridBorders.hide();
            }
            let gridAxisIndex = 0;
            while (gridAxisIndex < gl.seriesYAxisMap.length && gl.ignoreYAxisIndexes.includes(gridAxisIndex)) {
                gridAxisIndex++;
            }
            if (gridAxisIndex === gl.seriesYAxisMap.length) {
                gridAxisIndex = 0;
            }
            let yTickAmount = gl.yAxisScale[gridAxisIndex].result.length - 1;
            let xCount;
            if (!gl.isBarHorizontal || this.isRangeBar) {
                xCount = this.xaxisLabels.length;
                if (this.isRangeBar) {
                    yTickAmount = w.labelData.labels.length;
                    if (w.config.xaxis.tickAmount && w.config.xaxis.labels.formatter) {
                        xCount = w.config.xaxis.tickAmount;
                    }
                    if (((_c = (_b = (_a = gl.yAxisScale) == null ? void 0 : _a[gridAxisIndex]) == null ? void 0 : _b.result) == null ? void 0 : _c.length) > 0 && w.config.xaxis.type !== "datetime") {
                        xCount = gl.yAxisScale[gridAxisIndex].result.length - 1;
                    }
                }
                this._drawXYLines({
                    xCount,
                    tickAmount: yTickAmount
                });
            } else {
                xCount = yTickAmount;
                yTickAmount = gl.xTickAmount;
                this._drawInvertedXYLines({
                    xCount,
                    tickAmount: yTickAmount
                });
            }
            this.drawGridBands(xCount, yTickAmount);
            return {
                el: this.elg,
                elGridBorders: this.elGridBorders,
                xAxisTickWidth: w.layout.gridWidth / xCount
            };
        }
        /**
         * @param {number} xCount
         * @param {number} tickAmount
         */
        drawGridBands(xCount, tickAmount) {
            var _a, _b, _c, _d, _e;
            const w = this.w;
            const drawBands = (type, count, x1, y1, x2, y2) => {
                for (let i = 0, c = 0; i < count; i++, c++) {
                    if (c >= w.config.grid[type].colors.length) {
                        c = 0;
                    }
                    this._drawGridBandRect({
                        c,
                        x1,
                        y1,
                        x2,
                        y2,
                        type
                    });
                    y1 += w.layout.gridHeight / tickAmount;
                }
            };
            if (((_a = w.config.grid.row.colors) == null ? void 0 : _a.length) > 0) {
                drawBands(
                    "row",
                    tickAmount,
                    0,
                    0,
                    w.layout.gridWidth,
                    w.layout.gridHeight / tickAmount
                );
            }
            if (((_b = w.config.grid.column.colors) == null ? void 0 : _b.length) > 0) {
                let xc = !w.globals.isBarHorizontal && w.config.xaxis.tickPlacement === "on" && (w.config.xaxis.type === "category" || w.config.xaxis.convertedCatToNumeric) ? xCount - 1 : xCount;
                if (w.axisFlags.isXNumeric) {
                    xc = ((_d = (_c = w.globals.xAxisScale) == null ? void 0 : _c.result.length) != null ? _d : 1) - 1;
                }
                let x1 = w.globals.padHorizontal;
                const y1 = 0;
                let x2 = w.globals.padHorizontal + w.layout.gridWidth / xc;
                const y2 = w.layout.gridHeight;
                for (let i = 0, c = 0; i < xCount; i++, c++) {
                    if (c >= w.config.grid.column.colors.length) {
                        c = 0;
                    }
                    if (w.config.xaxis.type === "datetime") {
                        x1 = /** @type {any} */
                            this.xaxisLabels[i].position;
                        x2 = /** @type {any} */
                            (((_e = this.xaxisLabels[i + 1]) == null ? void 0 : _e.position) || w.layout.gridWidth) - /** @type {any} */
                            this.xaxisLabels[i].position;
                    }
                    this._drawGridBandRect({
                        c,
                        x1,
                        y1,
                        x2,
                        y2,
                        type: "column"
                    });
                    x1 += w.layout.gridWidth / xc;
                }
            }
        }
    }
    class Scales {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
            this.coreUtils = new CoreUtils(this.w);
        }
        // http://stackoverflow.com/questions/326679/choosing-an-attractive-linear-scale-for-a-graphs-y-axis
        // This routine creates the Y axis values for a graph.
        /**
         * @param {number} yMin
         * @param {number} yMax
         */
        niceScale(yMin, yMax, index = 0) {
            const jsPrecision = 1e-11;
            const w = this.w;
            const gl = w.globals;
            let axisCnf;
            let maxTicks;
            let gotMin;
            let gotMax;
            if (gl.isBarHorizontal) {
                axisCnf = w.config.xaxis;
                maxTicks = Math.max((gl.svgWidth - 100) / 25, 2);
            } else {
                axisCnf = w.config.yaxis[index];
                maxTicks = Math.max((gl.svgHeight - 100) / 15, 2);
            }
            if (!Utils$1.isNumber(maxTicks)) {
                maxTicks = 10;
            }
            gotMin = axisCnf.min !== void 0 && axisCnf.min !== null;
            gotMax = axisCnf.max !== void 0 && axisCnf.min !== null;
            let gotStepSize = axisCnf.stepSize !== void 0 && axisCnf.stepSize !== null;
            let gotTickAmount = axisCnf.tickAmount !== void 0 && axisCnf.tickAmount !== null;
            let ticks = gotTickAmount ? axisCnf.tickAmount : NICE_SCALE_DEFAULT_TICKS[Math.min(
                Math.round(maxTicks / 2),
                NICE_SCALE_DEFAULT_TICKS.length - 1
            )];
            if (gl.isMultipleYAxis && !gotTickAmount && gl.multiAxisTickAmount > 0) {
                ticks = gl.multiAxisTickAmount;
                gotTickAmount = true;
            }
            if (ticks === "dataPoints") {
                ticks = gl.dataPoints - 1;
            } else {
                ticks = Math.abs(Math.round(ticks));
            }
            if (yMin === Number.MIN_VALUE && yMax === 0 || !Utils$1.isNumber(yMin) && !Utils$1.isNumber(yMax) || yMin === Number.MIN_VALUE && yMax === -Number.MAX_VALUE) {
                yMin = Utils$1.isNumber(axisCnf.min) ? axisCnf.min : 0;
                yMax = Utils$1.isNumber(axisCnf.max) ? axisCnf.max : yMin + ticks;
                gl.allSeriesCollapsed = false;
            }
            if (yMin > yMax) {
                console.warn(
                    "axis.min cannot be greater than axis.max: swapping min and max"
                );
                const temp = yMax;
                yMax = yMin;
                yMin = temp;
            } else if (yMin === yMax) {
                yMin = yMin === 0 ? 0 : yMin - 1;
                yMax = yMax === 0 ? 2 : yMax + 1;
            }
            const result = [];
            if (ticks < 1) {
                ticks = 1;
            }
            let tiks = ticks;
            let range = Math.abs(yMax - yMin);
            const proximityRatio = 0.15;
            if (!gotMin && yMin > 0 && yMin / range < proximityRatio) {
                yMin = 0;
                gotMin = true;
            }
            if (!gotMax && yMax < 0 && -yMax / range < proximityRatio) {
                yMax = 0;
                gotMax = true;
            }
            range = Math.abs(yMax - yMin);
            let stepSize = range / tiks;
            let niceStep = stepSize;
            const mag = Math.floor(Math.log10(niceStep));
            const magPow = Math.pow(10, mag);
            let magMsd = Math.ceil(niceStep / magPow);
            magMsd = NICE_SCALE_ALLOWED_MAG_MSD[gl.yValueDecimal === 0 ? 0 : 1][magMsd];
            niceStep = magMsd * magPow;
            stepSize = niceStep;
            if (gl.isBarHorizontal && axisCnf.stepSize && axisCnf.type !== "datetime") {
                stepSize = axisCnf.stepSize;
                gotStepSize = true;
            } else if (gotStepSize) {
                stepSize = axisCnf.stepSize;
            }
            if (gotStepSize) {
                if (axisCnf.forceNiceScale) {
                    const stepMag = Math.floor(Math.log10(stepSize));
                    stepSize *= Math.pow(10, mag - stepMag);
                }
            }
            if (gotMin && gotMax) {
                let crudeStep = range / tiks;
                if (gotTickAmount) {
                    if (gotStepSize) {
                        if (Utils$1.mod(range, stepSize) != 0) {
                            const gcdStep = Utils$1.getGCD(stepSize, crudeStep);
                            if (crudeStep / gcdStep < 10) {
                                stepSize = gcdStep;
                            } else {
                                stepSize = crudeStep;
                            }
                        } else {
                            if (Utils$1.mod(stepSize, crudeStep) == 0) {
                                stepSize = crudeStep;
                            } else {
                                crudeStep = stepSize;
                                gotTickAmount = false;
                            }
                        }
                    } else {
                        stepSize = crudeStep;
                    }
                } else {
                    if (gotStepSize) {
                        if (Utils$1.mod(range, stepSize) == 0) {
                            crudeStep = stepSize;
                        } else {
                            stepSize = crudeStep;
                        }
                    } else {
                        if (Utils$1.mod(range, stepSize) == 0) {
                            crudeStep = stepSize;
                        } else {
                            tiks = Math.ceil(range / stepSize);
                            crudeStep = range / tiks;
                            const gcdStep = Utils$1.getGCD(range, stepSize);
                            if (range / gcdStep < maxTicks) {
                                crudeStep = gcdStep;
                            }
                            stepSize = crudeStep;
                        }
                    }
                }
                tiks = Math.round(range / stepSize);
            } else {
                if (!gotMin && !gotMax) {
                    if (gl.isMultipleYAxis && gotTickAmount) {
                        const tMin = stepSize * Math.floor(yMin / stepSize);
                        let tMax = tMin + stepSize * tiks;
                        if (tMax < yMax) {
                            stepSize *= 2;
                        }
                        yMin = tMin;
                        tMax = yMax;
                        yMax = yMin + stepSize * tiks;
                        range = Math.abs(yMax - yMin);
                        if (yMin > 0 && yMin < Math.abs(tMax - yMax)) {
                            yMin = 0;
                            yMax = stepSize * tiks;
                        }
                        if (yMax < 0 && -yMax < Math.abs(tMin - yMin)) {
                            yMax = 0;
                            yMin = -stepSize * tiks;
                        }
                    } else {
                        yMin = stepSize * Math.floor(yMin / stepSize);
                        yMax = stepSize * Math.ceil(yMax / stepSize);
                    }
                } else if (gotMax) {
                    if (gotTickAmount) {
                        yMin = yMax - stepSize * tiks;
                    } else {
                        const yMinPrev = yMin;
                        yMin = stepSize * Math.floor(yMin / stepSize);
                        if (Math.abs(yMax - yMin) / Utils$1.getGCD(range, stepSize) > maxTicks) {
                            yMin = yMax - stepSize * ticks;
                            yMin += stepSize * Math.floor((yMinPrev - yMin) / stepSize);
                        }
                    }
                } else if (gotMin) {
                    if (gotTickAmount) {
                        yMax = yMin + stepSize * tiks;
                    } else {
                        const yMaxPrev = yMax;
                        yMax = stepSize * Math.ceil(yMax / stepSize);
                        if (Math.abs(yMax - yMin) / Utils$1.getGCD(range, stepSize) > maxTicks) {
                            yMax = yMin + stepSize * ticks;
                            yMax += stepSize * Math.ceil((yMaxPrev - yMax) / stepSize);
                        }
                    }
                }
                range = Math.abs(yMax - yMin);
                stepSize = Utils$1.getGCD(range, stepSize);
                tiks = Math.round(range / stepSize);
            }
            if (!gotTickAmount && !(gotMin || gotMax)) {
                tiks = Math.ceil((range - jsPrecision) / (stepSize + jsPrecision));
                if (tiks > 16 && Utils$1.getPrimeFactors(tiks).length < 2) {
                    tiks++;
                }
            }
            if (!gotTickAmount && axisCnf.forceNiceScale && gl.yValueDecimal === 0 && tiks > range) {
                tiks = range;
                stepSize = Math.round(range / tiks);
            }
            if (tiks > maxTicks && (!(gotTickAmount || gotStepSize) || axisCnf.forceNiceScale)) {
                const pf = Utils$1.getPrimeFactors(tiks);
                const last = pf.length - 1;
                let tt = tiks;
                reduceLoop: for (var xFactors = 0; xFactors < last; xFactors++) {
                    for (var lowest = 0; lowest <= last - xFactors; lowest++) {
                        const stop = Math.min(lowest + xFactors, last);
                        let t = tt;
                        let div = 1;
                        for (var next = lowest; next <= stop; next++) {
                            div *= pf[next];
                        }
                        t /= div;
                        if (t < maxTicks) {
                            tt = t;
                            break reduceLoop;
                        }
                    }
                }
                if (tt === tiks) {
                    stepSize = range;
                } else {
                    stepSize = range / tt;
                }
                tiks = Math.round(range / stepSize);
            }
            if (gl.isMultipleYAxis && gl.multiAxisTickAmount == 0 && gl.ignoreYAxisIndexes.indexOf(index) < 0) {
                gl.multiAxisTickAmount = tiks;
            }
            let val = yMin - stepSize;
            const err = stepSize * jsPrecision;
            do {
                val += stepSize;
                result.push(Utils$1.stripNumber(val, 7));
            } while (yMax - val > err);
            return {
                result,
                niceMin: result[0],
                niceMax: result[result.length - 1]
            };
        }
        /** @param {number} yMin @param {number} yMax @param {number|string} ticks @param {number} index @param {number|undefined} step */
        linearScale(yMin, yMax, ticks = 10, index = 0, step = void 0) {
            const range = Math.abs(yMax - yMin);
            let result = [];
            if (yMin === yMax) {
                result = [yMin];
                return {
                    result,
                    niceMin: result[0],
                    niceMax: result[result.length - 1]
                };
            }
            ticks = this._adjustTicksForSmallRange(ticks, index, range);
            if (
                /** @type {any} */
                ticks === "dataPoints"
            ) {
                ticks = this.w.globals.dataPoints - 1;
            }
            const ticksNum = (
                /** @type {number} */
                ticks
            );
            if (!step) {
                step = range / ticksNum;
            }
            const MIN_PRECISION = 2;
            if (step !== 0 && isFinite(step)) {
                const magnitude = Math.floor(Math.log10(Math.abs(step)));
                const precision = Math.max(MIN_PRECISION, -magnitude + MIN_PRECISION);
                const multiplier = Math.pow(10, precision);
                step = Math.round((step + Number.EPSILON) * multiplier) / multiplier;
            }
            let tickCount = ticks === Number.MAX_VALUE ? 5 : ticksNum;
            if (ticks === Number.MAX_VALUE) {
                step = 1;
            }
            let v = yMin;
            while (tickCount >= 0) {
                result.push(v);
                v = Utils$1.preciseAddition(v, step);
                tickCount -= 1;
            }
            return {
                result,
                niceMin: result[0],
                niceMax: result[result.length - 1]
            };
        }
        /**
         * @param {number} yMin
         * @param {number} yMax
         * @param {number} base
         */
        logarithmicScaleNice(yMin, yMax, base) {
            if (yMax <= 0) yMax = Math.max(yMin, base);
            if (yMin <= 0) yMin = Math.min(yMax, base);
            const logs = [];
            const logMax = Math.ceil(Math.log(yMax) / Math.log(base) + 1);
            const logMin = Math.floor(Math.log(yMin) / Math.log(base));
            for (let i = logMin; i < logMax; i++) {
                logs.push(Math.pow(base, i));
            }
            return {
                result: logs,
                niceMin: logs[0],
                niceMax: logs[logs.length - 1]
            };
        }
        /**
         * @param {number} yMin
         * @param {number} yMax
         * @param {number} base
         */
        logarithmicScale(yMin, yMax, base) {
            if (yMax <= 0) yMax = Math.max(yMin, base);
            if (yMin <= 0) yMin = Math.min(yMax, base);
            const logs = [];
            const logMax = Math.log(yMax) / Math.log(base);
            const logMin = Math.log(yMin) / Math.log(base);
            const logRange = logMax - logMin;
            const ticks = Math.round(logRange);
            const logTickSpacing = logRange / ticks;
            for (let i = 0, logTick = logMin; i < ticks; i++, logTick += logTickSpacing) {
                logs.push(Math.pow(base, logTick));
            }
            logs.push(Math.pow(base, logMax));
            return {
                result: logs,
                niceMin: yMin,
                niceMax: yMax
            };
        }
        /**
         * @param {number | string} ticks
         * @param {number} index
         * @param {number} range
         */
        _adjustTicksForSmallRange(ticks, index, range) {
            let newTicks = ticks;
            if (typeof index !== "undefined" && this.w.config.yaxis[index].labels.formatter && this.w.config.yaxis[index].tickAmount === void 0) {
                const formattedVal = Number(
                    this.w.config.yaxis[index].labels.formatter(1)
                );
                if (Utils$1.isNumber(formattedVal) && this.w.globals.yValueDecimal === 0) {
                    newTicks = Math.ceil(range);
                }
            }
            return newTicks < ticks ? newTicks : ticks;
        }
        /**
         * @param {number} index
         * @param {number} minY
         * @param {number} maxY
         */
        setYScaleForIndex(index, minY, maxY) {
            const gl = this.w.globals;
            const cnf = this.w.config;
            const y = gl.isBarHorizontal ? cnf.xaxis : cnf.yaxis[index];
            if (typeof gl.yAxisScale[index] === "undefined") {
                gl.yAxisScale[index] = [];
            }
            const range = Math.abs(maxY - minY);
            if (y.logarithmic && range <= 5) {
                gl.invalidLogScale = true;
            }
            if (y.logarithmic && range > 5) {
                gl.allSeriesCollapsed = false;
                gl.yAxisScale[index] = y.forceNiceScale ? this.logarithmicScaleNice(minY, maxY, y.logBase) : this.logarithmicScale(minY, maxY, y.logBase);
            } else {
                if (maxY === -Number.MAX_VALUE || !Utils$1.isNumber(maxY) || minY === Number.MAX_VALUE || !Utils$1.isNumber(minY)) {
                    gl.yAxisScale[index] = this.niceScale(
                        Number.MIN_VALUE,
                        0,
                        index
                    );
                } else {
                    gl.allSeriesCollapsed = false;
                    gl.yAxisScale[index] = this.niceScale(
                        minY,
                        maxY,
                        index
                    );
                }
            }
        }
        /**
         * @param {number} minX
         * @param {number} maxX
         */
        setXScale(minX, maxX) {
            const w = this.w;
            const gl = w.globals;
            if (maxX === -Number.MAX_VALUE || !Utils$1.isNumber(maxX)) {
                gl.xAxisScale = this.linearScale(0, 10, 10);
            } else {
                const ticks = gl.xTickAmount;
                gl.xAxisScale = this.linearScale(
                    minX,
                    maxX,
                    ticks,
                    0,
                    w.config.xaxis.max === void 0 ? w.config.xaxis.stepSize : void 0
                );
            }
            return gl.xAxisScale;
        }
        scaleMultipleYAxes() {
            const cnf = this.w.config;
            const gl = this.w.globals;
            this.coreUtils.setSeriesYAxisMappings();
            const axisSeriesMap = gl.seriesYAxisMap;
            const minYArr = gl.minYArr;
            const maxYArr = gl.maxYArr;
            const alignZeroParticipants = [];
            const canAlignZero = !gl.isBarHorizontal;
            gl.allSeriesCollapsed = true;
            gl.barGroups = [];
            axisSeriesMap.forEach((axisSeries, ai) => {
                const groupNames = [];
                axisSeries.forEach((as) => {
                    var _a;
                    const group = (
                        /** @type {Record<string,any>} */
                        (_a = cnf.series[as]) == null ? void 0 : _a.group
                    );
                    if (groupNames.indexOf(group) < 0) {
                        groupNames.push(group);
                    }
                });
                if (axisSeries.length > 0) {
                    let minY = Number.MAX_VALUE;
                    let maxY = -Number.MAX_VALUE;
                    let lowestY = minY;
                    let highestY = maxY;
                    let seriesType;
                    let seriesGroupName;
                    if (cnf.chart.stacked) {
                        const mapSeries = new Array(gl.dataPoints).fill(0);
                        const sumSeries = [];
                        const posSeries = [];
                        const negSeries = [];
                        groupNames.forEach(() => {
                            sumSeries.push(mapSeries.map(() => Number.MIN_VALUE));
                            posSeries.push(mapSeries.map(() => Number.MIN_VALUE));
                            negSeries.push(mapSeries.map(() => Number.MIN_VALUE));
                        });
                        for (let i = 0; i < axisSeries.length; i++) {
                            if (!seriesType && /** @type {Record<string,any>} */
                                cnf.series[axisSeries[i]].type) {
                                seriesType = /** @type {Record<string,any>} */
                                    cnf.series[axisSeries[i]].type;
                            }
                            const si = axisSeries[i];
                            if (
                                /** @type {Record<string,any>} */
                                cnf.series[si].group
                            ) {
                                seriesGroupName = /** @type {Record<string,any>} */
                                    cnf.series[si].group;
                            } else {
                                seriesGroupName = "axis-".concat(ai.toString());
                            }
                            const collapsed = !(gl.collapsedSeriesIndices.indexOf(si) < 0 && gl.ancillaryCollapsedSeriesIndices.indexOf(si) < 0);
                            if (!collapsed) {
                                gl.allSeriesCollapsed = false;
                                groupNames.forEach((gn, gni) => {
                                    if (
                                        /** @type {Record<string,any>} */
                                        cnf.series[si].group === gn
                                    ) {
                                        for (let j = 0; j < this.w.seriesData.series[si].length; j++) {
                                            const val = this.w.seriesData.series[si][j];
                                            if (val >= 0) {
                                                posSeries[gni][j] += val;
                                            } else {
                                                negSeries[gni][j] += val;
                                            }
                                            sumSeries[gni][j] += val;
                                            lowestY = Math.min(lowestY, val);
                                            highestY = Math.max(highestY, val);
                                        }
                                    }
                                });
                            }
                            if (seriesType === "bar" || seriesType === "column") {
                                gl.barGroups.push(seriesGroupName);
                            }
                        }
                        if (!seriesType) {
                            seriesType = cnf.chart.type;
                        }
                        if (seriesType === "bar" || seriesType === "column") {
                            groupNames.forEach((gn, gni) => {
                                minY = Math.min(minY, Math.min.apply(null, negSeries[gni]));
                                maxY = Math.max(maxY, Math.max.apply(null, posSeries[gni]));
                            });
                        } else {
                            groupNames.forEach((gn, gni) => {
                                lowestY = Math.min(lowestY, Math.min.apply(null, sumSeries[gni]));
                                highestY = Math.max(
                                    highestY,
                                    Math.max.apply(null, sumSeries[gni])
                                );
                            });
                            minY = lowestY;
                            maxY = highestY;
                        }
                        if (minY === Number.MIN_VALUE && maxY === Number.MIN_VALUE) {
                            maxY = -Number.MAX_VALUE;
                        }
                    } else {
                        for (let i = 0; i < axisSeries.length; i++) {
                            const si = axisSeries[i];
                            minY = Math.min(minY, minYArr[si]);
                            maxY = Math.max(maxY, maxYArr[si]);
                            const collapsed = !(gl.collapsedSeriesIndices.indexOf(si) < 0 && gl.ancillaryCollapsedSeriesIndices.indexOf(si) < 0);
                            if (!collapsed) {
                                gl.allSeriesCollapsed = false;
                            }
                        }
                    }
                    if (cnf.yaxis[ai].min !== void 0) {
                        if (typeof cnf.yaxis[ai].min === "function") {
                            minY = cnf.yaxis[ai].min(minY);
                        } else {
                            minY = cnf.yaxis[ai].min;
                        }
                    }
                    if (cnf.yaxis[ai].max !== void 0) {
                        if (typeof cnf.yaxis[ai].max === "function") {
                            maxY = cnf.yaxis[ai].max(maxY);
                        } else {
                            maxY = cnf.yaxis[ai].max;
                        }
                    }
                    gl.barGroups = gl.barGroups.filter((v, i, a) => a.indexOf(v) === i);
                    const yaxe = cnf.yaxis[ai];
                    const participates = canAlignZero && yaxe.alignZero === true && !yaxe.logarithmic && yaxe.min === void 0 && yaxe.max === void 0 && gl.ignoreYAxisIndexes.indexOf(ai) < 0 && Utils$1.isNumber(minY) && Utils$1.isNumber(maxY);
                    if (participates) {
                        alignZeroParticipants.push({
                            ai,
                            minY,
                            maxY
                        });
                    } else {
                        this.setYScaleForIndex(ai, minY, maxY);
                        axisSeries.forEach((si) => {
                            minYArr[si] = gl.yAxisScale[ai].niceMin;
                            maxYArr[si] = gl.yAxisScale[ai].niceMax;
                        });
                    }
                } else {
                    this.setYScaleForIndex(ai, 0, -Number.MAX_VALUE);
                }
            });
            if (alignZeroParticipants.length >= 2) {
                alignZeroParticipants.forEach((p) => {
                    this.setYScaleForIndex(p.ai, p.minY, p.maxY);
                    axisSeriesMap[p.ai].forEach((si) => {
                        minYArr[si] = gl.yAxisScale[p.ai].niceMin;
                        maxYArr[si] = gl.yAxisScale[p.ai].niceMax;
                    });
                });
                let targetRatio = 0;
                alignZeroParticipants.forEach((p) => {
                    const scale = gl.yAxisScale[p.ai];
                    const range = scale.niceMax - scale.niceMin;
                    if (range > 0) {
                        const r = -scale.niceMin / range;
                        if (r > targetRatio) targetRatio = r;
                    }
                });
                if (targetRatio > 1) targetRatio = 1;
                if (targetRatio < 0) targetRatio = 0;
                const niceRoundUp = (raw) => {
                    if (raw <= 0) return 1;
                    const mag = Math.floor(Math.log10(raw));
                    const magPow = Math.pow(10, mag);
                    const msd = raw / magPow;
                    let mult;
                    if (msd <= 1 + 1e-9) mult = 1;
                    else if (msd <= 2 + 1e-9) mult = 2;
                    else if (msd <= 2.5 + 1e-9) mult = 2.5;
                    else if (msd <= 5 + 1e-9) mult = 5;
                    else mult = 10;
                    return mult * magPow;
                };
                alignZeroParticipants.forEach((p) => {
                    const scale = gl.yAxisScale[p.ai];
                    if (!scale.result || scale.result.length < 2) return;
                    const range = scale.niceMax - scale.niceMin;
                    if (range <= 0) return;
                    const r = -scale.niceMin / range;
                    if (Math.abs(r - targetRatio) <= 1e-9) return;
                    const extendMin = r < targetRatio && targetRatio < 1 - 1e-9;
                    const extendMaxOnly = !extendMin && r > targetRatio && targetRatio > 1e-9;
                    if (!extendMin && !extendMaxOnly) return;
                    const targetNiceMin = extendMin ? -targetRatio * scale.niceMax / (1 - targetRatio) : scale.niceMin;
                    const targetNiceMax = extendMaxOnly ? -scale.niceMin * (1 - targetRatio) / targetRatio : scale.niceMax;
                    const newRange = targetNiceMax - targetNiceMin;
                    if (newRange <= 0) return;
                    const desiredTicks = Math.max(scale.result.length, 5);
                    const newStep = niceRoundUp(newRange / Math.max(desiredTicks - 1, 1));
                    if (newStep <= 0) return;
                    let newNiceMin;
                    let newNiceMax;
                    if (extendMin) {
                        newNiceMin = Math.floor(targetNiceMin / newStep + 1e-9) * newStep;
                        const requiredMax = targetRatio > 1e-9 ? newNiceMin * (targetRatio - 1) / targetRatio : scale.niceMax;
                        const maxNeeded = Math.max(requiredMax, scale.niceMax);
                        newNiceMax = Math.ceil(maxNeeded / newStep - 1e-9) * newStep;
                    } else {
                        newNiceMax = Math.ceil(targetNiceMax / newStep - 1e-9) * newStep;
                        const requiredMin = targetRatio < 1 - 1e-9 ? -targetRatio * newNiceMax / (1 - targetRatio) : scale.niceMin;
                        const minNeeded = Math.min(requiredMin, scale.niceMin);
                        newNiceMin = Math.floor(minNeeded / newStep + 1e-9) * newStep;
                    }
                    scale.result = [];
                    for (let v = newNiceMin; v <= newNiceMax + newStep * 1e-9; v = Utils$1.preciseAddition(v, newStep)) {
                        scale.result.push(Utils$1.stripNumber(v, 7));
                    }
                    scale.niceMin = newNiceMin;
                    scale.niceMax = newNiceMax;
                    axisSeriesMap[p.ai].forEach((si) => {
                        minYArr[si] = scale.niceMin;
                        maxYArr[si] = scale.niceMax;
                    });
                });
            } else if (alignZeroParticipants.length === 1) {
                const p = alignZeroParticipants[0];
                this.setYScaleForIndex(p.ai, p.minY, p.maxY);
                axisSeriesMap[p.ai].forEach((si) => {
                    minYArr[si] = gl.yAxisScale[p.ai].niceMin;
                    maxYArr[si] = gl.yAxisScale[p.ai].niceMax;
                });
            }
        }
    }
    class Range {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
            this.scales = new Scales(this.w);
        }
        init() {
            this.setYRange();
            this.setXRange();
            this.setZRange();
        }
        /**
         * @param {number} startingSeriesIndex
         * @param {number | null} [endingSeriesIndex]
         */
        getMinYMaxY(startingSeriesIndex, lowestY = Number.MAX_VALUE, highestY = -Number.MAX_VALUE, endingSeriesIndex = null) {
            var _a, _b, _c, _d, _e;
            const cnf = this.w.config;
            const gl = this.w.globals;
            let maxY = -Number.MAX_VALUE;
            let minY = Number.MIN_VALUE;
            if (endingSeriesIndex === null) {
                endingSeriesIndex = startingSeriesIndex + 1;
            }
            const series = this.w.seriesData.series;
            let seriesMin = series;
            let seriesMax = series;
            if (cnf.chart.type === "candlestick") {
                seriesMin = this.w.candleData.seriesCandleL;
                seriesMax = this.w.candleData.seriesCandleH;
            } else if (cnf.chart.type === "boxPlot") {
                seriesMin = this.w.candleData.seriesCandleO;
                seriesMax = this.w.candleData.seriesCandleC;
            } else if (this.w.axisFlags.isRangeData) {
                seriesMin = this.w.rangeData.seriesRangeStart;
                seriesMax = this.w.rangeData.seriesRangeEnd;
            }
            let autoScaleYaxis = false;
            if (this.w.seriesData.seriesX.length >= endingSeriesIndex) {
                const brush = (
                    /** @type {any} */
                    (_a = gl.brushSource) == null ? void 0 : _a.w.config.chart.brush
                );
                if (cnf.chart.zoom.enabled && cnf.chart.zoom.autoScaleYaxis || (brush == null ? void 0 : brush.enabled) && (brush == null ? void 0 : brush.autoScaleYaxis)) {
                    autoScaleYaxis = true;
                }
            }
            for (let i = startingSeriesIndex; i < endingSeriesIndex; i++) {
                gl.dataPoints = Math.max(gl.dataPoints, series[i].length);
                const seriesType = (
                    /** @type {Record<string,any>} */
                    cnf.series[i].type
                );
                if (this.w.labelData.categoryLabels.length) {
                    gl.dataPoints = this.w.labelData.categoryLabels.filter(
                        (label) => typeof label !== "undefined"
                    ).length;
                }
                if (this.w.labelData.labels.length && cnf.xaxis.type !== "datetime" &&
                    /**
                     * @param {number} a
                     * @param {number[]} c
                     */
                    this.w.seriesData.series.reduce((a, c) => a + c.length, 0) !== 0) {
                    gl.dataPoints = Math.max(gl.dataPoints, this.w.labelData.labels.length);
                }
                let firstXIndex = 0;
                let lastXIndex = series[i].length - 1;
                if (autoScaleYaxis) {
                    if (cnf.xaxis.min) {
                        for (; firstXIndex < lastXIndex && this.w.seriesData.seriesX[i][firstXIndex] < cnf.xaxis.min; firstXIndex++) {}
                    }
                    if (cnf.xaxis.max) {
                        for (; lastXIndex > firstXIndex && this.w.seriesData.seriesX[i][lastXIndex] > cnf.xaxis.max; lastXIndex--) {}
                    }
                }
                for (let j = firstXIndex; j <= lastXIndex && j < this.w.seriesData.series[i].length; j++) {
                    let val = series[i][j];
                    if (val !== null && Utils$1.isNumber(val)) {
                        if (typeof((_b = seriesMax[i]) == null ? void 0 : _b[j]) !== "undefined") {
                            maxY = Math.max(maxY, seriesMax[i][j]);
                            lowestY = Math.min(lowestY, seriesMax[i][j]);
                        }
                        if (typeof((_c = seriesMin[i]) == null ? void 0 : _c[j]) !== "undefined") {
                            lowestY = Math.min(lowestY, seriesMin[i][j]);
                            highestY = Math.max(highestY, seriesMin[i][j]);
                        }
                        switch (seriesType) {
                            case "candlestick": {
                                if (typeof this.w.candleData.seriesCandleC[i][j] !== "undefined") {
                                    maxY = Math.max(maxY, this.w.candleData.seriesCandleH[i][j]);
                                    lowestY = Math.min(
                                        lowestY,
                                        this.w.candleData.seriesCandleL[i][j]
                                    );
                                }
                            }
                            break;
                            case "boxPlot": {
                                if (typeof this.w.candleData.seriesCandleC[i][j] !== "undefined") {
                                    maxY = Math.max(maxY, this.w.candleData.seriesCandleC[i][j]);
                                    lowestY = Math.min(
                                        lowestY,
                                        this.w.candleData.seriesCandleO[i][j]
                                    );
                                }
                            }
                            break;
                        }
                        if (seriesType && seriesType !== "candlestick" && seriesType !== "boxPlot" && seriesType !== "rangeArea" && seriesType !== "rangeBar") {
                            maxY = Math.max(maxY, this.w.seriesData.series[i][j]);
                            lowestY = Math.min(lowestY, this.w.seriesData.series[i][j]);
                        }
                        if (this.w.seriesData.seriesGoals[i] && this.w.seriesData.seriesGoals[i][j] && Array.isArray(this.w.seriesData.seriesGoals[i][j])) {
                            this.w.seriesData.seriesGoals[i][j].forEach(
                                (g) => {
                                    maxY = Math.max(maxY, g.value);
                                    lowestY = Math.min(lowestY, g.value);
                                }
                            );
                        }
                        highestY = maxY;
                        val = Utils$1.noExponents(val);
                        if (Utils$1.isFloat(val)) {
                            gl.yValueDecimal = Math.max(
                                gl.yValueDecimal,
                                val.toString().split(".")[1].length
                            );
                        }
                        if (minY > ((_d = seriesMin[i]) == null ? void 0 : _d[j]) && ((_e = seriesMin[i]) == null ? void 0 : _e[j]) < 0) {
                            minY = seriesMin[i][j];
                        }
                    } else {
                        gl.hasNullValues = true;
                    }
                }
                if (seriesType === "bar" || seriesType === "column") {
                    if (minY < 0 && maxY < 0) {
                        maxY = 0;
                        highestY = Math.max(highestY, 0);
                    }
                    if (minY === Number.MIN_VALUE) {
                        minY = 0;
                        lowestY = Math.min(lowestY, 0);
                    }
                }
            }
            if (cnf.chart.type === "rangeBar" && this.w.rangeData.seriesRangeStart.length && gl.isBarHorizontal) {
                minY = lowestY;
            }
            if (cnf.chart.type === "bar") {
                if (minY < 0 && maxY < 0) {
                    maxY = 0;
                }
                if (minY === Number.MIN_VALUE) {
                    minY = 0;
                }
            }
            return {
                minY,
                maxY,
                lowestY,
                highestY
            };
        }
        setYRange() {
            const gl = this.w.globals;
            const cnf = this.w.config;
            gl.maxY = -Number.MAX_VALUE;
            gl.minY = Number.MIN_VALUE;
            let lowestYInAllSeries = Number.MAX_VALUE;
            let minYMaxY;
            if (gl.isMultipleYAxis) {
                lowestYInAllSeries = Number.MAX_VALUE;
                for (let i = 0; i < this.w.seriesData.series.length; i++) {
                    minYMaxY = this.getMinYMaxY(i);
                    gl.minYArr[i] = minYMaxY.lowestY;
                    gl.maxYArr[i] = minYMaxY.highestY;
                    lowestYInAllSeries = Math.min(lowestYInAllSeries, minYMaxY.lowestY);
                }
            }
            minYMaxY = this.getMinYMaxY(
                0,
                lowestYInAllSeries,
                void 0,
                this.w.seriesData.series.length
            );
            if (cnf.chart.type === "bar") {
                gl.minY = minYMaxY.minY;
                gl.maxY = minYMaxY.maxY;
            } else {
                gl.minY = minYMaxY.lowestY;
                gl.maxY = minYMaxY.highestY;
            }
            lowestYInAllSeries = minYMaxY.lowestY;
            if (cnf.chart.stacked) {
                this._setStackedMinMax();
            }
            if (cnf.chart.type === "line" || cnf.chart.type === "area" || cnf.chart.type === "scatter" || cnf.chart.type === "candlestick" || cnf.chart.type === "boxPlot" || cnf.chart.type === "rangeBar" && !gl.isBarHorizontal) {
                if (gl.minY === Number.MIN_VALUE && lowestYInAllSeries !== -Number.MAX_VALUE && lowestYInAllSeries !== gl.maxY) {
                    gl.minY = lowestYInAllSeries;
                }
            } else {
                gl.minY = gl.minY !== Number.MIN_VALUE ? Math.min(minYMaxY.minY, gl.minY) : minYMaxY.minY;
            }
            cnf.yaxis.forEach((yaxe, index) => {
                if (yaxe.max !== void 0) {
                    if (typeof yaxe.max === "number") {
                        gl.maxYArr[index] = yaxe.max;
                    } else if (typeof yaxe.max === "function") {
                        gl.maxYArr[index] = yaxe.max(
                            gl.isMultipleYAxis ? gl.maxYArr[index] : gl.maxY
                        );
                    }
                    gl.maxY = gl.maxYArr[index];
                }
                if (yaxe.min !== void 0) {
                    if (typeof yaxe.min === "number") {
                        gl.minYArr[index] = yaxe.min;
                    } else if (typeof yaxe.min === "function") {
                        gl.minYArr[index] = yaxe.min(
                            gl.isMultipleYAxis ? gl.minYArr[index] === Number.MIN_VALUE ? 0 : gl.minYArr[index] : gl.minY
                        );
                    }
                    gl.minY = gl.minYArr[index];
                }
            });
            if (gl.isBarHorizontal) {
                const minmax = ["min", "max"];
                minmax.forEach((m) => {
                    if (cnf.xaxis[m] !== void 0 && typeof cnf.xaxis[m] === "number") {
                        m === "min" ? gl.minY = cnf.xaxis[m] : gl.maxY = cnf.xaxis[m];
                    }
                });
            }
            if (gl.isMultipleYAxis) {
                this.scales.scaleMultipleYAxes();
                gl.minY = lowestYInAllSeries;
            } else {
                this.scales.setYScaleForIndex(0, gl.minY, gl.maxY);
                gl.minY = gl.yAxisScale[0].niceMin;
                gl.maxY = gl.yAxisScale[0].niceMax;
                gl.minYArr[0] = gl.minY;
                gl.maxYArr[0] = gl.maxY;
            }
            gl.barGroups = [];
            gl.lineGroups = [];
            gl.areaGroups = [];
            cnf.series.forEach((s) => {
                const _s = (
                    /** @type {any} */
                    s
                );
                const type = _s.type || cnf.chart.type;
                switch (type) {
                    case "bar":
                    case "column":
                        gl.barGroups.push(_s.group);
                        break;
                    case "line":
                        gl.lineGroups.push(_s.group);
                        break;
                    case "area":
                        gl.areaGroups.push(_s.group);
                        break;
                }
            });
            gl.barGroups = gl.barGroups.filter((v, i, a) => a.indexOf(v) === i);
            gl.lineGroups = gl.lineGroups.filter((v, i, a) => a.indexOf(v) === i);
            gl.areaGroups = gl.areaGroups.filter((v, i, a) => a.indexOf(v) === i);
            return {
                minY: gl.minY,
                maxY: gl.maxY,
                minYArr: gl.minYArr,
                maxYArr: gl.maxYArr,
                yAxisScale: gl.yAxisScale
            };
        }
        setXRange() {
            const gl = this.w.globals;
            const cnf = this.w.config;
            const isXNumeric = cnf.xaxis.type === "numeric" || cnf.xaxis.type === "datetime" || cnf.xaxis.type === "category" && !this.w.axisFlags.noLabelsProvided || this.w.axisFlags.noLabelsProvided || this.w.axisFlags.isXNumeric;
            const getInitialMinXMaxX = () => {
                for (let i = 0; i < this.w.seriesData.series.length; i++) {
                    if (this.w.labelData.labels[i]) {
                        for (let j = 0; j < this.w.labelData.labels[i].length; j++) {
                            if (this.w.labelData.labels[i][j] !== null && Utils$1.isNumber(this.w.labelData.labels[i][j])) {
                                gl.maxX = Math.max(
                                    gl.maxX,
                                    /** @type {number} */
                                    /** @type {any} */
                                    this.w.labelData.labels[i][j]
                                );
                                gl.initialMaxX = Math.max(
                                    gl.maxX,
                                    /** @type {number} */
                                    /** @type {any} */
                                    this.w.labelData.labels[i][j]
                                );
                                gl.minX = Math.min(
                                    gl.minX,
                                    /** @type {number} */
                                    /** @type {any} */
                                    this.w.labelData.labels[i][j]
                                );
                                gl.initialMinX = Math.min(
                                    gl.minX,
                                    /** @type {number} */
                                    /** @type {any} */
                                    this.w.labelData.labels[i][j]
                                );
                            }
                        }
                    }
                }
            };
            if (this.w.axisFlags.isXNumeric) {
                getInitialMinXMaxX();
            }
            if (this.w.axisFlags.noLabelsProvided) {
                if (cnf.xaxis.categories.length === 0) {
                    gl.maxX = /** @type {any} */
                        this.w.labelData.labels[this.w.labelData.labels.length - 1];
                    gl.initialMaxX = /** @type {any} */
                        this.w.labelData.labels[this.w.labelData.labels.length - 1];
                    gl.minX = 1;
                    gl.initialMinX = 1;
                }
            }
            if (this.w.axisFlags.isXNumeric || this.w.axisFlags.noLabelsProvided || this.w.axisFlags.dataFormatXNumeric) {
                let ticks = 10;
                if (cnf.xaxis.tickAmount === void 0) {
                    ticks = Math.round(gl.svgWidth / 150);
                    if (cnf.xaxis.type === "numeric" && gl.dataPoints < 30) {
                        ticks = gl.dataPoints - 1;
                    }
                    if (ticks > gl.dataPoints && gl.dataPoints !== 0) {
                        ticks = gl.dataPoints - 1;
                    }
                } else if (cnf.xaxis.tickAmount === "dataPoints") {
                    if (this.w.seriesData.series.length > 1) {
                        ticks = this.w.seriesData.series[gl.maxValsInArrayIndex].length - 1;
                    }
                    if (this.w.axisFlags.isXNumeric) {
                        const diff = Math.round(gl.maxX - gl.minX);
                        if (diff < 30) {
                            ticks = diff;
                        }
                    }
                } else {
                    ticks = cnf.xaxis.tickAmount;
                }
                gl.xTickAmount = ticks;
                if (cnf.xaxis.max !== void 0 && typeof cnf.xaxis.max === "number") {
                    gl.maxX = cnf.xaxis.max;
                }
                if (cnf.xaxis.min !== void 0 && typeof cnf.xaxis.min === "number") {
                    gl.minX = cnf.xaxis.min;
                }
                if (cnf.xaxis.range !== void 0) {
                    gl.minX = gl.maxX - cnf.xaxis.range;
                }
                if (gl.minX !== Number.MAX_VALUE && gl.maxX !== -Number.MAX_VALUE) {
                    if (cnf.xaxis.convertedCatToNumeric && !this.w.axisFlags.dataFormatXNumeric) {
                        const catScale = [];
                        for (let i = gl.minX - 1; i < gl.maxX; i++) {
                            catScale.push(i + 1);
                        }
                        gl.xAxisScale = {
                            result: catScale,
                            niceMin: catScale[0],
                            niceMax: catScale[catScale.length - 1]
                        };
                    } else {
                        gl.xAxisScale = this.scales.setXScale(gl.minX, gl.maxX);
                    }
                } else {
                    gl.xAxisScale = this.scales.linearScale(
                        0,
                        ticks,
                        ticks,
                        0,
                        cnf.xaxis.stepSize
                    );
                    if (this.w.axisFlags.noLabelsProvided && this.w.labelData.labels.length > 0) {
                        gl.xAxisScale = this.scales.linearScale(
                            1,
                            this.w.labelData.labels.length,
                            ticks - 1,
                            0,
                            cnf.xaxis.stepSize
                        );
                        this.w.seriesData.seriesX = /** @type {any} */
                            this.w.labelData.labels.slice();
                    }
                }
                if (isXNumeric) {
                    this.w.labelData.labels = /** @type {any} */
                        gl.xAxisScale.result.slice();
                }
            }
            if (gl.isBarHorizontal && this.w.labelData.labels.length) {
                gl.xTickAmount = this.w.labelData.labels.length;
            }
            this._handleSingleDataPoint();
            this._getMinXDiff();
            return {
                minX: gl.minX,
                maxX: gl.maxX
            };
        }
        setZRange() {
            const gl = this.w.globals;
            if (!this.w.axisFlags.isDataXYZ) return;
            for (let i = 0; i < this.w.seriesData.series.length; i++) {
                if (typeof this.w.seriesData.seriesZ[i] !== "undefined") {
                    for (let j = 0; j < this.w.seriesData.seriesZ[i].length; j++) {
                        if (this.w.seriesData.seriesZ[i][j] !== null && Utils$1.isNumber(this.w.seriesData.seriesZ[i][j])) {
                            gl.maxZ = Math.max(gl.maxZ, this.w.seriesData.seriesZ[i][j]);
                            gl.minZ = Math.min(gl.minZ, this.w.seriesData.seriesZ[i][j]);
                        }
                    }
                }
            }
        }
        _handleSingleDataPoint() {
            const gl = this.w.globals;
            const cnf = this.w.config;
            if (gl.minX === gl.maxX) {
                const datetimeObj = new DateTime(this.w);
                if (cnf.xaxis.type === "datetime") {
                    const newMinX = datetimeObj.getDate(gl.minX);
                    if (cnf.xaxis.labels.datetimeUTC) {
                        newMinX.setUTCDate(newMinX.getUTCDate() - 2);
                    } else {
                        newMinX.setDate(newMinX.getDate() - 2);
                    }
                    gl.minX = new Date(newMinX).getTime();
                    const newMaxX = datetimeObj.getDate(gl.maxX);
                    if (cnf.xaxis.labels.datetimeUTC) {
                        newMaxX.setUTCDate(newMaxX.getUTCDate() + 2);
                    } else {
                        newMaxX.setDate(newMaxX.getDate() + 2);
                    }
                    gl.maxX = new Date(newMaxX).getTime();
                } else if (cnf.xaxis.type === "numeric" || cnf.xaxis.type === "category" && !this.w.axisFlags.noLabelsProvided) {
                    gl.minX = gl.minX - 2;
                    gl.initialMinX = gl.minX;
                    gl.maxX = gl.maxX + 2;
                    gl.initialMaxX = gl.maxX;
                }
            }
        }
        _getMinXDiff() {
            const gl = this.w.globals;
            if (this.w.axisFlags.isXNumeric) {
                this.w.seriesData.seriesX.forEach((sX) => {
                    if (sX.length) {
                        if (sX.length === 1) {
                            sX.push(
                                this.w.seriesData.seriesX[gl.maxValsInArrayIndex][this.w.seriesData.seriesX[gl.maxValsInArrayIndex].length - 1]
                            );
                        }
                        const seriesX = sX.slice();
                        seriesX.sort((a, b) => a - b);
                        seriesX.forEach((s, j) => {
                            if (j > 0) {
                                const xDiff = s - seriesX[j - 1];
                                if (xDiff > 0) {
                                    gl.minXDiff = Math.min(xDiff, gl.minXDiff);
                                }
                            }
                        });
                        if (gl.dataPoints === 1 || gl.minXDiff === Number.MAX_VALUE) {
                            gl.minXDiff = 0.5;
                        }
                    }
                });
            }
        }
        _setStackedMinMax() {
            const gl = this.w.globals;
            if (!this.w.seriesData.series.length) return;
            let seriesGroups = this.w.labelData.seriesGroups;
            if (!seriesGroups.length) {
                seriesGroups = [this.w.seriesData.seriesNames.map((name2) => name2)];
            }
            const stackedPoss = {};
            const stackedNegs = {};
            seriesGroups.forEach((group) => {
                stackedPoss[group] = [];
                stackedNegs[group] = [];
                const indicesOfSeriesInGroup = this.w.config.series.map(
                    (serie, si) => group.indexOf(this.w.seriesData.seriesNames[si]) > -1 ? si : null
                ).filter((f) => f !== null);
                indicesOfSeriesInGroup.forEach((i) => {
                    var _a, _b, _c, _d;
                    for (let j = 0; j < this.w.seriesData.series[gl.maxValsInArrayIndex].length; j++) {
                        if (typeof stackedPoss[group][j] === "undefined") {
                            stackedPoss[group][j] = 0;
                            stackedNegs[group][j] = 0;
                        }
                        const stackSeries = this.w.config.chart.stacked && !gl.comboCharts || this.w.config.chart.stacked && gl.comboCharts && (!this.w.config.chart.stackOnlyBar || /** @type {Record<string,any>} */
                            ((_b = (_a = this.w.config.series) == null ? void 0 : _a[i]) == null ? void 0 : _b.type) === "bar" || /** @type {Record<string,any>} */
                            ((_d = (_c = this.w.config.series) == null ? void 0 : _c[i]) == null ? void 0 : _d.type) === "column");
                        if (stackSeries) {
                            if (this.w.seriesData.series[i][j] !== null && Utils$1.isNumber(this.w.seriesData.series[i][j])) {
                                this.w.seriesData.series[i][j] > 0 ? stackedPoss[group][j] += parseFloat(String(this.w.seriesData.series[i][j])) + 1e-4 : stackedNegs[group][j] += parseFloat(
                                    String(this.w.seriesData.series[i][j])
                                );
                            }
                        }
                    }
                });
            });
            Object.entries(stackedPoss).forEach(([key]) => {
                stackedPoss[key].forEach(
                    (_, stgi) => {
                        gl.maxY = Math.max(gl.maxY, stackedPoss[key][stgi]);
                        gl.minY = Math.min(gl.minY, stackedNegs[key][stgi]);
                    }
                );
            });
        }
    }

    function getThemePalettes() {
        return {
            // All colours pass WCAG 1.4.11 non-text contrast (≥ 3:1) against the
            // default light (#fff) and dark (#293450) theme backgrounds.
            palette1: ["#008FFB", "#00A86F", "#CA8501", "#FF4560", "#846DD5"],
            palette2: ["#6978CB", "#039DE2", "#49A84D", "#B39105", "#D68000"],
            palette3: ["#209FCC", "#648291", "#D4526E", "#0FA783", "#A19285"],
            palette4: ["#2FA59D", "#73A20B", "#099DE1", "#FD5D5D", "#648291"],
            palette5: ["#2B908F", "#F56566", "#2EAB16", "#FA4443", "#1EA2BD"],
            palette6: ["#449DD1", "#F86624", "#EA3A4A", "#9C63D1", "#899E2A"],
            palette7: ["#DF475B", "#1B998B", "#7E75B7", "#F46036", "#B1911B"],
            palette8: ["#9C63D1", "#F86624", "#B38F04", "#EA3A4A", "#2FA2B3"],
            palette9: ["#98776F", "#A19285", "#A8705E", "#BA6560", "#A0927F"],
            palette10: ["#C91EFF", "#A94BFD", "#6C6AFE", "#2983FF", "#009ED8"],
            // CVD-safe palettes (Wong 2011 / IBM design)
            cvdDeuteranopia: [
                "#0072B2",
                "#E69F00",
                "#56B4E9",
                "#009E73",
                "#F0E442",
                "#D55E00",
                "#CC79A7"
            ],
            cvdProtanopia: [
                "#0077BB",
                "#EE7733",
                "#009988",
                "#EE3377",
                "#BBBBBB",
                "#33BBEE",
                "#CC3311"
            ],
            cvdTritanopia: [
                "#CC3311",
                "#009988",
                "#EE7733",
                "#0077BB",
                "#EE3377",
                "#BBBBBB",
                "#33BBEE"
            ],
            highContrast: [
                "#005A9C",
                "#C00000",
                "#007A33",
                "#6C3483",
                "#7B3F00",
                "#0097A7",
                "#4A235A"
            ]
        };
    }
    class YAxis {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {any} [elgrid]
         */
        constructor(w, {
            theme = null,
            timeScale = null
        } = {}, elgrid) {
            this.w = w;
            this.elgrid = elgrid;
            this.xaxisFontSize = w.config.xaxis.labels.style.fontSize;
            this.axisFontFamily = w.config.xaxis.labels.style.fontFamily;
            this.xaxisForeColors = w.config.xaxis.labels.style.colors;
            this.isCategoryBarHorizontal = w.config.chart.type === "bar" && w.config.plotOptions.bar.horizontal;
            this.xAxisoffX = w.config.xaxis.position === "bottom" ? w.layout.gridHeight : 0;
            this.drawnLabels = [];
            this.axesUtils = new AxesUtils(w, {
                theme,
                timeScale
            });
        }
        /**
         * @param {number} realIndex
         */
        drawYaxis(realIndex) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const yaxisStyle = w.config.yaxis[realIndex].labels.style;
            const {
                fontSize: yaxisFontSize,
                fontFamily: yaxisFontFamily,
                fontWeight: yaxisFontWeight
            } = yaxisStyle;
            const elYaxis = graphics.group({
                class: "apexcharts-yaxis",
                rel: realIndex,
                transform: `translate(${w.globals.translateYAxisX[realIndex]}, 0)`
            });
            if (this.axesUtils.isYAxisHidden(realIndex)) return elYaxis;
            const elYaxisTexts = graphics.group({
                class: "apexcharts-yaxis-texts-g"
            });
            elYaxis.add(elYaxisTexts);
            const tickAmount = w.globals.yAxisScale[realIndex].result.length - 1;
            const labelsDivider = w.layout.gridHeight / tickAmount;
            const lbFormatter = w.formatters.yLabelFormatters[realIndex];
            const labels = this.axesUtils.checkForReversedLabels(
                realIndex,
                w.globals.yAxisScale[realIndex].result.slice()
            );
            if (w.config.yaxis[realIndex].labels.show) {
                let lY = w.layout.translateY + w.config.yaxis[realIndex].labels.offsetY;
                if (w.globals.isBarHorizontal) lY = 0;
                else if (w.config.chart.type === "heatmap") lY -= labelsDivider / 2;
                lY += parseInt(yaxisFontSize, 10) / 3;
                let firstLabel = null;
                for (let i = tickAmount; i >= 0; i--) {
                    const val = lbFormatter(labels[i], i, w);
                    let xPad = w.config.yaxis[realIndex].labels.padding;
                    if (w.config.yaxis[realIndex].opposite && w.config.yaxis.length !== 0)
                        xPad *= -1;
                    const textAnchor = this.getTextAnchor(
                        w.config.yaxis[realIndex].labels.align,
                        w.config.yaxis[realIndex].opposite
                    );
                    const yColors = this.axesUtils.getYAxisForeColor(
                        yaxisStyle.colors,
                        realIndex
                    );
                    const foreColor = Array.isArray(yColors) ? yColors[i] : yColors;
                    const existingYLabels = Array.from(
                        w.dom.baseEl.querySelectorAll(
                            `.apexcharts-yaxis[rel='${realIndex}'] .apexcharts-yaxis-label tspan`
                        )
                    ).map((label2) => label2.textContent);
                    const label = graphics.drawText({
                        x: xPad,
                        y: lY,
                        text: existingYLabels.includes(val) && !w.config.yaxis[realIndex].labels.showDuplicates ? "" : val,
                        textAnchor,
                        fontSize: yaxisFontSize,
                        fontFamily: yaxisFontFamily,
                        fontWeight: yaxisFontWeight,
                        maxWidth: w.config.yaxis[realIndex].labels.maxWidth,
                        foreColor,
                        isPlainText: false,
                        cssClass: `apexcharts-yaxis-label ${yaxisStyle.cssClass}`
                    });
                    elYaxisTexts.add(label);
                    this.addTooltip(label, val);
                    if (firstLabel === null) {
                        firstLabel = label;
                    }
                    if (w.config.yaxis[realIndex].labels.rotate !== 0) {
                        this.rotateLabel(
                            graphics,
                            label,
                            firstLabel,
                            w.config.yaxis[realIndex].labels.rotate
                        );
                    }
                    lY += labelsDivider;
                }
            }
            this.addYAxisTitle(graphics, elYaxis, realIndex);
            this.addAxisBorder(graphics, elYaxis, realIndex, tickAmount, labelsDivider);
            return elYaxis;
        }
        /**
         * @param {string} align
         * @param {boolean} opposite
         */
        getTextAnchor(align, opposite) {
            if (align === "left") return "start";
            if (align === "center") return "middle";
            if (align === "right") return "end";
            return opposite ? "start" : "end";
        }
        /**
         * @param {any} label
         * @param {any} val
         */
        addTooltip(label, val) {
            const elTooltipTitle = BrowserAPIs.createElementNS(SVGNS, "title");
            elTooltipTitle.textContent = Array.isArray(val) ? val.join(" ") : val;
            label.node.appendChild(elTooltipTitle);
        }
        /**
         * @param {import('../Graphics').default} graphics
         * @param {any} label
         * @param {any} firstLabel
         * @param {number} rotate
         */
        rotateLabel(graphics, label, firstLabel, rotate) {
            const firstLabelCenter = graphics.rotateAroundCenter(firstLabel.node);
            const labelCenter = graphics.rotateAroundCenter(label.node);
            label.node.setAttribute(
                "transform",
                `rotate(${rotate} ${firstLabelCenter.x} ${labelCenter.y})`
            );
        }
        /**
         * @param {import('../Graphics').default} graphics
         * @param {any} elYaxis
         * @param {number} realIndex
         */
        addYAxisTitle(graphics, elYaxis, realIndex) {
            const w = this.w;
            if (w.config.yaxis[realIndex].title.text !== void 0) {
                const elYaxisTitle = graphics.group({
                    class: "apexcharts-yaxis-title"
                });
                const x = w.config.yaxis[realIndex].opposite ? w.globals.translateYAxisX[realIndex] : 0;
                const elYAxisTitleText = graphics.drawText({
                    x,
                    y: w.layout.gridHeight / 2 + w.layout.translateY + w.config.yaxis[realIndex].title.offsetY,
                    text: w.config.yaxis[realIndex].title.text,
                    textAnchor: "end",
                    foreColor: w.config.yaxis[realIndex].title.style.color,
                    fontSize: w.config.yaxis[realIndex].title.style.fontSize,
                    fontWeight: w.config.yaxis[realIndex].title.style.fontWeight,
                    fontFamily: w.config.yaxis[realIndex].title.style.fontFamily,
                    cssClass: `apexcharts-yaxis-title-text ${w.config.yaxis[realIndex].title.style.cssClass}`
                });
                elYaxisTitle.add(elYAxisTitleText);
                elYaxis.add(elYaxisTitle);
            }
        }
        /**
         * @param {import('../Graphics').default} graphics
         * @param {any} elYaxis
         * @param {number} realIndex
         * @param {number} tickAmount
         * @param {number} labelsDivider
         */
        addAxisBorder(graphics, elYaxis, realIndex, tickAmount, labelsDivider) {
            const w = this.w;
            const axisBorder = w.config.yaxis[realIndex].axisBorder;
            let x = 31 + axisBorder.offsetX;
            if (w.config.yaxis[realIndex].opposite) x = -31 - axisBorder.offsetX;
            if (axisBorder.show) {
                const elVerticalLine = graphics.drawLine(
                    x,
                    w.layout.translateY + axisBorder.offsetY - 2,
                    x,
                    w.layout.gridHeight + w.layout.translateY + axisBorder.offsetY + 2,
                    axisBorder.color,
                    0,
                    axisBorder.width
                );
                elYaxis.add(elVerticalLine);
            }
            if (w.config.yaxis[realIndex].axisTicks.show) {
                this.axesUtils.drawYAxisTicks(
                    x,
                    tickAmount,
                    axisBorder,
                    w.config.yaxis[realIndex].axisTicks,
                    realIndex,
                    labelsDivider,
                    elYaxis
                );
            }
        }
        /**
         * @param {number} realIndex
         */
        drawYaxisInversed(realIndex) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const elXaxis = graphics.group({
                class: "apexcharts-xaxis apexcharts-yaxis-inversed"
            });
            const elXaxisTexts = graphics.group({
                class: "apexcharts-xaxis-texts-g",
                transform: `translate(${w.layout.translateXAxisX}, ${w.layout.translateXAxisY})`
            });
            elXaxis.add(elXaxisTexts);
            let tickAmount = w.globals.yAxisScale[realIndex].result.length - 1;
            const labelsDivider = w.layout.gridWidth / tickAmount + 0.1;
            let l = labelsDivider + w.config.xaxis.labels.offsetX;
            const lbFormatter = w.formatters.xLabelFormatter;
            let labels = this.axesUtils.checkForReversedLabels(
                realIndex,
                w.globals.yAxisScale[realIndex].result.slice()
            );
            const timescaleLabels = w.labelData.timescaleLabels;
            if (timescaleLabels.length > 0) {
                this.xaxisLabels = timescaleLabels.slice();
                labels = timescaleLabels.slice();
                tickAmount = labels.length;
            }
            if (w.config.xaxis.labels.show) {
                for (let i = timescaleLabels.length ? 0 : tickAmount; timescaleLabels.length ? i < timescaleLabels.length : i >= 0; timescaleLabels.length ? i++ : i--) {
                    let val = lbFormatter == null ? void 0 : lbFormatter(labels[i], i, w);
                    let x = w.layout.gridWidth + w.globals.padHorizontal - (l - labelsDivider + w.config.xaxis.labels.offsetX);
                    if (timescaleLabels.length) {
                        const label = this.axesUtils.getLabel(
                            labels,
                            timescaleLabels,
                            x,
                            i,
                            this.drawnLabels,
                            this.xaxisFontSize
                        );
                        x = label.x;
                        val = label.text;
                        this.drawnLabels.push(label.text);
                        if (i === 0 && w.globals.skipFirstTimelinelabel) val = "";
                        if (i === labels.length - 1 && w.globals.skipLastTimelinelabel)
                            val = "";
                    }
                    const elTick = graphics.drawText({
                        x,
                        y: this.xAxisoffX + w.config.xaxis.labels.offsetY + 30 - (w.config.xaxis.position === "top" ? w.layout.xAxisHeight + w.config.xaxis.axisTicks.height - 2 : 0),
                        text: val,
                        textAnchor: "middle",
                        foreColor: Array.isArray(this.xaxisForeColors) ? this.xaxisForeColors[realIndex] : this.xaxisForeColors,
                        fontSize: this.xaxisFontSize,
                        fontFamily: this.axisFontFamily,
                        fontWeight: w.config.xaxis.labels.style.fontWeight,
                        isPlainText: false,
                        cssClass: `apexcharts-xaxis-label ${w.config.xaxis.labels.style.cssClass}`
                    });
                    elXaxisTexts.add(elTick);
                    this.addTooltip(elTick, val);
                    l += labelsDivider;
                }
            }
            this.inversedYAxisTitleText(elXaxis);
            this.inversedYAxisBorder(elXaxis);
            return elXaxis;
        }
        /**
         * @param {any} parent
         */
        inversedYAxisBorder(parent) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const axisBorder = w.config.xaxis.axisBorder;
            if (axisBorder.show) {
                let lineCorrection = 0;
                if (w.config.chart.type === "bar" && w.axisFlags.isXNumeric)
                    lineCorrection -= 15;
                const elHorzLine = graphics.drawLine(
                    w.globals.padHorizontal + lineCorrection + axisBorder.offsetX,
                    this.xAxisoffX,
                    w.layout.gridWidth,
                    this.xAxisoffX,
                    axisBorder.color,
                    0,
                    axisBorder.height
                );
                if (this.elgrid && this.elgrid.elGridBorders && w.config.grid.show) {
                    this.elgrid.elGridBorders.add(elHorzLine);
                } else {
                    parent.add(elHorzLine);
                }
            }
        }
        /**
         * @param {any} parent
         */
        inversedYAxisTitleText(parent) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            if (w.config.xaxis.title.text !== void 0) {
                const elYaxisTitle = graphics.group({
                    class: "apexcharts-xaxis-title apexcharts-yaxis-title-inversed"
                });
                const elYAxisTitleText = graphics.drawText({
                    x: w.layout.gridWidth / 2 + w.config.xaxis.title.offsetX,
                    y: this.xAxisoffX + parseFloat(this.xaxisFontSize) + parseFloat(w.config.xaxis.title.style.fontSize) + w.config.xaxis.title.offsetY + 20,
                    text: w.config.xaxis.title.text,
                    textAnchor: "middle",
                    fontSize: w.config.xaxis.title.style.fontSize,
                    fontFamily: w.config.xaxis.title.style.fontFamily,
                    fontWeight: w.config.xaxis.title.style.fontWeight,
                    foreColor: w.config.xaxis.title.style.color,
                    cssClass: `apexcharts-xaxis-title-text ${w.config.xaxis.title.style.cssClass}`
                });
                elYaxisTitle.add(elYAxisTitleText);
                parent.add(elYaxisTitle);
            }
        }
        /**
         * @param {number} realIndex
         * @param {boolean} yAxisOpposite
         */
        yAxisTitleRotate(realIndex, yAxisOpposite) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const elYAxisLabelsWrap = w.dom.baseEl.querySelector(
                `.apexcharts-yaxis[rel='${realIndex}'] .apexcharts-yaxis-texts-g`
            );
            const yAxisLabelsCoord = elYAxisLabelsWrap ? elYAxisLabelsWrap.getBoundingClientRect() : {
                width: 0,
                height: 0
            };
            const yAxisTitle = w.dom.baseEl.querySelector(
                `.apexcharts-yaxis[rel='${realIndex}'] .apexcharts-yaxis-title text`
            );
            const yAxisTitleCoord = yAxisTitle ? yAxisTitle.getBoundingClientRect() : {
                width: 0,
                height: 0
            };
            if (yAxisTitle) {
                const x = this.xPaddingForYAxisTitle(
                    realIndex,
                    yAxisLabelsCoord,
                    yAxisTitleCoord,
                    yAxisOpposite
                );
                yAxisTitle.setAttribute("x", String(x.xPos - (yAxisOpposite ? 10 : 0)));
                const titleRotatingCenter = graphics.rotateAroundCenter(yAxisTitle);
                yAxisTitle.setAttribute(
                    "transform",
                    `rotate(${yAxisOpposite ? w.config.yaxis[realIndex].title.rotate * -1 : w.config.yaxis[realIndex].title.rotate} ${titleRotatingCenter.x} ${titleRotatingCenter.y})`
                );
            }
        }
        /**
         * @param {number} realIndex
         * @param {{width: number, height: number}} yAxisLabelsCoord
         * @param {{width: number, height: number}} yAxisTitleCoord
         * @param {boolean} yAxisOpposite
         */
        xPaddingForYAxisTitle(realIndex, yAxisLabelsCoord, yAxisTitleCoord, yAxisOpposite) {
            const w = this.w;
            let x = 0;
            let padd = 10;
            if (w.config.yaxis[realIndex].title.text === void 0 || realIndex < 0) {
                return {
                    xPos: x,
                    padd: 0
                };
            }
            if (yAxisOpposite) {
                x = yAxisLabelsCoord.width + w.config.yaxis[realIndex].title.offsetX + yAxisTitleCoord.width / 2 + padd / 2;
            } else {
                x = yAxisLabelsCoord.width * -1 + w.config.yaxis[realIndex].title.offsetX + padd / 2 + yAxisTitleCoord.width / 2;
                if (w.globals.isBarHorizontal) {
                    padd = 25;
                    x = yAxisLabelsCoord.width * -1 - w.config.yaxis[realIndex].title.offsetX - padd;
                }
            }
            return {
                xPos: x,
                padd
            };
        }
        /**
         * @param {Array<{width: number, height: number}>} yaxisLabelCoords
         * @param {Array<{width: number, height: number}>} yTitleCoords
         */
        setYAxisXPosition(yaxisLabelCoords, yTitleCoords) {
            const w = this.w;
            let xLeft = 0;
            let xRight = 0;
            let leftOffsetX = 18;
            let rightOffsetX = 1;
            if (w.config.yaxis.length > 1) this.multipleYs = true;
            w.config.yaxis.forEach((yaxe, index) => {
                const shouldNotDrawAxis = w.globals.ignoreYAxisIndexes.includes(index) || !yaxe.show || yaxe.floating || yaxisLabelCoords[index].width === 0;
                const axisWidth = yaxisLabelCoords[index].width + yTitleCoords[index].width;
                if (!yaxe.opposite) {
                    xLeft = w.layout.translateX - leftOffsetX;
                    if (!shouldNotDrawAxis) leftOffsetX += axisWidth + 20;
                    w.globals.translateYAxisX[index] = xLeft + yaxe.labels.offsetX;
                } else {
                    if (w.globals.isBarHorizontal) {
                        xRight = w.layout.gridWidth + w.layout.translateX - 1;
                        w.globals.translateYAxisX[index] = xRight - yaxe.labels.offsetX;
                    } else {
                        xRight = w.layout.gridWidth + w.layout.translateX + rightOffsetX;
                        if (!shouldNotDrawAxis) rightOffsetX += axisWidth + 20;
                        w.globals.translateYAxisX[index] = xRight - yaxe.labels.offsetX + 20;
                    }
                }
            });
        }
        setYAxisTextAlignments() {
            const w = this.w;
            const yaxis = Array.from(
                w.dom.baseEl.getElementsByClassName("apexcharts-yaxis")
            );
            yaxis.forEach((y, index) => {
                const yaxe = w.config.yaxis[index];
                if (yaxe && !yaxe.floating && yaxe.labels.align !== void 0) {
                    const yAxisInner = w.dom.baseEl.querySelector(
                        `.apexcharts-yaxis[rel='${index}'] .apexcharts-yaxis-texts-g`
                    );
                    const yAxisTexts = Array.from(
                        w.dom.baseEl.querySelectorAll(
                            `.apexcharts-yaxis[rel='${index}'] .apexcharts-yaxis-label`
                        )
                    );
                    const rect = (
                        /** @type {Element} */
                        yAxisInner.getBoundingClientRect()
                    );
                    yAxisTexts.forEach((label) => {
                        label.setAttribute("text-anchor", yaxe.labels.align);
                    });
                    if (yaxe.labels.align === "left" && !yaxe.opposite) {
                        yAxisInner.setAttribute(
                            "transform",
                            `translate(-${rect.width}, 0)`
                        );
                    } else if (yaxe.labels.align === "center") {
                        yAxisInner.setAttribute(
                            "transform",
                            `translate(${rect.width / 2 * (!yaxe.opposite ? -1 : 1)}, 0)`
                        );
                    } else if (yaxe.labels.align === "right" && yaxe.opposite) {
                        yAxisInner.setAttribute(
                            "transform",
                            `translate(${rect.width}, 0)`
                        );
                    }
                }
            });
        }
    }
    class Events {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this.documentEvent = this.documentEvent.bind(this);
        }
        /**
         * @param {string} name
         * @param {Function} handler
         */
        addEventListener(name2, handler) {
            const w = this.w;
            if (Object.prototype.hasOwnProperty.call(w.globals.events, name2)) {
                w.globals.events[name2].push(handler);
            } else {
                w.globals.events[name2] = [handler];
            }
        }
        /**
         * @param {string} name
         * @param {Function} handler
         */
        removeEventListener(name2, handler) {
            const w = this.w;
            if (!Object.prototype.hasOwnProperty.call(w.globals.events, name2)) {
                return;
            }
            const index = (
                /** @type {Record<string,any>} */
                w.globals.events[name2].indexOf(handler)
            );
            if (index !== -1) {
                w.globals.events[name2].splice(
                    index,
                    1
                );
            }
        }
        /**
         * @param {string} name
         * @param {any[]} args
         */
        fireEvent(name2, args) {
            const w = this.w;
            if (!Object.prototype.hasOwnProperty.call(w.globals.events, name2)) {
                return;
            }
            if (!args || !args.length) {
                args = [];
            }
            const evs = (
                /** @type {Record<string,any>} */
                w.globals.events[name2]
            );
            const l = evs.length;
            for (let i = 0; i < l; i++) {
                evs[i].apply(null, args);
            }
        }
        setupEventHandlers() {
            const w = this.w;
            const me = this.ctx;
            const clickableArea = w.dom.baseEl.querySelector(w.globals.chartClass);
            this.ctx.eventList.forEach((event) => {
                clickableArea == null ? void 0 : clickableArea.addEventListener(
                    event,
                    (e) => {
                        const capturedSeriesIndex = e.target.getAttribute("i") === null && w.interact.capturedSeriesIndex !== -1 ? w.interact.capturedSeriesIndex : e.target.getAttribute("i");
                        const capturedDataPointIndex = e.target.getAttribute("j") === null && w.interact.capturedDataPointIndex !== -1 ? w.interact.capturedDataPointIndex : e.target.getAttribute("j");
                        const opts = Object.assign({}, w, {
                            seriesIndex: w.globals.axisCharts ? capturedSeriesIndex : 0,
                            dataPointIndex: capturedDataPointIndex
                        });
                        if (e.type === "keydown") {
                            if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.keyboard.enabled) {
                                if (me.ctx.keyboardNavigation) {
                                    me.ctx.keyboardNavigation.handleKey(e);
                                }
                                if (typeof w.config.chart.events.keyDown === "function") {
                                    w.config.chart.events.keyDown(e, me, opts);
                                }
                                me.ctx.events.fireEvent("keydown", [e, me, opts]);
                            }
                        } else if (e.type === "keyup") {
                            if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.keyboard.enabled) {
                                if (typeof w.config.chart.events.keyUp === "function") {
                                    w.config.chart.events.keyUp(e, me, opts);
                                }
                                me.ctx.events.fireEvent("keyup", [e, me, opts]);
                            }
                        } else if (e.type === "mousemove" || e.type === "touchmove") {
                            if (typeof w.config.chart.events.mouseMove === "function") {
                                w.config.chart.events.mouseMove(e, me, opts);
                            }
                        } else if (e.type === "mouseleave" || e.type === "touchleave") {
                            if (typeof w.config.chart.events.mouseLeave === "function") {
                                w.config.chart.events.mouseLeave(e, me, opts);
                            }
                        } else if (e.type === "mouseup" && e.which === 1 || e.type === "touchend") {
                            if (typeof w.config.chart.events.click === "function") {
                                w.config.chart.events.click(e, me, opts);
                            }
                            me.ctx.events.fireEvent("click", [e, me, opts]);
                        }
                    }, {
                        capture: false,
                        passive: true
                    }
                );
            });
            this.ctx.eventList.forEach((event) => {
                w.dom.baseEl.addEventListener(event, this.documentEvent, {
                    passive: true
                });
            });
            this.ctx.core.setupBrushHandler();
        }
        /**
         * @param {any} e
         */
        documentEvent(e) {
            const w = this.w;
            const target = e.target.className;
            if (e.type === "click") {
                const elMenu = w.dom.baseEl.querySelector(".apexcharts-menu");
                if (elMenu && elMenu.classList.contains("apexcharts-menu-open") && target !== "apexcharts-menu-icon") {
                    elMenu.classList.remove("apexcharts-menu-open");
                }
            }
            w.interact.clientX = e.type === "touchmove" ? e.touches[0].clientX : e.clientX;
            w.interact.clientY = e.type === "touchmove" ? e.touches[0].clientY : e.clientY;
        }
    }
    class Localization {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
        }
        /**
         * @param {string} localeName
         */
        setCurrentLocaleValues(localeName) {
            let locales = this.w.config.chart.locales;
            const globalApex = Environment.getApex();
            if (globalApex.chart && globalApex.chart.locales && globalApex.chart.locales.length > 0) {
                locales = this.w.config.chart.locales.concat(globalApex.chart.locales);
            }
            const selectedLocale = locales.filter(
                (c) => c.name === localeName
            )[0];
            if (selectedLocale) {
                const ret = Utils$1.extend(en, selectedLocale);
                this.w.globals.locale = ret.options;
            } else {
                throw new Error(
                    "Wrong locale name provided. Please make sure you set the correct locale name in options"
                );
            }
        }
    }
    class Axes {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {import('../../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
        }
        /**
         * @param {string} type
         * @param {any} elgrid
         */
        drawAxis(type, elgrid) {
            const gl = this.w.globals;
            const cnf = this.w.config;
            const xAxis = new XAxis(this.w, this.ctx, elgrid);
            const yAxis = new YAxis(this.w, {
                theme: this.ctx.theme,
                timeScale: this.ctx.timeScale
            }, elgrid);
            if (gl.axisCharts && type !== "radar") {
                let elXaxis, elYaxis;
                if (gl.isBarHorizontal) {
                    elYaxis = yAxis.drawYaxisInversed(0);
                    elXaxis = xAxis.drawXaxisInversed(0);
                    this.w.dom.elGraphical.add(elXaxis);
                    this.w.dom.elGraphical.add(elYaxis);
                } else {
                    elXaxis = xAxis.drawXaxis();
                    this.w.dom.elGraphical.add(elXaxis);
                    cnf.yaxis.map((yaxe, index) => {
                        if (gl.ignoreYAxisIndexes.indexOf(index) === -1) {
                            elYaxis = yAxis.drawYaxis(index);
                            this.w.dom.Paper.add(elYaxis);
                            if (this.w.config.grid.position === "back") {
                                const inner = this.w.dom.Paper.children()[1];
                                if (inner) {
                                    inner.remove();
                                    this.w.dom.Paper.add(inner);
                                }
                            }
                        }
                    });
                }
            }
        }
    }
    class Crosshairs {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
        }
        drawXCrosshairs() {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const filters = new Filters(this.w);
            const crosshairGradient = w.config.xaxis.crosshairs.fill.gradient;
            const crosshairShadow = w.config.xaxis.crosshairs.dropShadow;
            const fillType = w.config.xaxis.crosshairs.fill.type;
            const gradientFrom = crosshairGradient.colorFrom;
            const gradientTo = crosshairGradient.colorTo;
            const opacityFrom = crosshairGradient.opacityFrom;
            const opacityTo = crosshairGradient.opacityTo;
            const stops = crosshairGradient.stops;
            const shadow = "none";
            const dropShadow = crosshairShadow.enabled;
            const shadowLeft = crosshairShadow.left;
            const shadowTop = crosshairShadow.top;
            const shadowBlur = crosshairShadow.blur;
            const shadowColor = crosshairShadow.color;
            const shadowOpacity = crosshairShadow.opacity;
            let xcrosshairsFill = w.config.xaxis.crosshairs.fill.color;
            if (w.config.xaxis.crosshairs.show) {
                if (fillType === "gradient") {
                    xcrosshairsFill = graphics.drawGradient(
                        "vertical",
                        gradientFrom,
                        gradientTo,
                        opacityFrom,
                        opacityTo,
                        null,
                        stops,
                        []
                    );
                }
                let xcrosshairs = graphics.drawRect();
                if (w.config.xaxis.crosshairs.width === 1) {
                    xcrosshairs = graphics.drawLine(0, 0, 0, 0);
                }
                let gridHeight = w.layout.gridHeight;
                if (!Utils$1.isNumber(gridHeight) || gridHeight < 0) {
                    gridHeight = 0;
                }
                let crosshairsWidth = w.config.xaxis.crosshairs.width;
                if (!Utils$1.isNumber(crosshairsWidth) || Number(crosshairsWidth) < 0) {
                    crosshairsWidth = 0;
                }
                xcrosshairs.attr({
                    class: "apexcharts-xcrosshairs",
                    x: 0,
                    y: 0,
                    y2: gridHeight,
                    width: crosshairsWidth,
                    height: gridHeight,
                    fill: xcrosshairsFill,
                    filter: shadow,
                    "fill-opacity": w.config.xaxis.crosshairs.opacity,
                    stroke: w.config.xaxis.crosshairs.stroke.color,
                    "stroke-width": w.config.xaxis.crosshairs.stroke.width,
                    "stroke-dasharray": w.config.xaxis.crosshairs.stroke.dashArray
                });
                if (dropShadow) {
                    xcrosshairs = filters.dropShadow(xcrosshairs, {
                        left: shadowLeft,
                        top: shadowTop,
                        blur: shadowBlur,
                        color: shadowColor,
                        opacity: shadowOpacity
                    });
                }
                w.dom.elGraphical.add(xcrosshairs);
            }
        }
        drawYCrosshairs() {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const crosshair = (
                /** @type {any[]} */
                w.config.yaxis[0].crosshairs
            );
            const offX = w.globals.barPadForNumericAxis;
            if (
                /** @type {any[]} */
                w.config.yaxis[0].crosshairs.show
            ) {
                const ycrosshairs = graphics.drawLine(
                    -offX,
                    0,
                    w.layout.gridWidth + offX,
                    0,
                    crosshair.stroke.color,
                    crosshair.stroke.dashArray,
                    crosshair.stroke.width
                );
                ycrosshairs.attr({
                    class: "apexcharts-ycrosshairs"
                });
                w.dom.elGraphical.add(ycrosshairs);
            }
            const ycrosshairsHidden = graphics.drawLine(
                -offX,
                0,
                w.layout.gridWidth + offX,
                0,
                crosshair.stroke.color,
                0,
                0
            );
            ycrosshairsHidden.attr({
                class: "apexcharts-ycrosshairs-hidden"
            });
            w.dom.elGraphical.add(ycrosshairsHidden);
        }
    }

    function mergeYaxisOverride(base, override) {
        if (!Utils$1.isObject(base) || !Utils$1.isObject(override)) {
            return override !== void 0 ? override : base;
        }
        const out = __spreadValues({}, base);
        for (const key of Object.keys(override)) {
            const v = override[key];
            if (v === void 0) continue;
            if (Utils$1.isObject(v) && Utils$1.isObject(base[key])) {
                out[key] = mergeYaxisOverride(base[key], v);
            } else {
                out[key] = v;
            }
        }
        return out;
    }
    class Responsive {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
            this._activeBreakpoint = null;
        }
        // the opts parameter if not null has to be set overriding everything
        // as the opts is set by user externally
        /**
         * @param {object} opts
         */
        checkResponsiveConfig(opts) {
            const w = this.w;
            const cnf = w.config;
            if (cnf.responsive.length === 0) return;
            const res = cnf.responsive.slice();
            res.sort(
                (a, b) => a.breakpoint > b.breakpoint ? 1 : b.breakpoint > a.breakpoint ? -1 : 0
            ).reverse();
            const config = new Config({});
            const iterateResponsiveOptions = (newOptions = {}) => {
                var _a;
                const largestBreakpoint = res[0].breakpoint;
                const width = Environment.isBrowser() ? window.innerWidth > 0 ? window.innerWidth : screen.width : 0;
                if (width > largestBreakpoint) {
                    if (this._activeBreakpoint !== null) {
                        if (!w.globals.initialConfig) return;
                        const initialConfig = Utils$1.clone(w.globals.initialConfig);
                        initialConfig.series = Utils$1.clone(w.config.series);
                        const options2 = CoreUtils.extendArrayProps(config, initialConfig, w);
                        newOptions = Utils$1.extend(options2, newOptions);
                        this.overrideResponsiveOptions(newOptions);
                        this._activeBreakpoint = null;
                    }
                } else {
                    for (let i = 0; i < res.length; i++) {
                        if (width < res[i].breakpoint) {
                            const originalUserYaxis = ((_a = res[i].options) == null ? void 0 : _a.yaxis) ? Utils$1.clone(res[i].options.yaxis) : null;
                            newOptions = CoreUtils.extendArrayProps(config, res[i].options, w);
                            newOptions = Utils$1.extend(w.config, newOptions);
                            if (Array.isArray(w.config.yaxis) && originalUserYaxis) {
                                const userYaxis = Array.isArray(originalUserYaxis) ? originalUserYaxis : [originalUserYaxis];
                                newOptions = __spreadProps(__spreadValues({}, newOptions), {
                                    yaxis: w.config.yaxis.map(
                                        (baseAxis, idx) => mergeYaxisOverride(baseAxis, userYaxis[idx])
                                    )
                                });
                            }
                            this.overrideResponsiveOptions(newOptions);
                            this._activeBreakpoint = res[i].breakpoint;
                        }
                    }
                }
            };
            if (opts) {
                let options2 = CoreUtils.extendArrayProps(config, opts, w);
                options2 = Utils$1.extend(w.config, options2);
                options2 = Utils$1.extend(options2, opts);
                iterateResponsiveOptions(options2);
            } else {
                iterateResponsiveOptions({});
            }
        }
        /**
         * @param {Record<string, any>} newOptions
         */
        overrideResponsiveOptions(newOptions) {
            const newConfig = new Config(newOptions).init({
                responsiveOverride: true
            });
            this.w.config = /** @type {any} */
                newConfig;
        }
    }
    class Series {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {{ toggleDataSeries?: Function, revertDefaultAxisMinMax?: Function, updateSeries?: Function }} [callbacks]
         */
        constructor(w, {
            toggleDataSeries = void 0,
            revertDefaultAxisMinMax = void 0,
            updateSeries = void 0
        } = {}) {
            this.w = w;
            this._toggleDataSeries = toggleDataSeries || null;
            this._revertDefaultAxisMinMax = revertDefaultAxisMinMax || null;
            this._updateSeries = updateSeries || null;
            this.legendInactiveClass = "legend-mouseover-inactive";
        }
        clearSeriesCache() {
            const w = this.w;
            if (w.globals.cachedSelectors) {
                delete w.globals.cachedSelectors.allSeriesEls;
                delete w.globals.cachedSelectors.highlightSeriesEls;
            }
        }
        getAllSeriesEls() {
            const w = this.w;
            const cacheKey = "allSeriesEls";
            if (!w.globals.cachedSelectors[cacheKey]) {
                w.globals.cachedSelectors[cacheKey] = /** @type {any} */
                    w.dom.baseEl.getElementsByClassName(`apexcharts-series`);
            }
            return w.globals.cachedSelectors[cacheKey];
        }
        /**
         * @param {string} seriesName
         */
        getSeriesByName(seriesName) {
            return this.w.dom.baseEl.querySelector(
                `.apexcharts-inner .apexcharts-series[seriesName='${Utils$1.escapeString(
          seriesName
        )}']`
            );
        }
        /**
         * @param {string} seriesName
         */
        isSeriesHidden(seriesName) {
            var _a;
            const targetElement = this.getSeriesByName(seriesName);
            const el = (
                /** @type {Element} */
                targetElement
            );
            const realIndex = parseInt((_a = el.getAttribute("data:realIndex")) != null ? _a : "0", 10);
            const isHidden = el.classList.contains("apexcharts-series-collapsed");
            return {
                isHidden,
                realIndex
            };
        }
        /**
         * @param {any} elSeries
         * @param {number} index
         */
        addCollapsedClassToSeries(elSeries, index) {
            Series.addCollapsedClassToSeries(this.w, elSeries, index);
        }
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {any} elSeries
         * @param {number} index
         */
        static addCollapsedClassToSeries(w, elSeries, index) {
            function iterateOnAllCollapsedSeries(series) {
                for (let cs = 0; cs < series.length; cs++) {
                    if (series[cs].index === index) {
                        elSeries.node.classList.add("apexcharts-series-collapsed");
                    }
                }
            }
            iterateOnAllCollapsedSeries(w.globals.collapsedSeries);
            iterateOnAllCollapsedSeries(w.globals.ancillaryCollapsedSeries);
        }
        /**
         * @param {string} seriesName
         */
        toggleSeries(seriesName) {
            var _a;
            const isSeriesHidden = this.isSeriesHidden(seriesName);
            (_a = this._toggleDataSeries) == null ? void 0 : _a.call(this, isSeriesHidden.realIndex, isSeriesHidden.isHidden);
            return isSeriesHidden.isHidden;
        }
        /**
         * @param {string} seriesName
         */
        showSeries(seriesName) {
            var _a;
            const isSeriesHidden = this.isSeriesHidden(seriesName);
            if (isSeriesHidden.isHidden) {
                (_a = this._toggleDataSeries) == null ? void 0 : _a.call(this, isSeriesHidden.realIndex, true);
            }
        }
        /**
         * @param {string} seriesName
         */
        hideSeries(seriesName) {
            var _a;
            const isSeriesHidden = this.isSeriesHidden(seriesName);
            if (!isSeriesHidden.isHidden) {
                (_a = this._toggleDataSeries) == null ? void 0 : _a.call(this, isSeriesHidden.realIndex, false);
            }
        }
        resetSeries(shouldUpdateChart = true, shouldResetZoom = true, shouldResetCollapsed = true) {
            var _a, _b;
            const w = this.w;
            this.clearSeriesCache();
            let series = Utils$1.clone(w.globals.initialSeries);
            w.globals.previousPaths = [];
            if (shouldResetCollapsed) {
                w.globals.collapsedSeries = [];
                w.globals.ancillaryCollapsedSeries = [];
                w.globals.collapsedSeriesIndices = [];
                w.globals.ancillaryCollapsedSeriesIndices = [];
            } else {
                series = this.emptyCollapsedSeries(series);
            }
            w.config.series = series;
            if (shouldUpdateChart) {
                if (shouldResetZoom) {
                    w.interact.zoomed = false;
                    (_a = this._revertDefaultAxisMinMax) == null ? void 0 : _a.call(this);
                }
                (_b = this._updateSeries) == null ? void 0 : _b.call(
                    this,
                    series,
                    w.config.chart.animations.dynamicAnimation.enabled
                );
            }
        }
        /**
         * @param {any[]} series
         */
        emptyCollapsedSeries(series) {
            const w = this.w;
            for (let i = 0; i < series.length; i++) {
                if (w.globals.collapsedSeriesIndices.indexOf(i) > -1) {
                    series[i].data = [];
                }
            }
            return series;
        }
        /**
         * @param {string} seriesName
         */
        highlightSeries(seriesName) {
            var _a;
            const w = this.w;
            const targetElement = this.getSeriesByName(seriesName);
            const realIndex = parseInt(
                (_a = targetElement == null ? void 0 : targetElement.getAttribute("data:realIndex")) != null ? _a : "",
                10
            );
            const cacheKey = "highlightSeriesEls";
            let allSeriesEls = w.globals.cachedSelectors[cacheKey];
            if (!allSeriesEls) {
                allSeriesEls = w.dom.baseEl.querySelectorAll(
                    `.apexcharts-series, .apexcharts-datalabels, .apexcharts-yaxis`
                );
                w.globals.cachedSelectors[cacheKey] = allSeriesEls;
            }
            let seriesEl = null;
            let dataLabelEl = null;
            let yaxisEl = null;
            if (w.globals.axisCharts || w.config.chart.type === "radialBar") {
                if (w.globals.axisCharts) {
                    seriesEl = w.dom.baseEl.querySelector(
                        `.apexcharts-series[data\\:realIndex='${realIndex}']`
                    );
                    dataLabelEl = w.dom.baseEl.querySelector(
                        `.apexcharts-datalabels[data\\:realIndex='${realIndex}']`
                    );
                    const yaxisIndex = w.globals.seriesYAxisReverseMap[realIndex];
                    yaxisEl = w.dom.baseEl.querySelector(
                        `.apexcharts-yaxis[rel='${yaxisIndex}']`
                    );
                } else {
                    seriesEl = w.dom.baseEl.querySelector(
                        `.apexcharts-series[rel='${realIndex + 1}']`
                    );
                }
            } else {
                seriesEl = w.dom.baseEl.querySelector(
                    `.apexcharts-series[rel='${realIndex + 1}'] path`
                );
            }
            for (let se = 0; se < allSeriesEls.length; se++) {
                const serEl = (
                    /** @type {Element} */
                    allSeriesEls[se]
                );
                serEl.classList.add(this.legendInactiveClass);
            }
            if (seriesEl) {
                if (!w.globals.axisCharts) {
                    const parentEl = (
                        /** @type {Element} */
                        seriesEl.parentNode
                    );
                    parentEl == null ? void 0 : parentEl.classList.remove(this.legendInactiveClass);
                }
                seriesEl.classList.remove(this.legendInactiveClass);
                if (dataLabelEl !== null) {
                    dataLabelEl.classList.remove(this.legendInactiveClass);
                }
                if (yaxisEl !== null) {
                    yaxisEl.classList.remove(this.legendInactiveClass);
                }
            } else {
                for (let se = 0; se < allSeriesEls.length; se++) {
                    const serEl = (
                        /** @type {Element} */
                        allSeriesEls[se]
                    );
                    serEl.classList.remove(this.legendInactiveClass);
                }
            }
        }
        /**
         * @param {Event} e
         * @param {any} targetElement
         */
        toggleSeriesOnHover(e, targetElement) {
            const w = this.w;
            if (!targetElement) targetElement = e.target;
            const allSeriesEls = w.dom.baseEl.querySelectorAll(
                `.apexcharts-series, .apexcharts-datalabels, .apexcharts-yaxis`
            );
            if (e.type === "mousemove") {
                const realIndex = parseInt(targetElement.getAttribute("rel"), 10) - 1;
                this.highlightSeries(w.seriesData.seriesNames[realIndex]);
            } else if (e.type === "mouseout") {
                for (let se = 0; se < allSeriesEls.length; se++) {
                    allSeriesEls[se].classList.remove(this.legendInactiveClass);
                }
            }
        }
        /**
         * Dim every heatmap cell except those whose value falls inside the color
         * range at `rangeIndex`. Shared by the categorical legend (hover a legend
         * item) and the gradient legend (hover a band) — both supply an index into
         * `colorScale.ranges` plus an action, decoupling the highlight from any
         * particular DOM element / event shape.
         *
         * @param {number} rangeIndex index into `colorScale.ranges`
         * @param {'highlight'|'reset'} action
         */
        highlightRangeInSeries(rangeIndex, action) {
            const w = this.w;
            const allHeatMapElements = w.dom.baseEl.getElementsByClassName(
                "apexcharts-heatmap-rect"
            );
            const toggleAllInactive = (op) => {
                for (let i = 0; i < allHeatMapElements.length; i++) {
                    const classList = (
                        /** @type {any} */
                        allHeatMapElements[i].classList
                    );
                    if (typeof classList[op] === "function") {
                        classList[op](this.legendInactiveClass);
                    }
                }
            };
            if (action === "reset") {
                toggleAllInactive("remove");
                return;
            }
            const ranges = w.config.plotOptions.heatmap.colorScale.ranges;
            const range = ranges && ranges[rangeIndex];
            if (!range) return;
            toggleAllInactive("add");
            for (let i = 0; i < allHeatMapElements.length; i++) {
                const val = Number(allHeatMapElements[i].getAttribute("val"));
                if (val >= range.from && val <= range.to) {
                    allHeatMapElements[i].classList.remove(this.legendInactiveClass);
                }
            }
        }
        /**
         * @param {string[]} chartTypes
         */
        getActiveConfigSeriesIndex(order = "asc", chartTypes = []) {
            const w = this.w;
            let activeIndex = 0;
            if (w.config.series.length > 1) {
                const activeSeriesIndex = w.config.series.map((s, index) => {
                    const checkChartType = () => {
                        if (w.globals.comboCharts) {
                            return chartTypes.length === 0 || chartTypes.length && chartTypes.indexOf(
                                /** @type {Record<string,any>} */
                                w.config.series[index].type
                            ) > -1;
                        }
                        return true;
                    };
                    const hasData = (
                        /** @type {any} */
                        s.data && /** @type {any} */
                        s.data.length > 0 && w.globals.collapsedSeriesIndices.indexOf(index) === -1
                    );
                    return hasData && checkChartType() ? index : -1;
                });
                for (let a = order === "asc" ? 0 : activeSeriesIndex.length - 1; order === "asc" ? a < activeSeriesIndex.length : a >= 0; order === "asc" ? a++ : a--) {
                    if (activeSeriesIndex[a] !== -1) {
                        activeIndex = activeSeriesIndex[a];
                        break;
                    }
                }
            }
            return activeIndex;
        }
        getBarSeriesIndices() {
            const w = this.w;
            if (w.globals.comboCharts) {
                return this.w.config.series.map((s, i) => {
                    return s.type === "bar" || s.type === "column" ? i : -1;
                }).filter((i) => {
                    return i !== -1;
                });
            }
            return this.w.config.series.map((s, i) => {
                return i;
            });
        }
        getPreviousPaths() {
            var _a, _b, _c, _d;
            const w = this.w;
            if (!w.globals.axisCharts) {
                w.globals.previousPaths = w.seriesData.series;
                return;
            }
            w.globals.previousPaths = [];

            function pushPaths(seriesEls, i, type) {
                const paths = seriesEls[i].childNodes;
                const dArr = {
                    type,
                    paths: (
                        /** @type {any[]} */
                        []
                    ),
                    realIndex: seriesEls[i].getAttribute("data:realIndex")
                };
                for (let j = 0; j < paths.length; j++) {
                    if (paths[j].hasAttribute("pathTo")) {
                        const d = paths[j].getAttribute("pathTo");
                        dArr.paths.push({
                            d
                        });
                    }
                }
                w.globals.previousPaths.push(dArr);
            }
            const getPaths = (chartType) => {
                return w.dom.baseEl.querySelectorAll(
                    `.apexcharts-${chartType}-series .apexcharts-series`
                );
            };
            const chartTypes = [
                "line",
                "area",
                "bar",
                "rangebar",
                "rangeArea",
                "candlestick",
                "radar"
            ];
            chartTypes.forEach((type) => {
                const paths = getPaths(type);
                for (let p = 0; p < paths.length; p++) {
                    pushPaths(paths, p, type);
                }
            });
            const heatTreeSeries = w.dom.baseEl.querySelectorAll(
                `.apexcharts-${w.config.chart.type} .apexcharts-series`
            );
            if (heatTreeSeries.length > 0) {
                for (let h = 0; h < heatTreeSeries.length; h++) {
                    const seriesEls = w.dom.baseEl.querySelectorAll(
                        `.apexcharts-${w.config.chart.type} .apexcharts-series[data\\:realIndex='${h}'] rect`
                    );
                    const dArr = [];
                    for (let i = 0; i < seriesEls.length; i++) {
                        const getAttr = (x) => {
                            return (
                                /** @type {Element} */
                                seriesEls[i].getAttribute(x)
                            );
                        };
                        const rect = {
                            x: parseFloat((_a = getAttr("x")) != null ? _a : "0"),
                            y: parseFloat((_b = getAttr("y")) != null ? _b : "0"),
                            width: parseFloat((_c = getAttr("width")) != null ? _c : "0"),
                            height: parseFloat((_d = getAttr("height")) != null ? _d : "0")
                        };
                        dArr.push({
                            rect,
                            color: seriesEls[i].getAttribute("color")
                        });
                    }
                    w.globals.previousPaths.push(dArr);
                }
            }
        }
        clearPreviousPaths() {
            const w = this.w;
            w.globals.previousPaths = [];
            w.globals.allSeriesCollapsed = false;
        }
        handleNoData() {
            const w = this.w;
            const me = this;
            const noDataOpts = w.config.noData;
            const graphics = new Graphics(me.w);
            let x = w.globals.svgWidth / 2;
            let y = w.globals.svgHeight / 2;
            let textAnchor = "middle";
            w.globals.noData = true;
            w.globals.animationEnded = true;
            if (noDataOpts.align === "left") {
                x = 10;
                textAnchor = "start";
            } else if (noDataOpts.align === "right") {
                x = w.globals.svgWidth - 10;
                textAnchor = "end";
            }
            if (noDataOpts.verticalAlign === "top") {
                y = 50;
            } else if (noDataOpts.verticalAlign === "bottom") {
                y = w.globals.svgHeight - 50;
            }
            x = x + noDataOpts.offsetX;
            y = y + parseInt(noDataOpts.style.fontSize, 10) + 2 + noDataOpts.offsetY;
            if (noDataOpts.text !== void 0 && noDataOpts.text !== "") {
                const titleText = graphics.drawText({
                    x,
                    y,
                    text: noDataOpts.text,
                    textAnchor,
                    fontSize: noDataOpts.style.fontSize,
                    fontFamily: noDataOpts.style.fontFamily,
                    foreColor: noDataOpts.style.color,
                    opacity: 1,
                    cssClass: "apexcharts-text-nodata"
                });
                w.dom.Paper.add(titleText);
            }
        }
        // When user clicks on legends, the collapsed series is filled with [0,0,0,...,0]
        // This is because we don't want to alter the series' length as it is used at many places
        /**
         * @param {any[]} series
         */
        setNullSeriesToZeroValues(series) {
            const w = this.w;
            for (let sl = 0; sl < series.length; sl++) {
                if (series[sl].length === 0) {
                    for (let j = 0; j < series[w.globals.maxValsInArrayIndex].length; j++) {
                        series[sl].push(0);
                    }
                }
            }
            return series;
        }
        hasAllSeriesEqualX() {
            let equalLen = true;
            const w = this.w;
            const filteredSerX = this.filteredSeriesX();
            for (let i = 0; i < filteredSerX.length - 1; i++) {
                if (filteredSerX[i][0] !== filteredSerX[i + 1][0]) {
                    equalLen = false;
                    break;
                }
            }
            w.globals.allSeriesHasEqualX = equalLen;
            return equalLen;
        }
        filteredSeriesX() {
            const w = this.w;
            const filteredSeriesX = w.seriesData.seriesX.map(
                (ser) => ser.length > 0 ? ser : []
            );
            return filteredSeriesX;
        }
    }
    class Theme {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
            this.colors = [];
            this.isColorFn = false;
            this.isHeatmapDistributed = this.checkHeatmapDistributed();
            this.isBarDistributed = this.checkBarDistributed();
        }
        checkHeatmapDistributed() {
            const {
                chart,
                plotOptions
            } = this.w.config;
            return chart.type === "treemap" && plotOptions.treemap && plotOptions.treemap.distributed || chart.type === "heatmap" && plotOptions.heatmap && plotOptions.heatmap.distributed;
        }
        checkBarDistributed() {
            const {
                chart,
                plotOptions
            } = this.w.config;
            return plotOptions.bar && plotOptions.bar.distributed && (chart.type === "bar" || chart.type === "rangeBar");
        }
        init() {
            this.setDefaultColors();
        }
        setDefaultColors() {
            var _a;
            const w = this.w;
            const utils = new Utils$1();
            w.dom.elWrap.classList.add(
                `apexcharts-theme-${w.config.theme.mode || "light"}`
            );
            const colorBlindMode = (_a = w.config.theme.accessibility) == null ? void 0 : _a.colorBlindMode;
            if (colorBlindMode) {
                w.globals.colors = this.getColorBlindColors(colorBlindMode);
                this.applySeriesColors(w.seriesData.seriesColors, w.globals.colors);
                const defaultColors2 = w.globals.colors.slice();
                this.pushExtraColors(w.globals.colors);
                this.applyColorTypes(["fill", "stroke"], defaultColors2);
                this.applyDataLabelsColors(defaultColors2);
                this.applyRadarPolygonsColors();
                this.applyMarkersColors(defaultColors2);
                if (colorBlindMode === "highContrast") {
                    w.dom.elWrap.classList.add("apexcharts-high-contrast");
                }
                return;
            }
            const configColors = [...w.config.colors || w.config.fill.colors || []];
            w.globals.colors = this.getColors(configColors);
            this.applySeriesColors(w.seriesData.seriesColors, w.globals.colors);
            if (w.config.theme.monochrome.enabled) {
                w.globals.colors = this.getMonochromeColors(
                    w.config.theme.monochrome,
                    w.seriesData.series,
                    utils
                );
            }
            const defaultColors = w.globals.colors.slice();
            this.pushExtraColors(w.globals.colors);
            this.applyColorTypes(["fill", "stroke"], defaultColors);
            this.applyDataLabelsColors(defaultColors);
            this.applyRadarPolygonsColors();
            this.applyMarkersColors(defaultColors);
        }
        /**
         * @param {any[]} configColors
         */
        getColors(configColors) {
            const w = this.w;
            if (!configColors || configColors.length === 0) {
                return this.predefined();
            }
            if (Array.isArray(configColors) && configColors.length > 0 && typeof configColors[0] === "function") {
                this.isColorFn = true;
                return w.config.series.map((s, i) => {
                    const c = configColors[i] || configColors[0];
                    return typeof c === "function" ? c({
                        value: w.globals.axisCharts ? w.seriesData.series[i][0] || 0 : w.seriesData.series[i],
                        seriesIndex: i,
                        dataPointIndex: i,
                        w: this.w
                    }) : c;
                });
            }
            return configColors;
        }
        /**
         * @param {any[]} seriesColors
         * @param {any[]} globalsColors
         */
        applySeriesColors(seriesColors, globalsColors) {
            seriesColors.forEach((c, i) => {
                if (c) {
                    globalsColors[i] = c;
                }
            });
        }
        /**
         * @param {Record<string, any>} monochrome
         * @param {any[]} series
         * @param {any} utils
         */
        getMonochromeColors(monochrome, series, utils) {
            const {
                color,
                shadeIntensity,
                shadeTo
            } = monochrome;
            const glsCnt = this.isBarDistributed || this.isHeatmapDistributed ? series[0].length * series.length : series.length;
            const part = 1 / (glsCnt / shadeIntensity);
            let percent = 0;
            return Array.from({
                length: glsCnt
            }, () => {
                const newColor = shadeTo === "dark" ? utils.shadeColor(percent * -1, color) : utils.shadeColor(percent, color);
                percent += part;
                return newColor;
            });
        }
        /**
         * @param {string[]} colorTypes
         * @param {string[]} defaultColors
         */
        applyColorTypes(colorTypes, defaultColors) {
            const w = this.w;
            colorTypes.forEach((c) => {
                w.globals[c].colors = w.config[c].colors === void 0 ? this.isColorFn ? w.config.colors : defaultColors : w.config[c].colors.slice();
                this.pushExtraColors(
                    /** @type {Record<string,any>} */
                    w.globals[c].colors
                );
            });
        }
        /**
         * @param {string[]} defaultColors
         */
        applyDataLabelsColors(defaultColors) {
            const w = this.w;
            w.globals.dataLabels.style.colors = w.config.dataLabels.style.colors === void 0 ? defaultColors : w.config.dataLabels.style.colors.slice();
            this.pushExtraColors(w.globals.dataLabels.style.colors, 50);
        }
        applyRadarPolygonsColors() {
            const w = this.w;
            w.globals.radarPolygons.fill.colors = w.config.plotOptions.radar.polygons.fill.colors === void 0 ? [w.config.theme.mode === "dark" ? "#343A3F" : "none"] : w.config.plotOptions.radar.polygons.fill.colors.slice();
            this.pushExtraColors(w.globals.radarPolygons.fill.colors, 20);
        }
        /**
         * @param {string[]} defaultColors
         */
        applyMarkersColors(defaultColors) {
            const w = this.w;
            w.globals.markers.colors = w.config.markers.colors === void 0 ? defaultColors : w.config.markers.colors.slice();
            this.pushExtraColors(w.globals.markers.colors);
        }
        /**
         * @param {any} colorSeries
         * @param {number} [length]
         * @param {boolean | null} [distributed]
         */
        pushExtraColors(colorSeries, length, distributed = null) {
            const w = this.w;
            let len = length || w.seriesData.series.length;
            if (distributed === null) {
                distributed = this.isBarDistributed || this.isHeatmapDistributed || w.config.chart.type === "heatmap" && w.config.plotOptions.heatmap && w.config.plotOptions.heatmap.colorScale.inverse;
            }
            if (distributed && w.seriesData.series.length) {
                len = w.seriesData.series[w.globals.maxValsInArrayIndex].length * w.seriesData.series.length;
            }
            if (colorSeries.length < len) {
                const diff = len - colorSeries.length;
                for (let i = 0; i < diff; i++) {
                    colorSeries.push(colorSeries[i]);
                }
            }
        }
        /**
         * @param {'light' | 'dark'} mode
         */
        getColorBlindColors(mode) {
            const palettes = getThemePalettes();
            const map = {
                deuteranopia: palettes.cvdDeuteranopia,
                protanopia: palettes.cvdProtanopia,
                tritanopia: palettes.cvdTritanopia,
                highContrast: palettes.highContrast
            };
            return (
                /** @type {Record<string,any>} */
                /** @type {any} */
                (map[mode] || palettes.palette1).slice()
            );
        }
        /**
         * @param {Record<string, any>} options
         */
        updateThemeOptions(options2) {
            options2.chart = options2.chart || {};
            options2.tooltip = options2.tooltip || {};
            const mode = options2.theme.mode;
            const palette = mode === "dark" ? "palette4" : mode === "light" ? "palette1" : options2.theme.palette || "palette1";
            const foreColor = mode === "dark" ? "#f6f7f8" : mode === "light" ? "#373d3f" : options2.chart.foreColor || "#373d3f";
            options2.tooltip.theme = mode || "light";
            options2.chart.foreColor = foreColor;
            options2.theme.palette = palette;
            return options2;
        }
        predefined() {
            const palette = this.w.config.theme.palette;
            const palettes = getThemePalettes();
            return (
                /** @type {Record<string,any>} */
                palettes[palette] || palettes.palette1
            );
        }
    }
    class TitleSubtitle {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
        }
        draw() {
            this.drawTitleSubtitle("title");
            this.drawTitleSubtitle("subtitle");
        }
        /**
         * @param {'title' | 'subtitle'} type
         */
        drawTitleSubtitle(type) {
            const w = this.w;
            const tsConfig = type === "title" ? w.config.title : w.config.subtitle;
            let x = w.globals.svgWidth / 2;
            let y = tsConfig.offsetY;
            let textAnchor = "middle";
            if (tsConfig.align === "left") {
                x = 10;
                textAnchor = "start";
            } else if (tsConfig.align === "right") {
                x = w.globals.svgWidth - 10;
                textAnchor = "end";
            }
            x = x + tsConfig.offsetX;
            y = y + parseInt(tsConfig.style.fontSize, 10) + tsConfig.margin / 2;
            if (tsConfig.text !== void 0) {
                const graphics = new Graphics(this.w);
                const titleText = graphics.drawText({
                    x,
                    y,
                    text: tsConfig.text,
                    textAnchor,
                    fontSize: tsConfig.style.fontSize,
                    fontFamily: tsConfig.style.fontFamily,
                    fontWeight: tsConfig.style.fontWeight,
                    foreColor: tsConfig.style.color,
                    opacity: 1
                });
                titleText.node.setAttribute("class", `apexcharts-${type}-text`);
                w.dom.Paper.add(titleText);
            }
        }
    }
    let Helpers$4 = class Helpers {
        /**
         * @param {import('./Dimensions').default} dCtx
         */
        constructor(dCtx) {
            this.w = dCtx.w;
            this.dCtx = dCtx;
        }
        /**
         * Get Chart Title/Subtitle Dimensions
         * @memberof Dimensions
         * @return {{width: number, height: number}}
         * @param {string} type
         **/
        getTitleSubtitleCoords(type) {
            const w = this.w;
            let width = 0;
            let height = 0;
            const floating = type === "title" ? w.config.title.floating : w.config.subtitle.floating;
            const el = w.dom.baseEl.querySelector(`.apexcharts-${type}-text`);
            if (el !== null && !floating) {
                const coord = el.getBoundingClientRect();
                width = coord.width;
                height = w.globals.axisCharts ? coord.height + 5 : coord.height;
            }
            return {
                width,
                height
            };
        }
        getLegendsRect() {
            const w = this.w;
            const elLegendWrap = w.dom.elLegendWrap;
            if (!w.config.legend.height && (w.config.legend.position === "top" || w.config.legend.position === "bottom")) {
                if (elLegendWrap)
                    elLegendWrap.style.maxHeight = w.globals.svgHeight / 2 + "px";
            }
            const lgRect = (
                /** @type {any} */
                Object.assign({}, Utils$1.getBoundingClientRect(elLegendWrap))
            );
            if (elLegendWrap !== null && !w.config.legend.floating && w.config.legend.show) {
                this.dCtx.lgRect = {
                    x: lgRect.x,
                    y: lgRect.y,
                    height: lgRect.height,
                    width: lgRect.height === 0 ? 0 : lgRect.width
                };
            } else {
                this.dCtx.lgRect = {
                    x: 0,
                    y: 0,
                    height: 0,
                    width: 0
                };
            }
            if (w.config.legend.position === "left" || w.config.legend.position === "right") {
                if (this.dCtx.lgRect.width * 1.5 > w.globals.svgWidth) {
                    this.dCtx.lgRect.width = w.globals.svgWidth / 1.5;
                }
            }
            return this.dCtx.lgRect;
        }
        /**
         * Get Y Axis Dimensions
         * @memberof Dimensions
         * @return {{width: number, height: number}}
         **/
        getDatalabelsRect() {
            const w = this.w;
            const allLabels = [];
            w.config.series.forEach(
                (serie, seriesIndex) => {
                    serie.data.forEach(
                        (datum, dataPointIndex) => {
                            const getText = (v) => {
                                return w.config.dataLabels.formatter(v, {
                                    seriesIndex,
                                    dataPointIndex,
                                    w
                                });
                            };
                            const labelText = getText(
                                w.seriesData.series[seriesIndex][dataPointIndex]
                            );
                            allLabels.push(labelText);
                        }
                    );
                }
            );
            const val = Utils$1.getLargestStringFromArr(allLabels);
            const graphics = new Graphics(this.w);
            const dataLabelsStyle = w.config.dataLabels.style;
            const labelrect = graphics.getTextRects(
                val,
                parseInt(dataLabelsStyle.fontSize).toString(),
                dataLabelsStyle.fontFamily
            );
            return {
                width: labelrect.width * 1.05,
                height: labelrect.height
            };
        }
        /**
         * @param {any} val
         * @param {any[]} arr
         */
        getLargestStringFromMultiArr(val, arr) {
            const w = this.w;
            let valArr = val;
            if (w.axisFlags.isMultiLineX) {
                const maxArrs = arr.map((xl) => {
                    return Array.isArray(xl) ? xl.length : 1;
                });
                const maxArrLen = Math.max(...maxArrs);
                const maxArrIndex = maxArrs.indexOf(maxArrLen);
                valArr = arr[maxArrIndex];
            }
            return valArr;
        }
    };
    class DimXAxis {
        /**
         * @param {import('./Dimensions').default} dCtx
         */
        constructor(dCtx) {
            this.w = dCtx.w;
            this.dCtx = dCtx;
        }
        /**
         * Get X Axis Dimensions
         * @memberof Dimensions
         * @return {{width: number, height: number}}
         **/
        getxAxisLabelsCoords() {
            const w = this.w;
            let xaxisLabels = w.labelData.labels.slice();
            if (w.config.xaxis.convertedCatToNumeric && xaxisLabels.length === 0) {
                xaxisLabels = w.labelData.categoryLabels;
            }
            let rect;
            if (w.labelData.timescaleLabels.length > 0) {
                const coords = this.getxAxisTimeScaleLabelsCoords();
                rect = {
                    width: coords.width,
                    height: coords.height
                };
                w.layout.rotateXLabels = false;
            } else {
                this.dCtx.lgWidthForSideLegends = (w.config.legend.position === "left" || w.config.legend.position === "right") && !w.config.legend.floating ? this.dCtx.lgRect.width : 0;
                const xlbFormatter = w.formatters.xLabelFormatter;
                let val = Utils$1.getLargestStringFromArr(xaxisLabels);
                let valArr = this.dCtx.dimHelpers.getLargestStringFromMultiArr(
                    val,
                    xaxisLabels
                );
                if (w.globals.isBarHorizontal) {
                    val = w.globals.yAxisScale[0].result.reduce(
                        (a, b) => a.length > b.length ? a : b,
                        0
                    );
                    valArr = val;
                }
                const xFormat = new Formatters(this.w);
                const timestamp = val;
                val = xFormat.xLabelFormat(
                    /** @type {Function} */
                    xlbFormatter,
                    val,
                    timestamp, {
                        i: void 0,
                        dateFormatter: new DateTime(this.w).formatDate,
                        w
                    }
                );
                valArr = xFormat.xLabelFormat(
                    /** @type {Function} */
                    xlbFormatter,
                    valArr,
                    timestamp, {
                        i: void 0,
                        dateFormatter: new DateTime(this.w).formatDate,
                        w
                    }
                );
                if (w.config.xaxis.convertedCatToNumeric && typeof val === "undefined" || String(val).trim() === "") {
                    val = "1";
                    valArr = val;
                }
                const graphics = new Graphics(this.w);
                let xLabelrect = graphics.getTextRects(
                    val,
                    w.config.xaxis.labels.style.fontSize
                );
                let xArrLabelrect = xLabelrect;
                if (val !== valArr) {
                    xArrLabelrect = graphics.getTextRects(
                        valArr,
                        w.config.xaxis.labels.style.fontSize
                    );
                }
                rect = {
                    width: xLabelrect.width >= xArrLabelrect.width ? xLabelrect.width : xArrLabelrect.width,
                    height: xLabelrect.height >= xArrLabelrect.height ? xLabelrect.height : xArrLabelrect.height
                };
                if (rect.width * xaxisLabels.length > w.globals.svgWidth - this.dCtx.lgWidthForSideLegends - this.dCtx.yAxisWidth - this.dCtx.gridPad.left - this.dCtx.gridPad.right && w.config.xaxis.labels.rotate !== 0 || w.config.xaxis.labels.rotateAlways) {
                    if (!w.globals.isBarHorizontal) {
                        w.layout.rotateXLabels = true;
                        const getRotatedTextRects = (text) => {
                            return graphics.getTextRects(
                                text,
                                w.config.xaxis.labels.style.fontSize,
                                w.config.xaxis.labels.style.fontFamily,
                                `rotate(${w.config.xaxis.labels.rotate} 0 0)`,
                                false
                            );
                        };
                        xLabelrect = getRotatedTextRects(val);
                        if (val !== valArr) {
                            xArrLabelrect = getRotatedTextRects(valArr);
                        }
                        rect.height = (xLabelrect.height > xArrLabelrect.height ? xLabelrect.height : xArrLabelrect.height) / 1.5;
                        rect.width = xLabelrect.width > xArrLabelrect.width ? xLabelrect.width : xArrLabelrect.width;
                    }
                } else {
                    w.layout.rotateXLabels = false;
                }
            }
            if (!w.config.xaxis.labels.show) {
                rect = {
                    width: 0,
                    height: 0
                };
            }
            return {
                width: rect.width,
                height: rect.height
            };
        }
        /**
         * Get X Axis Label Group height
         * @memberof Dimensions
         * @return {{width: number, height: number}}
         */
        getxAxisGroupLabelsCoords() {
            var _a;
            const w = this.w;
            if (!w.labelData.hasXaxisGroups) {
                return {
                    width: 0,
                    height: 0
                };
            }
            const fontSize = ((_a = w.config.xaxis.group.style) == null ? void 0 : _a.fontSize) || w.config.xaxis.labels.style.fontSize;
            const xaxisLabels = w.labelData.groups.map(
                (g) => g.title
            );
            let rect;
            const val = Utils$1.getLargestStringFromArr(xaxisLabels);
            const valArr = this.dCtx.dimHelpers.getLargestStringFromMultiArr(
                val,
                xaxisLabels
            );
            const graphics = new Graphics(this.w);
            const xLabelrect = graphics.getTextRects(val, fontSize);
            let xArrLabelrect = xLabelrect;
            if (val !== valArr) {
                xArrLabelrect = graphics.getTextRects(valArr, fontSize);
            }
            rect = {
                width: xLabelrect.width >= xArrLabelrect.width ? xLabelrect.width : xArrLabelrect.width,
                height: xLabelrect.height >= xArrLabelrect.height ? xLabelrect.height : xArrLabelrect.height
            };
            if (!w.config.xaxis.labels.show) {
                rect = {
                    width: 0,
                    height: 0
                };
            }
            return {
                width: rect.width,
                height: rect.height
            };
        }
        /**
         * Get X Axis Title Dimensions
         * @memberof Dimensions
         * @return {{width: number, height: number}}
         **/
        getxAxisTitleCoords() {
            const w = this.w;
            let width = 0;
            let height = 0;
            if (w.config.xaxis.title.text !== void 0) {
                const graphics = new Graphics(this.w);
                const rect = graphics.getTextRects(
                    w.config.xaxis.title.text,
                    w.config.xaxis.title.style.fontSize
                );
                width = rect.width;
                height = rect.height;
            }
            return {
                width,
                height
            };
        }
        getxAxisTimeScaleLabelsCoords() {
            const w = this.w;
            this.dCtx.timescaleLabels = w.labelData.timescaleLabels.slice();
            const labels = this.dCtx.timescaleLabels.map(
                (label) => label.value
            );
            const val = labels.reduce((a, b) => {
                if (typeof a === "undefined") {
                    console.error(
                        "You have possibly supplied invalid Date format. Please supply a valid JavaScript Date"
                    );
                    return 0;
                } else {
                    return a.length > b.length ? a : b;
                }
            }, 0);
            const graphics = new Graphics(this.w);
            const rect = graphics.getTextRects(
                val,
                w.config.xaxis.labels.style.fontSize
            );
            const totalWidthRotated = rect.width * 1.05 * labels.length;
            if (totalWidthRotated > w.layout.gridWidth && w.config.xaxis.labels.rotate !== 0) {
                w.globals.overlappingXLabels = true;
            }
            return rect;
        }
        // In certain cases, the last labels gets cropped in xaxis.
        // Hence, we add some additional padding based on the label length to avoid the last label being cropped or we don't draw it at all
        /**
         * @param {Record<string, any>} xaxisLabelCoords
         */
        additionalPaddingXLabels(xaxisLabelCoords) {
            const w = this.w;
            const gl = w.globals;
            const cnf = w.config;
            const xtype = cnf.xaxis.type;
            const lbWidth = xaxisLabelCoords.width;
            gl.skipLastTimelinelabel = false;
            gl.skipFirstTimelinelabel = false;
            const isBarOpposite = w.config.yaxis[0].opposite && w.globals.isBarHorizontal;
            const isCollapsed = (i) => gl.collapsedSeriesIndices.indexOf(i) !== -1;
            const rightPad = (yaxe) => {
                if (this.dCtx.timescaleLabels && this.dCtx.timescaleLabels.length) {
                    const firstimescaleLabel = this.dCtx.timescaleLabels[0];
                    const lastTimescaleLabel = this.dCtx.timescaleLabels[this.dCtx.timescaleLabels.length - 1];
                    const lastLabelPosition = lastTimescaleLabel.position + lbWidth / 1.75 - this.dCtx.yAxisWidthRight;
                    const firstLabelPosition = firstimescaleLabel.position - lbWidth / 1.75 + this.dCtx.yAxisWidthLeft;
                    const lgRightRectWidth = w.config.legend.position === "right" && this.dCtx.lgRect.width > 0 ? this.dCtx.lgRect.width : 0;
                    if (lastLabelPosition > gl.svgWidth - w.layout.translateX - lgRightRectWidth) {
                        gl.skipLastTimelinelabel = true;
                    }
                    if (firstLabelPosition < -((!yaxe.show || yaxe.floating) && (cnf.chart.type === "bar" || cnf.chart.type === "candlestick" || cnf.chart.type === "rangeBar" || cnf.chart.type === "boxPlot") ? lbWidth / 1.75 : 10)) {
                        gl.skipFirstTimelinelabel = true;
                    }
                } else if (xtype === "datetime") {
                    if (this.dCtx.gridPad.right < lbWidth && !w.layout.rotateXLabels) {
                        gl.skipLastTimelinelabel = true;
                    }
                } else if (xtype !== "datetime") {
                    if (this.dCtx.gridPad.right < lbWidth / 2 - this.dCtx.yAxisWidthRight && !w.layout.rotateXLabels && !w.config.xaxis.labels.trim) {
                        this.dCtx.xPadRight = lbWidth / 2 + 1;
                    }
                }
            };
            const padYAxe = (yaxe, i) => {
                if (cnf.yaxis.length > 1 && isCollapsed(i)) return;
                rightPad(yaxe);
            };
            cnf.yaxis.forEach((yaxe, i) => {
                if (isBarOpposite) {
                    if (this.dCtx.gridPad.left < lbWidth) {
                        this.dCtx.xPadLeft = lbWidth / 2 + 1;
                    }
                    this.dCtx.xPadRight = lbWidth / 2 + 1;
                } else {
                    padYAxe(yaxe, i);
                }
            });
        }
    }
    class DimYAxis {
        /**
         * @param {import('./Dimensions').default} dCtx
         */
        constructor(dCtx) {
            this.w = dCtx.w;
            this.dCtx = dCtx;
        }
        /**
         * Get Y Axis Dimensions
         * @memberof Dimensions
         * @returns {Array<{width: number, height: number}>}
         **/
        getyAxisLabelsCoords() {
            const w = this.w;
            const width = 0;
            const height = 0;
            const ret = [];
            let labelPad = 10;
            const axesUtils = new AxesUtils(this.w, {
                theme: this.dCtx.theme,
                timeScale: this.dCtx.timeScale
            });
            w.config.yaxis.map((yaxe, index) => {
                const formatterArgs = {
                    seriesIndex: index,
                    dataPointIndex: -1,
                    w
                };
                const yS = w.globals.yAxisScale[index];
                let yAxisMinWidth = 0;
                if (!axesUtils.isYAxisHidden(index) && yaxe.labels.show && yaxe.labels.minWidth !== void 0)
                    yAxisMinWidth = yaxe.labels.minWidth;
                if (!axesUtils.isYAxisHidden(index) && yaxe.labels.show && yS.result.length) {
                    const lbFormatter = w.formatters.yLabelFormatters[index];
                    const minV = yS.niceMin === Number.MIN_VALUE ? 0 : yS.niceMin;
                    let val = yS.result.reduce((acc, curr) => {
                        var _a, _b;
                        return ((_a = String(lbFormatter(acc, formatterArgs))) == null ? void 0 : _a.length) > ((_b = String(lbFormatter(curr, formatterArgs))) == null ? void 0 : _b.length) ? acc : curr;
                    }, minV);
                    val = lbFormatter(val, formatterArgs);
                    let valArr = val;
                    if (typeof val === "undefined" || val.length === 0) {
                        val = yS.niceMax;
                    }
                    if (String(val).length === 1) {
                        val = val + ".0";
                        valArr = val;
                    }
                    if (w.globals.isBarHorizontal) {
                        labelPad = 0;
                        const barYaxisLabels = w.labelData.labels.slice();
                        val = Utils$1.getLargestStringFromArr(barYaxisLabels);
                        val = lbFormatter(val, {
                            seriesIndex: index,
                            dataPointIndex: -1,
                            w
                        });
                        valArr = this.dCtx.dimHelpers.getLargestStringFromMultiArr(
                            val,
                            barYaxisLabels
                        );
                    }
                    const graphics = new Graphics(this.w);
                    const rotateStr = "rotate(".concat(yaxe.labels.rotate, " 0 0)");
                    const rect = graphics.getTextRects(
                        val,
                        yaxe.labels.style.fontSize,
                        yaxe.labels.style.fontFamily,
                        rotateStr,
                        false
                    );
                    let arrLabelrect = rect;
                    if (val !== valArr) {
                        arrLabelrect = graphics.getTextRects(
                            valArr,
                            yaxe.labels.style.fontSize,
                            yaxe.labels.style.fontFamily,
                            rotateStr,
                            false
                        );
                    }
                    ret.push({
                        width: (yAxisMinWidth > arrLabelrect.width || yAxisMinWidth > rect.width ? yAxisMinWidth : arrLabelrect.width > rect.width ? arrLabelrect.width : rect.width) + labelPad,
                        height: arrLabelrect.height > rect.height ? arrLabelrect.height : rect.height
                    });
                } else {
                    ret.push({
                        width,
                        height
                    });
                }
            });
            return ret;
        }
        /**
         * Get Y Axis Dimensions
         * @memberof Dimensions
         * @returns {Array<{width: number, height: number}>}
         **/
        getyAxisTitleCoords() {
            const w = this.w;
            const ret = [];
            w.config.yaxis.map((yaxe) => {
                if (yaxe.show && yaxe.title.text !== void 0) {
                    const graphics = new Graphics(this.w);
                    const rotateStr = "rotate(".concat(yaxe.title.rotate, " 0 0)");
                    const rect = graphics.getTextRects(
                        yaxe.title.text,
                        yaxe.title.style.fontSize,
                        yaxe.title.style.fontFamily,
                        rotateStr,
                        false
                    );
                    ret.push({
                        width: rect.width,
                        height: rect.height
                    });
                } else {
                    ret.push({
                        width: 0,
                        height: 0
                    });
                }
            });
            return ret;
        }
        getTotalYAxisWidth() {
            const w = this.w;
            let yAxisWidth = 0;
            let yAxisWidthLeft = 0;
            let yAxisWidthRight = 0;
            const padding = w.globals.yAxisScale.length > 1 ? 10 : 0;
            const axesUtils = new AxesUtils(this.w, {
                theme: this.dCtx.theme,
                timeScale: this.dCtx.timeScale
            });
            const isHiddenYAxis = function(index) {
                return w.globals.ignoreYAxisIndexes.indexOf(index) > -1;
            };
            const padForLabelTitle = (coord, index) => {
                const floating = w.config.yaxis[index].floating;
                let width = 0;
                if (coord.width > 0 && !floating) {
                    width = coord.width + padding;
                    if (isHiddenYAxis(index)) {
                        width = width - coord.width - padding;
                    }
                } else {
                    width = floating || axesUtils.isYAxisHidden(index) ? 0 : 5;
                }
                w.config.yaxis[index].opposite ? yAxisWidthRight = yAxisWidthRight + width : yAxisWidthLeft = yAxisWidthLeft + width;
                yAxisWidth = yAxisWidth + width;
            };
            w.layout.yLabelsCoords.map((yLabelCoord, index) => {
                padForLabelTitle(yLabelCoord, index);
            });
            w.layout.yTitleCoords.map((yTitleCoord, index) => {
                padForLabelTitle(yTitleCoord, index);
            });
            if (w.globals.isBarHorizontal && !w.config.yaxis[0].floating) {
                yAxisWidth = w.layout.yLabelsCoords[0].width + w.layout.yTitleCoords[0].width + 15;
            }
            this.dCtx.yAxisWidthLeft = yAxisWidthLeft;
            this.dCtx.yAxisWidthRight = yAxisWidthRight;
            return yAxisWidth;
        }
    }
    class DimGrid {
        /**
         * @param {import('./Dimensions').default} dCtx
         */
        constructor(dCtx) {
            this.w = dCtx.w;
            this.dCtx = dCtx;
        }
        /**
         * @param {number} gridWidth
         */
        gridPadForColumnsInNumericAxis(gridWidth) {
            const {
                w
            } = this;
            const {
                config: cnf,
                globals: gl
            } = w;
            if (gl.noData || gl.collapsedSeries.length + gl.ancillaryCollapsedSeries.length === cnf.series.length) {
                return 0;
            }
            const hasBar = (type2) => ["bar", "rangeBar", "candlestick", "boxPlot"].includes(type2);
            const type = cnf.chart.type;
            let barWidth = 0;
            let seriesLen = hasBar(type) ? cnf.series.length : 1;
            if (gl.comboBarCount > 0) {
                seriesLen = gl.comboBarCount;
            }
            gl.collapsedSeries.forEach((c) => {
                if (hasBar(c.type)) {
                    seriesLen -= 1;
                }
            });
            if (cnf.chart.stacked) {
                seriesLen = 1;
            }
            const barsPresent = hasBar(type) || gl.comboBarCount > 0;
            let xRange = Math.abs(gl.initialMaxX - gl.initialMinX);
            if (barsPresent && w.axisFlags.isXNumeric && !gl.isBarHorizontal && seriesLen > 0 && xRange !== 0) {
                if (xRange <= 3) {
                    xRange = gl.dataPoints;
                }
                const xRatio = xRange / gridWidth;
                let xDivision = gl.minXDiff && gl.minXDiff / xRatio > 0 ? gl.minXDiff / xRatio : 0;
                if (xDivision > gridWidth / 2) {
                    xDivision /= 2;
                }
                barWidth = xDivision * parseInt(cnf.plotOptions.bar.columnWidth, 10) / 100;
                if (barWidth < 1) {
                    barWidth = 1;
                }
                gl.barPadForNumericAxis = barWidth;
            }
            return barWidth;
        }
        gridPadFortitleSubtitle() {
            const {
                w
            } = this;
            const {
                globals: gl
            } = w;
            let gridShrinkOffset = this.dCtx.isSparkline || !gl.axisCharts ? 0 : 10;
            const titleSubtitle = ["title", "subtitle"];
            titleSubtitle.forEach((t) => {
                if (w.config[t].text !== void 0) {
                    gridShrinkOffset += w.config[t].margin;
                } else {
                    gridShrinkOffset += this.dCtx.isSparkline || !gl.axisCharts ? 0 : 5;
                }
            });
            if (w.config.legend.show && w.config.legend.position === "bottom" && !w.config.legend.floating && !gl.axisCharts) {
                gridShrinkOffset += 10;
            }
            const titleCoords = this.dCtx.dimHelpers.getTitleSubtitleCoords("title");
            const subtitleCoords = this.dCtx.dimHelpers.getTitleSubtitleCoords("subtitle");
            w.layout.gridHeight -= titleCoords.height + subtitleCoords.height + gridShrinkOffset;
            w.layout.translateY += titleCoords.height + subtitleCoords.height + gridShrinkOffset;
        }
        /**
         * @param {{width: number, height: number}[]} yTitleCoords
         * @param {{width: number, height: number}[]} yaxisLabelCoords
         */
        setGridXPosForDualYAxis(yTitleCoords, yaxisLabelCoords) {
            const {
                w
            } = this;
            const axesUtils = new AxesUtils(this.w, {
                theme: this.dCtx.theme,
                timeScale: this.dCtx.timeScale
            });
            w.config.yaxis.forEach((yaxe, index) => {
                if (w.globals.ignoreYAxisIndexes.indexOf(index) === -1 && !yaxe.floating && !axesUtils.isYAxisHidden(index)) {
                    if (yaxe.opposite) {
                        w.layout.translateX -= yaxisLabelCoords[index].width + yTitleCoords[index].width + parseInt(yaxe.labels.style.fontSize, 10) / 1.2 + 12;
                    }
                    if (w.layout.translateX < 2) {
                        w.layout.translateX = 2;
                    }
                }
            });
        }
    }
    class Dimensions {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {import('../../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this.theme = ctx.theme;
            this.timeScale = ctx.timeScale;
            this.lgRect = /** @type {any} */ {};
            this.yAxisWidth = 0;
            this.yAxisWidthLeft = 0;
            this.yAxisWidthRight = 0;
            this.xAxisHeight = 0;
            this.isSparkline = this.w.config.chart.sparkline.enabled;
            this.dimHelpers = new Helpers$4(this);
            this.dimYAxis = new DimYAxis(this);
            this.dimXAxis = new DimXAxis(this);
            this.dimGrid = new DimGrid(this);
            this.lgWidthForSideLegends = 0;
            this.gridPad = this.w.config.grid.padding;
            this.xPadRight = 0;
            this.xPadLeft = 0;
            this.datalabelsCoords = {
                width: 0,
                height: 0
            };
            this.xAxisWidth = 0;
            this.timescaleLabels = [];
        }
        /**
         * @memberof Dimensions
         **/
        plotCoords() {
            const w = this.w;
            const gl = w.globals;
            this.lgRect = this.dimHelpers.getLegendsRect();
            this.datalabelsCoords = {
                width: 0,
                height: 0
            };
            const maxStrokeWidth = Array.isArray(w.config.stroke.width) ? Math.max(...w.config.stroke.width) : w.config.stroke.width;
            if (this.isSparkline) {
                if (w.config.markers.discrete.length > 0 || w.config.markers.size > 0) {
                    Object.entries(this.gridPad).forEach(([k, v]) => {
                        this.gridPad[k] = Math.max(
                            v,
                            this.w.globals.markers.largestSize / 1.5
                        );
                    });
                }
                this.gridPad.top = Math.max(maxStrokeWidth / 2, this.gridPad.top);
                this.gridPad.bottom = Math.max(maxStrokeWidth / 2, this.gridPad.bottom);
            }
            if (gl.axisCharts) {
                this.setDimensionsForAxisCharts();
            } else {
                this.setDimensionsForNonAxisCharts();
            }
            this.dimGrid.gridPadFortitleSubtitle();
            w.layout.gridHeight = w.layout.gridHeight - this.gridPad.top - this.gridPad.bottom;
            w.layout.gridWidth = w.layout.gridWidth - this.gridPad.left - this.gridPad.right - this.xPadRight - this.xPadLeft;
            const barWidth = this.dimGrid.gridPadForColumnsInNumericAxis(
                w.layout.gridWidth
            );
            w.layout.gridWidth = w.layout.gridWidth - barWidth * 2;
            w.layout.translateX = w.layout.translateX + this.gridPad.left + this.xPadLeft + (barWidth > 0 ? barWidth : 0);
            w.layout.translateY = w.layout.translateY + this.gridPad.top;
            return {
                // w.layout (future slice)
                layout: {
                    gridHeight: w.layout.gridHeight,
                    gridWidth: w.layout.gridWidth,
                    translateX: w.layout.translateX,
                    translateY: w.layout.translateY,
                    translateXAxisX: w.layout.translateXAxisX,
                    translateXAxisY: w.layout.translateXAxisY,
                    rotateXLabels: w.layout.rotateXLabels,
                    xAxisHeight: w.layout.xAxisHeight,
                    xAxisLabelsHeight: w.layout.xAxisLabelsHeight,
                    xAxisGroupLabelsHeight: w.layout.xAxisGroupLabelsHeight,
                    xAxisLabelsWidth: w.layout.xAxisLabelsWidth,
                    yLabelsCoords: w.layout.yLabelsCoords,
                    yTitleCoords: w.layout.yTitleCoords
                }
            };
        }
        setDimensionsForAxisCharts() {
            const w = this.w;
            const gl = w.globals;
            const yaxisLabelCoords = this.dimYAxis.getyAxisLabelsCoords();
            const yTitleCoords = this.dimYAxis.getyAxisTitleCoords();
            if (gl.isSlopeChart) {
                this.datalabelsCoords = this.dimHelpers.getDatalabelsRect();
            }
            w.layout.yLabelsCoords = [];
            w.layout.yTitleCoords = [];
            w.config.yaxis.map((yaxe, index) => {
                w.layout.yLabelsCoords.push({
                    width: yaxisLabelCoords[index].width,
                    index
                });
                w.layout.yTitleCoords.push(
                    /** @type {any} */
                    {
                        width: yTitleCoords[index].width,
                        index
                    }
                );
            });
            this.yAxisWidth = this.dimYAxis.getTotalYAxisWidth();
            const xaxisLabelCoords = this.dimXAxis.getxAxisLabelsCoords();
            const xaxisGroupLabelCoords = this.dimXAxis.getxAxisGroupLabelsCoords();
            const xtitleCoords = this.dimXAxis.getxAxisTitleCoords();
            this.conditionalChecksForAxisCoords(
                xaxisLabelCoords,
                xtitleCoords,
                xaxisGroupLabelCoords
            );
            w.layout.translateXAxisY = w.layout.rotateXLabels ? this.xAxisHeight / 8 : -4;
            w.layout.translateXAxisX = w.layout.rotateXLabels && w.axisFlags.isXNumeric && w.config.xaxis.labels.rotate <= -45 ? -this.xAxisWidth / 4 : 0;
            if (w.globals.isBarHorizontal) {
                w.layout.rotateXLabels = false;
                w.layout.translateXAxisY = -1 * (parseInt(w.config.xaxis.labels.style.fontSize, 10) / 1.5);
            }
            w.layout.translateXAxisY = w.layout.translateXAxisY + w.config.xaxis.labels.offsetY;
            w.layout.translateXAxisX = w.layout.translateXAxisX + w.config.xaxis.labels.offsetX;
            let yAxisWidth = this.yAxisWidth;
            let xAxisHeight = this.xAxisHeight;
            w.layout.xAxisLabelsHeight = this.xAxisHeight - xtitleCoords.height;
            w.layout.xAxisGroupLabelsHeight = w.layout.xAxisLabelsHeight - xaxisLabelCoords.height;
            w.layout.xAxisLabelsWidth = this.xAxisWidth;
            w.layout.xAxisHeight = this.xAxisHeight;
            let translateY = 10;
            if (w.config.chart.type === "radar" || this.isSparkline) {
                yAxisWidth = 0;
                xAxisHeight = 0;
            }
            if (this.isSparkline) {
                this.lgRect = {
                    height: 0,
                    width: 0
                };
            }
            if (this.isSparkline || w.config.chart.type === "treemap") {
                yAxisWidth = 0;
                xAxisHeight = 0;
                translateY = 0;
            }
            if (!this.isSparkline && w.config.chart.type !== "treemap") {
                this.dimXAxis.additionalPaddingXLabels(xaxisLabelCoords);
            }
            const legendTopBottom = () => {
                w.layout.translateX = yAxisWidth + this.datalabelsCoords.width;
                w.layout.gridHeight = gl.svgHeight - this.lgRect.height - xAxisHeight - (!this.isSparkline && w.config.chart.type !== "treemap" ? w.layout.rotateXLabels ? 10 : 15 : 0);
                w.layout.gridWidth = gl.svgWidth - yAxisWidth - this.datalabelsCoords.width * 2;
            };
            if (w.config.xaxis.position === "top")
                translateY = w.layout.xAxisHeight - w.config.xaxis.axisTicks.height - 5;
            switch (w.config.legend.position) {
                case "bottom":
                    w.layout.translateY = translateY;
                    legendTopBottom();
                    break;
                case "top":
                    w.layout.translateY = this.lgRect.height + translateY;
                    legendTopBottom();
                    break;
                case "left":
                    w.layout.translateY = translateY;
                    w.layout.translateX = this.lgRect.width + yAxisWidth + this.datalabelsCoords.width;
                    w.layout.gridHeight = gl.svgHeight - xAxisHeight - 12;
                    w.layout.gridWidth = gl.svgWidth - this.lgRect.width - yAxisWidth - this.datalabelsCoords.width * 2;
                    break;
                case "right":
                    w.layout.translateY = translateY;
                    w.layout.translateX = yAxisWidth + this.datalabelsCoords.width;
                    w.layout.gridHeight = gl.svgHeight - xAxisHeight - 12;
                    w.layout.gridWidth = gl.svgWidth - this.lgRect.width - yAxisWidth - this.datalabelsCoords.width * 2 - 5;
                    break;
                default:
                    throw new Error("Legend position not supported");
            }
            this.dimGrid.setGridXPosForDualYAxis(yTitleCoords, yaxisLabelCoords);
            const objyAxis = new YAxis(this.w, {
                theme: this.theme,
                timeScale: this.timeScale
            });
            objyAxis.setYAxisXPosition(yaxisLabelCoords, yTitleCoords);
        }
        setDimensionsForNonAxisCharts() {
            const w = this.w;
            const gl = w.globals;
            const cnf = w.config;
            let xPad = 0;
            if (w.config.legend.show && !w.config.legend.floating) {
                xPad = 20;
            }
            const type = cnf.chart.type === "pie" || cnf.chart.type === "polarArea" || cnf.chart.type === "donut" ? "pie" : "radialBar";
            const offY = cnf.plotOptions[type].offsetY;
            const offX = cnf.plotOptions[type].offsetX;
            if (!cnf.legend.show || cnf.legend.floating) {
                w.layout.gridHeight = gl.svgHeight;
                const maxWidth = w.dom.elWrap.getBoundingClientRect().width;
                w.layout.gridWidth = Math.min(maxWidth, w.layout.gridHeight);
                w.layout.translateY = offY;
                w.layout.translateX = offX + (gl.svgWidth - w.layout.gridWidth) / 2;
                return;
            }
            switch (cnf.legend.position) {
                case "bottom":
                    w.layout.gridHeight = gl.svgHeight - this.lgRect.height;
                    w.layout.gridWidth = gl.svgWidth;
                    w.layout.translateY = offY - 10;
                    w.layout.translateX = offX + (gl.svgWidth - w.layout.gridWidth) / 2;
                    break;
                case "top":
                    w.layout.gridHeight = gl.svgHeight - this.lgRect.height;
                    w.layout.gridWidth = gl.svgWidth;
                    w.layout.translateY = this.lgRect.height + offY + 10;
                    w.layout.translateX = offX + (gl.svgWidth - w.layout.gridWidth) / 2;
                    break;
                case "left":
                    w.layout.gridWidth = gl.svgWidth - this.lgRect.width - xPad;
                    w.layout.gridHeight = cnf.chart.height !== "auto" ? gl.svgHeight : w.layout.gridWidth;
                    w.layout.translateY = offY;
                    w.layout.translateX = offX + this.lgRect.width + xPad;
                    break;
                case "right":
                    w.layout.gridWidth = gl.svgWidth - this.lgRect.width - xPad - 5;
                    w.layout.gridHeight = cnf.chart.height !== "auto" ? gl.svgHeight : w.layout.gridWidth;
                    w.layout.translateY = offY;
                    w.layout.translateX = offX + 10;
                    break;
                default:
                    throw new Error("Legend position not supported");
            }
        }
        /**
         * @param {any} xaxisLabelCoords
         * @param {any} xtitleCoords
         * @param {any} xaxisGroupLabelCoords
         */
        conditionalChecksForAxisCoords(xaxisLabelCoords, xtitleCoords, xaxisGroupLabelCoords) {
            const w = this.w;
            const xAxisNum = w.labelData.hasXaxisGroups ? 2 : 1;
            const baseXAxisHeight = xaxisGroupLabelCoords.height + xaxisLabelCoords.height + xtitleCoords.height;
            const xAxisHeightMultiplicate = w.axisFlags.isMultiLineX ? 1.2 : LINE_HEIGHT_RATIO;
            const rotatedXAxisOffset = w.layout.rotateXLabels ? 22 : 10;
            const rotatedXAxisLegendOffset = w.layout.rotateXLabels && w.config.legend.position === "bottom";
            const additionalOffset = rotatedXAxisLegendOffset ? 10 : 0;
            this.xAxisHeight = baseXAxisHeight * xAxisHeightMultiplicate + xAxisNum * rotatedXAxisOffset + additionalOffset;
            this.xAxisWidth = xaxisLabelCoords.width;
            if (this.xAxisHeight - xtitleCoords.height > w.config.xaxis.labels.maxHeight) {
                this.xAxisHeight = w.config.xaxis.labels.maxHeight;
            }
            if (w.config.xaxis.labels.minHeight && this.xAxisHeight < w.config.xaxis.labels.minHeight) {
                this.xAxisHeight = w.config.xaxis.labels.minHeight;
            }
            if (w.config.xaxis.floating) {
                this.xAxisHeight = 0;
            }
            let minYAxisWidth = 0;
            let maxYAxisWidth = 0;
            w.config.yaxis.forEach((y) => {
                minYAxisWidth += y.labels.minWidth;
                maxYAxisWidth += y.labels.maxWidth;
            });
            if (this.yAxisWidth < minYAxisWidth) {
                this.yAxisWidth = minYAxisWidth;
            }
            if (this.yAxisWidth > maxYAxisWidth) {
                this.yAxisWidth = maxYAxisWidth;
            }
        }
    }
    const SECOND = 1e3;
    const MINUTE = 60 * SECOND;
    const HOUR = 60 * MINUTE;
    const DAY = 24 * HOUR;
    const WEEK = 7 * DAY;
    const APPROX_MONTH = 30 * DAY;
    const APPROX_YEAR = 365 * DAY;
    const MIN_ZOOM_DAYS = 10 / (24 * 60 * 60);
    const TICK_LADDER = [{
            unit: "second",
            step: 1,
            approxMs: SECOND
        },
        {
            unit: "second",
            step: 5,
            approxMs: 5 * SECOND
        },
        {
            unit: "second",
            step: 15,
            approxMs: 15 * SECOND
        },
        {
            unit: "second",
            step: 30,
            approxMs: 30 * SECOND
        },
        {
            unit: "minute",
            step: 1,
            approxMs: MINUTE
        },
        {
            unit: "minute",
            step: 5,
            approxMs: 5 * MINUTE
        },
        {
            unit: "minute",
            step: 15,
            approxMs: 15 * MINUTE
        },
        {
            unit: "minute",
            step: 30,
            approxMs: 30 * MINUTE
        },
        {
            unit: "hour",
            step: 1,
            approxMs: HOUR
        },
        {
            unit: "hour",
            step: 3,
            approxMs: 3 * HOUR
        },
        {
            unit: "hour",
            step: 6,
            approxMs: 6 * HOUR
        },
        {
            unit: "hour",
            step: 12,
            approxMs: 12 * HOUR
        },
        {
            unit: "day",
            step: 1,
            approxMs: DAY
        },
        {
            unit: "day",
            step: 2,
            approxMs: 2 * DAY
        },
        {
            unit: "week",
            step: 1,
            approxMs: WEEK
        },
        {
            unit: "week",
            step: 2,
            approxMs: 2 * WEEK
        },
        {
            unit: "month",
            step: 1,
            approxMs: APPROX_MONTH
        },
        {
            unit: "month",
            step: 3,
            approxMs: 3 * APPROX_MONTH
        },
        {
            unit: "month",
            step: 6,
            approxMs: 6 * APPROX_MONTH
        },
        {
            unit: "year",
            step: 1,
            approxMs: APPROX_YEAR
        },
        {
            unit: "year",
            step: 2,
            approxMs: 2 * APPROX_YEAR
        },
        {
            unit: "year",
            step: 5,
            approxMs: 5 * APPROX_YEAR
        },
        {
            unit: "year",
            step: 10,
            approxMs: 10 * APPROX_YEAR
        },
        {
            unit: "year",
            step: 25,
            approxMs: 25 * APPROX_YEAR
        },
        {
            unit: "year",
            step: 50,
            approxMs: 50 * APPROX_YEAR
        },
        {
            unit: "year",
            step: 100,
            approxMs: 100 * APPROX_YEAR
        }
    ];
    const DEFAULT_TICK_COUNT = 10;
    class TimeScale {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this.tickInterval = null;
            this.timeScaleArray = [];
            this.utc = w.config.xaxis.labels.datetimeUTC;
        }
        /**
         * Compute raw ticks for a datetime axis spanning [minX, maxX]. Single
         * uniform stride — one unit, no promotion, no calendar-boundary overlay.
         * Context (year, day) is folded into each label's format string at
         * `formatDates` time, not split across promoted ticks.
         *
         * @param {number} minX
         * @param {number} maxX
         * @returns {Array<any>} raw ticks (pre-formatting). Pass to recalcDimensionsBasedOnFormat for the final timescaleLabels.
         */
        calculateTimeScaleTicks(minX, maxX) {
            const w = this.w;
            if (w.globals.allSeriesCollapsed) {
                w.labelData.labels = [];
                w.labelData.timescaleLabels = [];
                this.timeScaleArray = [];
                return [];
            }
            const span = maxX - minX;
            const daysDiff = span / DAY;
            w.interact.disableZoomIn = false;
            w.interact.disableZoomOut = false;
            if (daysDiff < MIN_ZOOM_DAYS) {
                w.interact.disableZoomIn = true;
            } else if (daysDiff > 5e4) {
                w.interact.disableZoomOut = true;
            }
            const targetCount = Number.isFinite(w.config.xaxis.tickAmount) ? (
                /** @type {number} */
                w.config.xaxis.tickAmount
            ) : DEFAULT_TICK_COUNT;
            this.tickInterval = pickInterval(span, targetCount);
            const ticks = this.generateBaseTicks(minX, maxX, this.tickInterval);
            this.timeScaleArray = ticks;
            return ticks;
        }
        /**
         * Walk the interval stride from `minX` to `maxX`. Every tick carries
         * `unit: interval.unit` — no promotion, no snapping. Uniform spacing is
         * guaranteed.
         *
         * @param {number} minX
         * @param {number} maxX
         * @param {{ unit: string, step: number }} interval
         * @returns {Array<any>}
         */
        generateBaseTicks(minX, maxX, interval) {
            const w = this.w;
            const dt = new DateTime(w);
            const isUTC = this.utc;
            const gridWidth = w.layout.gridWidth;
            const span = maxX - minX;
            const ticks = [];
            let t = dt.ceilToBoundary(
                minX,
                /** @type {any} */
                interval.unit,
                interval.step,
                isUTC
            );
            let iter = 0;
            const MAX_ITER = 5e3;
            while (t <= maxX && iter < MAX_ITER) {
                const f = dt.getDateFields(t, isUTC);
                const position = span > 0 ? (t - minX) / span * gridWidth : 0;
                ticks.push({
                    timestamp: t,
                    position,
                    unit: interval.unit,
                    year: f.year,
                    month: f.month + 1,
                    day: f.date,
                    hour: f.hour,
                    minute: f.minute,
                    second: f.second,
                    value: t
                });
                t = dt.addInterval(
                    t,
                    /** @type {any} */
                    interval.unit,
                    interval.step,
                    isUTC
                );
                iter++;
            }
            return ticks;
        }
        /**
         * Public entry called from Core.js after calculateTimeScaleTicks. Formats
         * the raw ticks into display labels, removes overlapping entries, writes
         * the result to `w.labelData.timescaleLabels`, and re-runs Dimensions to
         * lay out the grid based on the final label widths.
         *
         * @param {Array<any>} rawTicks
         */
        recalcDimensionsBasedOnFormat(rawTicks) {
            const w = this.w;
            const formatted = this.formatDates(rawTicks);
            const filtered = this.removeOverlappingTS(formatted);
            w.labelData.timescaleLabels = filtered.slice();
            const dimensions = new Dimensions(this.w, this.ctx);
            const layoutState = dimensions.plotCoords();
            this.ctx._writeLayoutCoords(layoutState.layout);
        }
        /**
         * Format each raw tick into a display label. All ticks share one
         * effective format computed once from the interval unit and the data
         * range — when the range spans coarser units, the base format from
         * `datetimeFormatter[unit]` is automatically extended with the higher-
         * unit context (e.g. month-scale spanning years → `MMM yyyy`, hour-scale
         * spanning days → `dd MMM HH:mm`). A user-supplied `xaxis.labels.format`
         * overrides everything.
         *
         * @param {Array<any>} rawTicks
         * @returns {Array<any>}
         */
        formatDates(rawTicks) {
            const w = this.w;
            const dt = new DateTime(w);
            const userFormat = w.config.xaxis.labels.format;
            const dtFmt = w.config.xaxis.labels.datetimeFormatter;
            const isUTC = this.utc;
            const pad = (n, len = 2) => String(n).padStart(len, "0");
            const effectiveFormat = userFormat ? userFormat : this._effectiveFormat(rawTicks, dtFmt);
            return rawTicks.map((tick) => {
                const date = dt.getDate(tick.timestamp);
                const value = dt.formatDate(date, effectiveFormat);
                const ds = `${tick.year}-${pad(tick.month)}-${pad(tick.day)}T${pad(tick.hour)}:${pad(tick.minute)}:${pad(tick.second)}.000${isUTC ? "Z" : ""}`;
                return {
                    dateString: ds,
                    position: tick.position,
                    value,
                    unit: tick.unit,
                    year: tick.year,
                    month: tick.month
                };
            });
        }
        /**
         * Pick the format string used for every tick this render. Folds coarser
         * context into the base `datetimeFormatter[unit]` when the data range
         * spans it. Skipped when the base format already references the higher
         * unit's tokens (so user customizations aren't doubled).
         *
         * @param {Array<any>} rawTicks
         * @param {Record<string, string>} dtFmt
         * @returns {string}
         */
        _effectiveFormat(rawTicks, dtFmt) {
            if (rawTicks.length === 0) return dtFmt.day || "dd MMM";
            const unit = this.tickInterval && this.tickInterval.unit || rawTicks[0].unit;
            const base = dtFmt[unit === "week" ? "day" : unit] || dtFmt.day || "dd MMM";
            const first = rawTicks[0];
            const last = rawTicks[rawTicks.length - 1];
            const spansYears = first.year !== last.year;
            const spansMonths = spansYears || first.month !== last.month;
            const spansDays = spansMonths || first.day !== last.day;
            const hasYearToken = /y/i.test(base);
            const hasMonthToken = /M/.test(base);
            const hasDayToken = /d/i.test(base);
            if (unit === "month" || unit === "week") {
                if (spansYears && !hasYearToken) return base + " yyyy";
                return base;
            }
            if (unit === "day") {
                if (spansYears && !hasYearToken) return base + " yyyy";
                return base;
            }
            if (unit === "hour" || unit === "minute" || unit === "second") {
                if (spansDays && !hasDayToken && !hasMonthToken) {
                    const prefix = spansYears ? "dd MMM yyyy" : "dd MMM";
                    return prefix + " " + base;
                }
                return base;
            }
            return base;
        }
        /**
         * Drop labels that would overlap their predecessor (when
         * `xaxis.labels.hideOverlappingLabels` is true). The first label is always
         * kept. Width is measured per-label unless all labels have the same string
         * length, in which case one measurement is reused.
         *
         * @param {Array<any>} arr
         * @returns {Array<any>}
         */
        removeOverlappingTS(arr) {
            if (arr.length === 0) return [];
            const w = this.w;
            const graphics = new Graphics(w);
            let equalLabelLengthFlag = false;
            let constantLabelWidth;
            if (arr[0].value && arr.every((lb) => lb.value.length === arr[0].value.length)) {
                equalLabelLengthFlag = true;
                constantLabelWidth = graphics.getTextRects(
                    arr[0].value,
                    w.config.xaxis.labels.style.fontSize
                ).width;
            }
            let lastDrawnIndex = 0;
            const filtered = arr.map((item, index) => {
                if (index === 0) return item;
                if (!w.config.xaxis.labels.hideOverlappingLabels) return item;
                const prevLabelWidth = equalLabelLengthFlag ? (
                    /** @type {number} */
                    constantLabelWidth
                ) : graphics.getTextRects(
                    arr[lastDrawnIndex].value,
                    w.config.xaxis.labels.style.fontSize
                ).width;
                const prevPos = arr[lastDrawnIndex].position;
                const pos = item.position;
                if (pos > prevPos + prevLabelWidth + 10) {
                    lastDrawnIndex = index;
                    return item;
                }
                return null;
            }).filter((f) => f !== null);
            return filtered;
        }
    }

    function pickInterval(span, targetCount) {
        if (!Number.isFinite(targetCount) || targetCount <= 0) {
            targetCount = DEFAULT_TICK_COUNT;
        }
        if (span <= 0) return TICK_LADDER[0];
        const targetMs = span / targetCount;
        let best = TICK_LADDER[0];
        let bestDist = Infinity;
        for (const interval of TICK_LADDER) {
            const dist = Math.abs(Math.log(interval.approxMs / targetMs));
            if (dist < bestDist) {
                bestDist = dist;
                best = interval;
            }
        }
        return best;
    }
    const REGISTRY_KEY = "__apexcharts_registry__";
    if (! /** @type {any} */
        globalThis[REGISTRY_KEY]) {
        globalThis[REGISTRY_KEY] = {};
    }

    function getRegistry() {
        return (
            /** @type {any} */
            globalThis[REGISTRY_KEY]
        );
    }

    function register(typeMap) {
        Object.assign(getRegistry(), typeMap);
    }

    function getChartClass(type) {
        const Cls = getRegistry()[type];
        if (!Cls) {
            throw new Error(
                `ApexCharts: chart type "${type}" is not registered. Import it via ApexCharts.use() or use the full apexcharts bundle.`
            );
        }
        return Cls;
    }
    class Core {
        /**
         * @param {Element} el
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(el, w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this.el = el;
        }
        setupElements() {
            const {
                globals: gl,
                config: cnf
            } = this.w;
            const ct = cnf.chart.type;
            const xyChartsArrTypes = [
                "line",
                "area",
                "bar",
                "rangeBar",
                "rangeArea",
                "candlestick",
                "boxPlot",
                "scatter",
                "bubble"
            ];
            const axisChartsArrTypes = [
                ...xyChartsArrTypes,
                "radar",
                "heatmap",
                "treemap"
            ];
            gl.axisCharts = axisChartsArrTypes.includes(ct);
            gl.xyCharts = xyChartsArrTypes.includes(ct);
            gl.isBarHorizontal = ["bar", "rangeBar", "boxPlot"].includes(ct) && cnf.plotOptions.bar.horizontal;
            gl.chartClass = `.apexcharts${gl.chartID}`;
            this.w.dom.baseEl = this.el;
            this.w.dom.elWrap = BrowserAPIs.createElementNS(
                "http://www.w3.org/1999/xhtml",
                "div"
            );
            Graphics.setAttrs(this.w.dom.elWrap, {
                id: gl.chartClass.substring(1),
                class: `apexcharts-canvas ${gl.chartClass.substring(1)}`
            });
            this.el.appendChild(this.w.dom.elWrap);
            const SVG2 = (
                /** @type {any} */
                globalThis.SVG
            );
            this.w.dom.Paper = SVG2().addTo(this.w.dom.elWrap);
            this.w.dom.Paper.attr({
                class: "apexcharts-svg",
                "xmlns:data": "ApexChartsNS",
                transform: `translate(${cnf.chart.offsetX}, ${cnf.chart.offsetY})`
            });
            this.w.dom.Paper.node.style.background = cnf.theme.mode === "dark" && !cnf.chart.background ? "#343A3F" : cnf.theme.mode === "light" && !cnf.chart.background ? "#fff" : cnf.chart.background;
            this.setSVGDimensions();
            this.w.dom.elLegendForeign = BrowserAPIs.createElementNS(
                SVGNS,
                "foreignObject"
            );
            Graphics.setAttrs(this.w.dom.elLegendForeign, {
                x: 0,
                y: 0,
                width: gl.svgWidth,
                height: gl.svgHeight
            });
            this.w.dom.elLegendWrap = BrowserAPIs.createElementNS(
                "http://www.w3.org/1999/xhtml",
                "div"
            );
            this.w.dom.elLegendWrap.classList.add("apexcharts-legend");
            this.w.dom.elWrap.appendChild(this.w.dom.elLegendWrap);
            this.w.dom.Paper.node.appendChild(this.w.dom.elLegendForeign);
            if (cnf.chart.accessibility.enabled && cnf.chart.accessibility.announcements.enabled) {
                const srStatus = BrowserAPIs.createElement("div");
                srStatus.className = "apexcharts-sr-status";
                srStatus.setAttribute("role", "status");
                srStatus.setAttribute("aria-live", "polite");
                srStatus.setAttribute("aria-atomic", "true");
                this.w.dom.elWrap.appendChild(srStatus);
            }
            if (cnf.chart.accessibility.enabled) {
                const ariaLabel = this.getAccessibleChartLabel();
                const svgRole = cnf.chart.accessibility.keyboard.enabled && cnf.chart.accessibility.keyboard.navigation.enabled ? "application" : "img";
                this.w.dom.Paper.attr({
                    role: svgRole,
                    "aria-label": ariaLabel
                });
                if (cnf.chart.accessibility.description) {
                    const descEl = BrowserAPIs.createElementNS(SVGNS, "desc");
                    descEl.textContent = cnf.chart.accessibility.description;
                    this.w.dom.Paper.node.insertBefore(
                        descEl,
                        this.w.dom.elLegendForeign.nextSibling
                    );
                }
            }
            this.w.dom.elGraphical = this.w.dom.Paper.group().attr({
                class: "apexcharts-inner apexcharts-graphical"
            });
            this.w.dom.elDefs = this.w.dom.Paper.defs();
            this.w.dom.Paper.add(this.w.dom.elGraphical);
            this.w.dom.elGraphical.add(this.w.dom.elDefs);
        }
        /**
         * @param {any[]} ser
         * @param {import('../types/internal').XYRatios} xyRatios
         */
        plotChartType(ser, xyRatios) {
            const {
                w,
                ctx
            } = this;
            const {
                config: cnf,
                globals: gl
            } = w;
            const seriesTypes = {
                line: {
                    series: [],
                    i: []
                },
                area: {
                    series: [],
                    i: []
                },
                scatter: {
                    series: [],
                    i: []
                },
                bubble: {
                    series: [],
                    i: []
                },
                bar: {
                    series: [],
                    i: []
                },
                candlestick: {
                    series: [],
                    i: []
                },
                boxPlot: {
                    series: [],
                    i: []
                },
                rangeBar: {
                    series: [],
                    i: []
                },
                rangeArea: {
                    series: [],
                    seriesRangeEnd: [],
                    i: []
                }
            };
            const chartType = cnf.chart.type || "line";
            let nonComboType = null;
            let comboCount = 0;
            this.w.seriesData.series.forEach((serie, st) => {
                var _a, _b;
                const seriesType = ((_a = ser[st]) == null ? void 0 : _a.type) === "column" ? "bar" : ((_b = ser[st]) == null ? void 0 : _b.type) || (chartType === "column" ? "bar" : chartType);
                const st_ = (
                    /** @type {Record<string,any>} */
                    seriesTypes
                );
                if (st_[seriesType]) {
                    if (seriesType === "rangeArea") {
                        st_[seriesType].series.push(this.w.rangeData.seriesRangeStart[st]);
                        st_[seriesType].seriesRangeEnd.push(
                            this.w.rangeData.seriesRangeEnd[st]
                        );
                    } else {
                        st_[seriesType].series.push(serie);
                    }
                    st_[seriesType].i.push(st);
                    if (seriesType === "bar") w.globals.columnSeries = seriesTypes.bar;
                } else if ([
                        "heatmap",
                        "treemap",
                        "pie",
                        "donut",
                        "polarArea",
                        "radialBar",
                        "radar"
                    ].includes(seriesType)) {
                    nonComboType = seriesType;
                } else {
                    console.warn(
                        `You have specified an unrecognized series type (${seriesType}).`
                    );
                }
                if (chartType !== seriesType && seriesType !== "scatter") comboCount++;
            });
            if (comboCount > 0) {
                if (nonComboType) {
                    console.warn(
                        `Chart or series type ${nonComboType} cannot appear with other chart or series types.`
                    );
                }
                if (seriesTypes.bar.series.length > 0 && cnf.plotOptions.bar.horizontal) {
                    comboCount -= seriesTypes.bar.series.length;
                    seriesTypes.bar = {
                        series: [],
                        i: []
                    };
                    w.globals.columnSeries = {
                        series: [],
                        i: []
                    };
                    console.warn(
                        "Horizontal bars are not supported in a mixed/combo chart. Please turn off `plotOptions.bar.horizontal`"
                    );
                }
            }
            gl.comboCharts || (gl.comboCharts = comboCount > 0);
            const needsLine = seriesTypes.line.series.length > 0 || seriesTypes.area.series.length > 0 || seriesTypes.scatter.series.length > 0 || seriesTypes.bubble.series.length > 0 || seriesTypes.rangeArea.series.length > 0 || !gl.comboCharts && ["line", "area", "scatter", "bubble", "rangeArea"].includes(
                cnf.chart.type
            );
            const line = needsLine ? new(getChartClass("line"))(ctx.w, ctx, xyRatios) : null;
            const needsCandlestick = seriesTypes.candlestick.series.length > 0 || seriesTypes.boxPlot.series.length > 0 || !gl.comboCharts && ["candlestick", "boxPlot"].includes(cnf.chart.type);
            const boxCandlestick = needsCandlestick ? new(getChartClass("candlestick"))(ctx.w, ctx, xyRatios) : null;
            const needsPie = !gl.comboCharts && ["pie", "donut", "polarArea"].includes(cnf.chart.type);
            ctx.pie = needsPie ? new(getChartClass("pie"))(ctx.w, ctx) : null;
            const needsRangeBar = seriesTypes.rangeBar.series.length > 0 || !gl.comboCharts && cnf.chart.type === "rangeBar";
            ctx.rangeBar = needsRangeBar ? new(getChartClass("rangeBar"))(ctx.w, ctx, xyRatios) : null;
            let elGraph = [];
            if (gl.comboCharts) {
                const coreUtils = new CoreUtils(this.w);
                if (seriesTypes.area.series.length > 0) {
                    elGraph.push(
                        ...coreUtils.drawSeriesByGroup(
                            seriesTypes.area,
                            gl.areaGroups,
                            "area",
                            line
                        )
                    );
                }
                if (seriesTypes.bar.series.length > 0) {
                    if (cnf.chart.stacked) {
                        const barStacked = new(getChartClass("barStacked"))(
                            ctx.w,
                            ctx,
                            xyRatios
                        );
                        elGraph.push(
                            barStacked.draw(seriesTypes.bar.series, seriesTypes.bar.i)
                        );
                    } else {
                        ctx.bar = new(getChartClass("bar"))(ctx.w, ctx, xyRatios);
                        elGraph.push(ctx.bar.draw(seriesTypes.bar.series, seriesTypes.bar.i));
                    }
                }
                if (seriesTypes.rangeArea.series.length > 0) {
                    elGraph.push(
                        line.draw(
                            seriesTypes.rangeArea.series,
                            "rangeArea",
                            seriesTypes.rangeArea.i,
                            seriesTypes.rangeArea.seriesRangeEnd
                        )
                    );
                }
                if (seriesTypes.line.series.length > 0) {
                    elGraph.push(
                        ...coreUtils.drawSeriesByGroup(
                            seriesTypes.line,
                            gl.lineGroups,
                            "line",
                            line
                        )
                    );
                }
                if (seriesTypes.candlestick.series.length > 0) {
                    elGraph.push(
                        boxCandlestick.draw(
                            seriesTypes.candlestick.series,
                            "candlestick",
                            seriesTypes.candlestick.i
                        )
                    );
                }
                if (seriesTypes.boxPlot.series.length > 0) {
                    elGraph.push(
                        boxCandlestick.draw(
                            seriesTypes.boxPlot.series,
                            "boxPlot",
                            seriesTypes.boxPlot.i
                        )
                    );
                }
                if (seriesTypes.rangeBar.series.length > 0) {
                    elGraph.push(
                        ctx.rangeBar.draw(
                            seriesTypes.rangeBar.series,
                            seriesTypes.rangeBar.i
                        )
                    );
                }
                if (seriesTypes.scatter.series.length > 0) {
                    const scatterLine = new(getChartClass("line"))(
                        ctx.w,
                        ctx,
                        xyRatios,
                        true
                    );
                    elGraph.push(
                        scatterLine.draw(
                            seriesTypes.scatter.series,
                            "scatter",
                            seriesTypes.scatter.i
                        )
                    );
                }
                if (seriesTypes.bubble.series.length > 0) {
                    const bubbleLine = new(getChartClass("line"))(
                        ctx.w,
                        ctx,
                        xyRatios,
                        true
                    );
                    elGraph.push(
                        bubbleLine.draw(
                            seriesTypes.bubble.series,
                            "bubble",
                            seriesTypes.bubble.i
                        )
                    );
                }
            } else {
                const type = cnf.chart.type;
                switch (type) {
                    case "line":
                        elGraph = line.draw(this.w.seriesData.series, "line");
                        break;
                    case "area":
                        elGraph = line.draw(this.w.seriesData.series, "area");
                        break;
                    case "bar":
                        if (cnf.chart.stacked) {
                            const barStacked = new(getChartClass("barStacked"))(
                                ctx.w,
                                ctx,
                                xyRatios
                            );
                            elGraph = barStacked.draw(this.w.seriesData.series);
                        } else {
                            ctx.bar = new(getChartClass("bar"))(ctx.w, ctx, xyRatios);
                            elGraph = ctx.bar.draw(this.w.seriesData.series);
                        }
                        break;
                    case "candlestick":
                        elGraph = boxCandlestick.draw(this.w.seriesData.series, "candlestick");
                        break;
                    case "boxPlot":
                        elGraph = boxCandlestick.draw(this.w.seriesData.series, type);
                        break;
                    case "rangeBar":
                        elGraph = ctx.rangeBar.draw(this.w.seriesData.series);
                        break;
                    case "rangeArea":
                        elGraph = line.draw(
                            this.w.rangeData.seriesRangeStart,
                            "rangeArea",
                            void 0,
                            this.w.rangeData.seriesRangeEnd
                        );
                        break;
                    case "heatmap": {
                        const heatmap = new(getChartClass("heatmap"))(ctx.w, ctx, xyRatios);
                        elGraph = heatmap.draw(this.w.seriesData.series);
                        break;
                    }
                    case "treemap": {
                        const treemap = new(getChartClass("treemap"))(ctx.w, ctx);
                        elGraph = treemap.draw(this.w.seriesData.series);
                        break;
                    }
                    case "pie":
                    case "donut":
                    case "polarArea":
                        elGraph = ctx.pie.draw(this.w.seriesData.series);
                        break;
                    case "radialBar": {
                        const radialBar = new(getChartClass("radialBar"))(ctx.w, ctx);
                        elGraph = radialBar.draw(this.w.seriesData.series);
                        break;
                    }
                    case "radar": {
                        const radar = new(getChartClass("radar"))(ctx.w, ctx);
                        elGraph = radar.draw(this.w.seriesData.series);
                        break;
                    }
                    default:
                        elGraph = line.draw(this.w.seriesData.series);
                }
            }
            return elGraph;
        }
        setSVGDimensions() {
            var _a;
            const {
                globals: gl,
                config: cnf
            } = this.w;
            cnf.chart.width = cnf.chart.width || "100%";
            cnf.chart.height = cnf.chart.height || "auto";
            const rawWidth = cnf.chart.width;
            const rawHeight = cnf.chart.height;
            gl.svgWidth = NaN;
            gl.svgHeight = NaN;
            let elDim = Utils$1.getDimensions(this.el);
            const widthUnit = rawWidth.toString().split(/[0-9]+/g).pop();
            if (widthUnit === "%") {
                if (Utils$1.isNumber(elDim[0])) {
                    if (elDim[0].width === 0) {
                        elDim = Utils$1.getDimensions(this.el.parentNode);
                    }
                    gl.svgWidth = elDim[0] * parseInt(rawWidth, 10) / 100;
                }
            } else if (widthUnit === "px" || widthUnit === "") {
                gl.svgWidth = parseInt(rawWidth, 10);
            }
            const heightUnit = String(rawHeight).toString().split(/[0-9]+/g).pop();
            if (rawHeight !== "auto" && rawHeight !== "") {
                if (heightUnit === "%") {
                    const elParentDim = Utils$1.getDimensions(this.el.parentNode);
                    gl.svgHeight = elParentDim[1] * parseInt(rawHeight, 10) / 100;
                } else {
                    gl.svgHeight = parseInt(rawHeight, 10);
                }
            } else {
                gl.svgHeight = gl.axisCharts ? gl.svgWidth / 1.61 : gl.svgWidth / 1.2;
            }
            gl.svgWidth = Math.max(gl.svgWidth, 0);
            gl.svgHeight = Math.max(gl.svgHeight, 0);
            Graphics.setAttrs(this.w.dom.Paper.node, {
                width: gl.svgWidth,
                height: gl.svgHeight
            });
            if (heightUnit !== "%" && Environment.isBrowser()) {
                const needsAxisPadding = gl.axisCharts && (cnf.grid.show || cnf.dataLabels.enabled || cnf.xaxis.labels.show || cnf.xaxis.axisBorder.show || cnf.xaxis.axisTicks.show || cnf.yaxis.some(
                    (y) => y.show && (y.labels.show || y.axisBorder.show || y.axisTicks.show)
                ));
                const offsetY = cnf.chart.sparkline.enabled || !needsAxisPadding ? 0 : cnf.chart.parentHeightOffset;
                const paperNode = this.w.dom.Paper.node;
                if ((_a = paperNode.parentNode) == null ? void 0 : _a.parentNode) {
                    paperNode.parentNode.parentNode.style.minHeight = `${gl.svgHeight + offsetY}px`;
                }
            }
            this.w.dom.elWrap.style.width = `${gl.svgWidth}px`;
            this.w.dom.elWrap.style.height = `${gl.svgHeight}px`;
        }
        shiftGraphPosition() {
            const {
                globals: gl
            } = this.w;
            const {
                translateY: tY,
                translateX: tX
            } = gl;
            Graphics.setAttrs(this.w.dom.elGraphical.node, {
                transform: `translate(${tX}, ${tY})`
            });
        }
        resizeNonAxisCharts() {
            var _a, _b, _c, _d, _e, _f;
            const {
                w
            } = this;
            const heightStr = w.config.chart.height ? String(w.config.chart.height) : "";
            const userSetFixedHeight = heightStr !== "" && heightStr !== "auto";
            const isPercentHeight = heightStr.includes("%");
            let legendHeight = 0;
            let offY = w.config.chart.sparkline.enabled ? 1 : 15;
            offY += w.config.grid.padding.bottom;
            if (["top", "bottom"].includes(w.config.legend.position) && w.config.legend.show && !w.config.legend.floating) {
                legendHeight = ((_b = (_a = this.ctx.legend) == null ? void 0 : _a.legendHelpers.getLegendDimensions().clwh) != null ? _b : 0) + 7;
            }
            const el = w.dom.baseEl.querySelector(
                ".apexcharts-radialbar, .apexcharts-pie"
            );
            let chartInnerDimensions = w.globals.radialSize * 2.05;
            const radialAngleSpan = Math.abs(
                w.config.plotOptions.radialBar.endAngle - w.config.plotOptions.radialBar.startAngle
            );
            if (el && !w.config.chart.sparkline.enabled && radialAngleSpan < 360) {
                const svgRect = Utils$1.getBoundingClientRect(this.w.dom.Paper.node);
                let arcTopFromSVGTop = Infinity;
                let arcBottomFromSVGTop = -Infinity;
                const accumulate = (node) => {
                    var _a2, _b2, _c2, _d2;
                    if ((_a2 = node.classList) == null ? void 0 : _a2.contains("apexcharts-radialbar-hollow")) {
                        return;
                    }
                    const tag = (_c2 = (_b2 = node.tagName) == null ? void 0 : _b2.toLowerCase) == null ? void 0 : _c2.call(_b2);
                    if (tag === "text" || tag === "tspan") return;
                    const children = Array.from((_d2 = node.children) != null ? _d2 : []);
                    if (children.length > 0) {
                        children.forEach((c) => accumulate(
                            /** @type {Element} */
                            c
                        ));
                        return;
                    }
                    const r = Utils$1.getBoundingClientRect(node);
                    const height = r.bottom - r.top;
                    if (height > 0) {
                        const top = r.top - svgRect.top;
                        const bottom = r.bottom - svgRect.top;
                        if (top < arcTopFromSVGTop) arcTopFromSVGTop = top;
                        if (bottom > arcBottomFromSVGTop) arcBottomFromSVGTop = bottom;
                    }
                };
                Array.from((_c = el.children) != null ? _c : []).forEach(
                    (c) => accumulate(
                        /** @type {Element} */
                        c
                    )
                );
                if (!Number.isFinite(arcTopFromSVGTop)) arcTopFromSVGTop = 0;
                if (!Number.isFinite(arcBottomFromSVGTop)) {
                    const elRect = Utils$1.getBoundingClientRect(el);
                    arcBottomFromSVGTop = elRect.bottom - svgRect.top;
                }
                const padding = Math.max(offY, w.globals.radialSize * 0.2);
                const verticalShift = Math.max(padding - arcTopFromSVGTop, 0);
                if (verticalShift !== 0) {
                    w.layout.translateY = ((_d = w.layout.translateY) != null ? _d : 0) + verticalShift;
                    Graphics.setAttrs(this.w.dom.elGraphical.node, {
                        transform: `translate(${(_e = w.layout.translateX) != null ? _e : 0}, ${w.layout.translateY})`
                    });
                    arcBottomFromSVGTop += verticalShift;
                }
                chartInnerDimensions = arcBottomFromSVGTop > 0 ? arcBottomFromSVGTop : w.globals.radialSize * 2.05;
                const bottomPadding = Math.max(padding, arcTopFromSVGTop);
                const svgHeight = Math.ceil(
                    chartInnerDimensions + legendHeight + bottomPadding
                );
                const chartOffsetY = (_f = w.config.chart.offsetY) != null ? _f : 0;
                const elWrapHeight = svgHeight + Math.max(chartOffsetY, 0);
                if (!isPercentHeight) {
                    if (this.w.dom.elLegendForeign) {
                        this.w.dom.elLegendForeign.setAttribute(
                            "height",
                            String(elWrapHeight)
                        );
                    }
                    this.w.dom.elWrap.style.height = `${elWrapHeight}px`;
                    Graphics.setAttrs(this.w.dom.Paper.node, {
                        height: svgHeight
                    });
                    if (Environment.isBrowser()) {
                        this.w.dom.Paper.node.parentNode.parentNode.style.minHeight = `${elWrapHeight}px`;
                    }
                }
                return;
            }
            const newHeight = Math.ceil(
                chartInnerDimensions + this.w.layout.translateY + legendHeight + offY
            );
            if (userSetFixedHeight) return;
            if (this.w.dom.elLegendForeign) {
                this.w.dom.elLegendForeign.setAttribute("height", String(newHeight));
            }
            this.w.dom.elWrap.style.height = `${newHeight}px`;
            Graphics.setAttrs(this.w.dom.Paper.node, {
                height: newHeight
            });
            if (Environment.isBrowser()) {
                this.w.dom.Paper.node.parentNode.parentNode.style.minHeight = `${newHeight}px`;
            }
        }
        coreCalculations() {
            new Range(this.w).init();
        }
        resetGlobals() {
            const resetxyValues = () => this.w.config.series.map(() => []);
            const globalObj = new Globals();
            const {
                globals: gl
            } = this.w;
            const parsingFlags = {
                dataWasParsed: this.w.axisFlags.dataWasParsed,
                originalSeries: gl.originalSeries
            };
            globalObj.initGlobalVars(gl);
            gl.seriesXvalues = resetxyValues();
            gl.seriesYvalues = resetxyValues();
            if (parsingFlags.dataWasParsed) {
                this.w.axisFlags.dataWasParsed = parsingFlags.dataWasParsed;
                gl.originalSeries = parsingFlags.originalSeries;
            }
        }
        isMultipleY() {
            if (Array.isArray(this.w.config.yaxis) && this.w.config.yaxis.length > 1) {
                this.w.globals.isMultipleYAxis = true;
                return true;
            }
            return false;
        }
        xySettings() {
            const {
                w
            } = this;
            let xyRatios = null;
            if (w.globals.axisCharts) {
                if (w.config.xaxis.crosshairs.position === "back") {
                    new Crosshairs(this.w).drawXCrosshairs();
                }
                if (w.config.yaxis[0].crosshairs.position === "back") {
                    new Crosshairs(this.w).drawYCrosshairs();
                }
                if (w.config.xaxis.type === "datetime" && w.config.xaxis.labels.formatter === void 0) {
                    this.ctx.timeScale = new TimeScale(this.w, this.ctx);
                    let formattedTimeScale = [];
                    if (isFinite(w.globals.minX) && isFinite(w.globals.maxX) && !w.globals.isBarHorizontal) {
                        formattedTimeScale = this.ctx.timeScale.calculateTimeScaleTicks(
                            w.globals.minX,
                            w.globals.maxX
                        );
                    } else if (w.globals.isBarHorizontal) {
                        formattedTimeScale = this.ctx.timeScale.calculateTimeScaleTicks(
                            w.globals.minY,
                            w.globals.maxY
                        );
                    }
                    this.ctx.timeScale.recalcDimensionsBasedOnFormat(formattedTimeScale);
                }
                const coreUtils = new CoreUtils(this.w);
                xyRatios = coreUtils.getCalculatedRatios();
            }
            return xyRatios;
        }
        /**
         * @param {any} targetChart
         */
        updateSourceChart(targetChart) {
            this.ctx.w.interact.selection = void 0;
            this.ctx.updateHelpers._updateOptions({
                    chart: {
                        selection: {
                            xaxis: {
                                min: targetChart.w.globals.minX,
                                max: targetChart.w.globals.maxX
                            }
                        }
                    }
                },
                false,
                false
            );
        }
        setupBrushHandler() {
            const {
                ctx,
                w
            } = this;
            if (!w.config.chart.brush.enabled) return;
            if (typeof w.config.chart.events.selection !== "function") {
                const targets = Array.isArray(w.config.chart.brush.targets) ? w.config.chart.brush.targets : [w.config.chart.brush.target];
                targets.forEach((target) => {
                    const targetChart = (
                        /** @type {any} */
                        ctx.constructor.getChartByID(
                            target
                        )
                    );
                    targetChart.w.globals.brushSource = this.ctx;
                    if (typeof targetChart.w.config.chart.events.zoomed !== "function") {
                        targetChart.w.config.chart.events.zoomed = () => this.updateSourceChart(targetChart);
                    }
                    if (typeof targetChart.w.config.chart.events.scrolled !== "function") {
                        targetChart.w.config.chart.events.scrolled = () => (
                            /**
                             * @param {any} chart
                             * @param {Event} e
                             */
                            this.updateSourceChart(targetChart)
                        );
                    }
                });
                w.config.chart.events.selection = (chart, e) => {
                    targets.forEach((target) => {
                        const targetChart = (
                            /** @type {any} */
                            ctx.constructor.getChartByID(
                                target
                            )
                        );
                        targetChart.ctx.updateHelpers._updateOptions({
                                xaxis: {
                                    min: e.xaxis.min,
                                    max: e.xaxis.max
                                }
                            },
                            false,
                            false,
                            false,
                            false
                        );
                    });
                };
            }
        }
        getAccessibleChartLabel() {
            const w = this.w;
            const cnf = w.config;
            if (cnf.chart.accessibility && cnf.chart.accessibility.description) {
                return cnf.chart.accessibility.description;
            }
            const chartType = cnf.chart.type;
            const parts = [];
            if (cnf.title.text) {
                parts.push(`${cnf.title.text}. ${chartType} chart`);
                if (cnf.subtitle.text) parts.push(cnf.subtitle.text);
            } else {
                const namedSeries = (() => {
                    if (Array.isArray(w.seriesData.seriesNames) && w.seriesData.seriesNames.length) {
                        return w.seriesData.seriesNames.filter(Boolean);
                    }
                    if (Array.isArray(cnf.series)) {
                        return cnf.series.map((s) => typeof s === "object" && s !== null ? s.name : null).filter(Boolean);
                    }
                    return [];
                })();
                const seriesCount = w.seriesData.series.length || (cnf.series ? cnf.series.length : 0);
                if (namedSeries.length) {
                    parts.push(
                        `${chartType} chart with ${seriesCount} data series: ${namedSeries.join(", ")}`
                    );
                } else {
                    parts.push(`${chartType} chart with ${seriesCount} data series`);
                }
            }
            return parts.join(". ");
        }
    }
    class Data {
        /**
         * @param {import('../types/internal').ChartStateW} w
         */
        constructor(w, {
            resetGlobals = () => {},
            isMultipleY = () => {}
        } = {}) {
            this.w = w;
            this.resetGlobals = resetGlobals;
            this.isMultipleY = isMultipleY;
            this.twoDSeries = [];
            this.threeDSeries = [];
            this.twoDSeriesX = [];
            this.seriesGoals = [];
            this.coreUtils = new CoreUtils(this.w);
            this.activeSeriesIndex = 0;
        }
        // Helper to get the first valid data point from the active series
        getFirstDataPoint() {
            const series = this.w.config.series;
            const sr = new Series(this.w);
            this.activeSeriesIndex = sr.getActiveConfigSeriesIndex();
            const activeItem = (
                /** @type {any} */
                series[this.activeSeriesIndex]
            );
            if (activeItem && activeItem.data && activeItem.data.length > 0 && activeItem.data[0] !== null && typeof activeItem.data[0] !== "undefined") {
                return activeItem.data[0];
            }
            return null;
        }
        isMultiFormat() {
            return this.isFormatXY() || this.isFormat2DArray();
        }
        // given format is [{x, y}, {x, y}]
        isFormatXY() {
            var _a;
            const firstDataPoint = this.getFirstDataPoint();
            if (!firstDataPoint || typeof firstDataPoint.x === "undefined") return false;
            const data = (
                /** @type {any} */
                (_a = this.w.config.series[this.activeSeriesIndex]) == null ? void 0 : _a.data
            );
            if (data) {
                const isXY = (pt) => pt && typeof pt.x !== "undefined";
                for (let k = 1; k < Math.min(3, data.length); k++) {
                    if (isXY(data[k]) !== true) {
                        console.warn(
                            `ApexCharts: series data has mixed formats starting at index ${k}`
                        );
                        break;
                    }
                }
            }
            return true;
        }
        // given format is [[x, y], [x, y]]
        isFormat2DArray() {
            const firstDataPoint = this.getFirstDataPoint();
            return firstDataPoint && Array.isArray(firstDataPoint);
        }
        /**
         * @param {any[]} ser
         * @param {number} i
         */
        handleFormat2DArray(ser, i) {
            const cnf = this.w.config;
            const data = ser[i].data;
            const isBoxPlot = cnf.chart.type === "boxPlot" || /** @type {any} */
                cnf.series[i].type === "boxPlot";
            for (let j = 0; j < data.length; j++) {
                const point = data[j];
                const x = point[0];
                const y = point[1];
                const z = point[2];
                if (typeof y !== "undefined") {
                    if (Array.isArray(y) && y.length === 4 && !isBoxPlot) {
                        this.twoDSeries.push(Utils$1.parseNumber(y[3]));
                    } else if (point.length >= 5) {
                        this.twoDSeries.push(Utils$1.parseNumber(point[4]));
                    } else {
                        this.twoDSeries.push(Utils$1.parseNumber(y));
                    }
                    this.w.axisFlags.dataFormatXNumeric = true;
                }
                if (cnf.xaxis.type === "datetime") {
                    const ts = new Date(x).getTime();
                    this.twoDSeriesX.push(ts);
                } else {
                    this.twoDSeriesX.push(x);
                }
                if (typeof z !== "undefined") {
                    this.threeDSeries.push(z);
                    this.w.axisFlags.isDataXYZ = true;
                }
            }
        }
        /**
         * @param {any[]} ser
         * @param {number} i
         */
        handleFormatXY(ser, i) {
            const cnf = this.w.config;
            const gl = this.w.globals;
            const dt = new DateTime(this.w);
            const data = ser[i].data;
            let activeI = i;
            if (gl.collapsedSeriesIndices.indexOf(i) > -1) {
                activeI = this.activeSeriesIndex;
            }
            const activeData = ser[activeI].data;
            for (let j = 0; j < data.length; j++) {
                const point = data[j];
                if (typeof point.y !== "undefined") {
                    const val = Array.isArray(point.y) ? Utils$1.parseNumber(point.y[point.y.length - 1]) : Utils$1.parseNumber(point.y);
                    this.twoDSeries.push(val);
                }
                if (typeof this.seriesGoals[i] === "undefined") {
                    this.seriesGoals[i] = [];
                }
                if (typeof point.goals !== "undefined" && Array.isArray(point.goals)) {
                    this.seriesGoals[i].push(point.goals);
                } else {
                    this.seriesGoals[i].push(null);
                }
                if (typeof point.z !== "undefined") {
                    this.threeDSeries.push(point.z);
                    this.w.axisFlags.isDataXYZ = true;
                }
            }
            for (let j = 0; j < activeData.length; j++) {
                const point = activeData[j];
                const x = point.x;
                const isXString = typeof x === "string";
                const isXArr = Array.isArray(x);
                const isXDate = !isXArr && !!dt.isValidDate(x);
                if (isXString || isXDate) {
                    if (isXString || cnf.xaxis.convertedCatToNumeric) {
                        const isRangeColumn = gl.isBarHorizontal && this.w.axisFlags.isRangeData;
                        if (cnf.xaxis.type === "datetime" && !isRangeColumn) {
                            this.twoDSeriesX.push(dt.parseDate(x));
                        } else {
                            this.fallbackToCategory = true;
                            this.twoDSeriesX.push(x);
                            if (!isNaN(x) && this.w.config.xaxis.type !== "category" && typeof x !== "string") {
                                this.w.axisFlags.isXNumeric = true;
                            }
                        }
                    } else {
                        if (cnf.xaxis.type === "datetime") {
                            this.twoDSeriesX.push(dt.parseDate(x.toString()));
                        } else {
                            this.w.axisFlags.dataFormatXNumeric = true;
                            this.w.axisFlags.isXNumeric = true;
                            this.twoDSeriesX.push(parseFloat(x));
                        }
                    }
                } else if (isXArr) {
                    this.fallbackToCategory = true;
                    this.twoDSeriesX.push(x);
                } else {
                    this.w.axisFlags.isXNumeric = true;
                    this.w.axisFlags.dataFormatXNumeric = true;
                    this.twoDSeriesX.push(x);
                }
            }
        }
        /**
         * @param {any[]} ser
         * @param {number} i
         */
        handleRangeData(ser, i) {
            let range = {
                start: [],
                end: [],
                rangeUniques: []
            };
            if (this.isFormat2DArray()) {
                range = this.handleRangeDataFormat("array", ser, i);
            } else if (this.isFormatXY()) {
                range = this.handleRangeDataFormat("xy", ser, i);
            }
            this.w.rangeData.seriesRangeStart[i] = range.start === void 0 ? [] : range.start;
            this.w.rangeData.seriesRangeEnd[i] = range.end === void 0 ? [] : range.end;
            this.w.rangeData.seriesRange[i] = range.rangeUniques;
            this.w.rangeData.seriesRange.forEach((sr) => {
                if (!sr) return;
                sr.forEach((sarr) => {
                    const yItems = (
                        /** @type {any} */
                        sarr.y
                    );
                    const len = (
                        /** @type {any[]} */
                        yItems.length
                    );
                    if (len <= 1) return;
                    for (let arri = 0; arri < len; arri++) {
                        const arr = (
                            /** @type {any} */
                            yItems[arri]
                        );
                        const range1y1 = arr.y1;
                        const range1y2 = arr.y2;
                        for (let sri = arri + 1; sri < len; sri++) {
                            const range2 = (
                                /** @type {any} */
                                yItems[sri]
                            );
                            const range2y1 = range2.y1;
                            const range2y2 = range2.y2;
                            if (range1y1 <= range2y2 && range2y1 <= range1y2) {
                                const sarrAny = (
                                    /** @type {any} */
                                    sarr
                                );
                                sarrAny.overlaps.add(arr.rangeName);
                                sarrAny.overlaps.add(range2.rangeName);
                            }
                        }
                    }
                });
            });
            return range;
        }
        /**
         * @param {any[]} ser
         * @param {number} i
         */
        handleCandleStickBoxData(ser, i) {
            let ohlc = {
                o: [],
                h: [],
                m: [],
                l: [],
                c: []
            };
            if (this.isFormat2DArray()) {
                ohlc = this.handleCandleStickBoxDataFormat("array", ser, i);
            } else if (this.isFormatXY()) {
                ohlc = this.handleCandleStickBoxDataFormat("xy", ser, i);
            }
            this.w.candleData.seriesCandleO[i] = ohlc.o;
            this.w.candleData.seriesCandleH[i] = ohlc.h;
            this.w.candleData.seriesCandleM[i] = ohlc.m;
            this.w.candleData.seriesCandleL[i] = ohlc.l;
            this.w.candleData.seriesCandleC[i] = ohlc.c;
            return ohlc;
        }
        /**
         * @param {string} format
         * @param {any[]} ser
         * @param {number} i
         */
        handleRangeDataFormat(format, ser, i) {
            const rangeStart = [];
            const rangeEnd = [];
            const uniqueKeysMap = /* @__PURE__ */ new Map();
            const uniqueKeys = [];
            ser[i].data.forEach((item) => {
                if (!uniqueKeysMap.has(item.x)) {
                    const keyObj = {
                        x: item.x,
                        overlaps: /* @__PURE__ */ new Set(),
                        y: []
                    };
                    uniqueKeysMap.set(item.x, keyObj);
                    uniqueKeys.push(keyObj);
                }
            });
            if (format === "array") {
                for (let j = 0; j < ser[i].data.length; j++) {
                    if (Array.isArray(ser[i].data[j])) {
                        rangeStart.push(ser[i].data[j][1][0]);
                        rangeEnd.push(ser[i].data[j][1][1]);
                    } else {
                        rangeStart.push(ser[i].data[j]);
                        rangeEnd.push(ser[i].data[j]);
                    }
                }
            } else if (format === "xy") {
                for (let j = 0; j < ser[i].data.length; j++) {
                    const isDataPoint2D = Array.isArray(ser[i].data[j].y);
                    const id = Utils$1.randomId();
                    const x = ser[i].data[j].x;
                    const y = {
                        y1: isDataPoint2D ? ser[i].data[j].y[0] : ser[i].data[j].y,
                        y2: isDataPoint2D ? ser[i].data[j].y[1] : ser[i].data[j].y,
                        rangeName: id
                    };
                    ser[i].data[j].rangeName = id;
                    const keyObj = uniqueKeysMap.get(x);
                    if (keyObj) {
                        keyObj.y.push(y);
                    }
                    rangeStart.push(y.y1);
                    rangeEnd.push(y.y2);
                }
            }
            return {
                start: rangeStart,
                end: rangeEnd,
                rangeUniques: uniqueKeys
            };
        }
        /**
         * @param {string} format
         * @param {any[]} ser
         * @param {number} i
         */
        handleCandleStickBoxDataFormat(format, ser, i) {
            const w = this.w;
            const isBoxPlot = w.config.chart.type === "boxPlot" || /** @type {Record<string,any>} */
                w.config.series[i].type === "boxPlot";
            const serO = [];
            const serH = [];
            const serM = [];
            const serL = [];
            const serC = [];
            const data = ser[i].data;
            let getVals;
            if (format === "array") {
                const isFlat = isBoxPlot && data[0].length === 6 || !isBoxPlot && data[0].length === 5;
                if (isFlat) {
                    getVals = (d) => d.slice(1);
                } else {
                    getVals = (d) => Array.isArray(d[1]) ? d[1] : [];
                }
            } else {
                getVals = (d) => Array.isArray(d.y) ? d.y : [];
            }
            for (let j = 0; j < data.length; j++) {
                const vals = getVals(data[j]);
                if (vals && vals.length >= 2) {
                    serO.push(vals[0]);
                    serH.push(vals[1]);
                    if (isBoxPlot) {
                        serM.push(vals[2]);
                        serL.push(vals[3]);
                        serC.push(vals[4]);
                    } else {
                        serL.push(vals[2]);
                        serC.push(vals[3]);
                    }
                }
            }
            return {
                o: serO,
                h: serH,
                m: serM,
                l: serL,
                c: serC
            };
        }
        /**
         * @param {any[]} ser
         */
        parseDataAxisCharts(ser) {
            var _a, _b, _c, _d;
            const cnf = this.w.config;
            const gl = this.w.globals;
            const dt = new DateTime(this.w);
            const xlabels = cnf.labels.length > 0 ? cnf.labels.slice() : cnf.xaxis.categories.slice();
            this.w.axisFlags.isRangeBar = cnf.chart.type === "rangeBar" && gl.isBarHorizontal;
            this.w.labelData.hasXaxisGroups = cnf.xaxis.type === "category" && cnf.xaxis.group.groups.length > 0;
            if (this.w.labelData.hasXaxisGroups) {
                this.w.labelData.groups = cnf.xaxis.group.groups;
            }
            ser.forEach((s, i) => {
                if (s.name !== void 0) {
                    this.w.seriesData.seriesNames.push(s.name);
                } else {
                    this.w.seriesData.seriesNames.push(
                        "series-" + parseInt(String(i + 1), 10)
                    );
                }
            });
            this.coreUtils.setSeriesYAxisMappings();
            const buckets = [];
            const groups = [
                ...new Set(cnf.series.map((s) => s.group))
            ];
            cnf.series.forEach((s, i) => {
                const index = groups.indexOf(s.group);
                if (!buckets[index]) buckets[index] = [];
                buckets[index].push(this.w.seriesData.seriesNames[i]);
            });
            this.w.labelData.seriesGroups = buckets;
            const handleDates = () => {
                for (let j = 0; j < xlabels.length; j++) {
                    if (typeof xlabels[j] === "string") {
                        const isDate = dt.isValidDate(xlabels[j]);
                        if (isDate) {
                            this.twoDSeriesX.push(dt.parseDate(xlabels[j]));
                        } else {
                            throw new Error(
                                "You have provided invalid Date format. Please provide a valid JavaScript Date"
                            );
                        }
                    } else {
                        this.twoDSeriesX.push(xlabels[j]);
                    }
                }
            };
            for (let i = 0; i < ser.length; i++) {
                this.twoDSeries = [];
                this.twoDSeriesX = [];
                this.threeDSeries = [];
                if (typeof ser[i].data === "undefined") {
                    console.error(
                        "It is a possibility that you may have not included 'data' property in series."
                    );
                    return;
                }
                const dr = cnf.chart.dataReducer;
                const rawStash = (_b = (_a = gl.dataReducerRawSeries) == null ? void 0 : _a[i]) == null ? void 0 : _b.data;
                if ((dr == null ? void 0 : dr.enabled) && this.isMultiFormat() && Array.isArray(rawStash) && rawStash.length > ((_c = dr.threshold) != null ? _c : 500)) {
                    const targetPoints = (_d = dr.targetPoints) != null ? _d : 250;
                    const xmin = cnf.xaxis.min;
                    const xmax = cnf.xaxis.max;
                    const windowed = xmin == null && xmax == null ? rawStash : Data.sliceByXRange(rawStash, xmin, xmax);
                    const reduced = windowed.length > targetPoints ? Data.lttbDownsample(windowed, targetPoints) : windowed;
                    ser[i] = __spreadProps(__spreadValues({}, ser[i]), {
                        data: reduced
                    });
                }
                if (cnf.chart.type === "rangeBar" || cnf.chart.type === "rangeArea" || ser[i].type === "rangeBar" || ser[i].type === "rangeArea") {
                    this.w.axisFlags.isRangeData = true;
                    this.handleRangeData(ser, i);
                }
                if (this.isMultiFormat()) {
                    if (this.isFormat2DArray()) {
                        this.handleFormat2DArray(ser, i);
                    } else if (this.isFormatXY()) {
                        this.handleFormatXY(ser, i);
                    }
                    if (cnf.chart.type === "candlestick" || ser[i].type === "candlestick" || cnf.chart.type === "boxPlot" || ser[i].type === "boxPlot") {
                        this.handleCandleStickBoxData(ser, i);
                    }
                    this.w.seriesData.series.push(this.twoDSeries);
                    this.w.labelData.labels.push(this.twoDSeriesX);
                    this.w.seriesData.seriesX.push(this.twoDSeriesX);
                    this.w.seriesData.seriesGoals = this.seriesGoals;
                    if (i === this.activeSeriesIndex && !this.fallbackToCategory) {
                        this.w.axisFlags.isXNumeric = true;
                    }
                } else {
                    if (cnf.xaxis.type === "datetime") {
                        this.w.axisFlags.isXNumeric = true;
                        handleDates();
                        this.w.seriesData.seriesX.push(this.twoDSeriesX);
                    } else if (cnf.xaxis.type === "numeric") {
                        this.w.axisFlags.isXNumeric = true;
                        if (xlabels.length > 0) {
                            this.twoDSeriesX = xlabels;
                            this.w.seriesData.seriesX.push(this.twoDSeriesX);
                        }
                    }
                    this.w.labelData.labels.push(this.twoDSeriesX);
                    const singleArray = ser[i].data.map(
                        (d) => Utils$1.parseNumber(d)
                    );
                    this.w.seriesData.series.push(singleArray);
                }
                this.w.seriesData.seriesZ.push(this.threeDSeries);
                if (ser[i].color !== void 0) {
                    this.w.seriesData.seriesColors.push(ser[i].color);
                } else {
                    this.w.seriesData.seriesColors.push(
                        /** @type {any} */
                        void 0
                    );
                }
            }
            return this.w;
        }
        /**
         * @param {any[]} ser
         */
        parseDataNonAxisCharts(ser) {
            const cnf = this.w.config;
            const hasOldFormat = Array.isArray(ser) && ser.every((s) => typeof s === "number") && cnf.labels.length > 0;
            const hasNewFormat = Array.isArray(ser) && ser.some(
                (s) => s && typeof s === "object" && s.data || s && typeof s === "object" && s.parsing
            );
            if (hasOldFormat && hasNewFormat) {
                console.warn(
                    "ApexCharts: Both old format (numeric series + labels) and new format (series objects with data/parsing) detected. Using old format for backward compatibility."
                );
            }
            if (hasOldFormat) {
                this.w.seriesData.series = /** @type {any} */
                    ser.slice();
                this.w.seriesData.seriesNames = cnf.labels.slice();
                for (let i = 0; i < this.w.seriesData.series.length; i++) {
                    if (this.w.seriesData.seriesNames[i] === void 0) {
                        this.w.seriesData.seriesNames.push("series-" + (i + 1));
                    }
                }
                return this.w;
            }
            if (Array.isArray(ser) && ser.every((s) => typeof s === "number")) {
                this.w.seriesData.series = /** @type {any} */
                    ser.slice();
                this.w.seriesData.seriesNames = [];
                for (let i = 0; i < this.w.seriesData.series.length; i++) {
                    this.w.seriesData.seriesNames.push(cnf.labels[i] || `series-${i + 1}`);
                }
                return this.w;
            }
            const processedData = this.extractPieDataFromSeries(ser);
            this.w.seriesData.series = processedData.values;
            this.w.seriesData.seriesNames = processedData.labels;
            if (cnf.chart.type === "radialBar") {
                this.w.seriesData.series = this.w.seriesData.series.map((val) => {
                    const numVal = Utils$1.parseNumber(val);
                    if (numVal > 100) {
                        console.warn(
                            `ApexCharts: RadialBar value ${numVal} > 100, consider using percentage values (0-100)`
                        );
                    }
                    return numVal;
                });
            }
            for (let i = 0; i < this.w.seriesData.series.length; i++) {
                if (this.w.seriesData.seriesNames[i] === void 0) {
                    this.w.seriesData.seriesNames.push("series-" + (i + 1));
                }
            }
            return this.w;
        }
        /**
         * Reset parsing flags to allow re-parsing of data during updates
         */
        resetParsingFlags() {
            const w = this.w;
            w.axisFlags.dataWasParsed = false;
            w.globals.originalSeries = null;
            if (w.config.series) {
                w.config.series.forEach((serie) => {
                    if (
                        /** @type {any} */
                        serie.__apexParsed
                    ) {
                        delete /** @type {any} */
                        serie.__apexParsed;
                    }
                });
            }
        }
        /**
         * @param {any[]} ser
         */
        extractPieDataFromSeries(ser) {
            const values = [];
            const labels = [];
            if (!Array.isArray(ser)) {
                console.warn("ApexCharts: Expected array for series data");
                return {
                    values: [],
                    labels: []
                };
            }
            if (ser.length === 0) {
                console.warn("ApexCharts: Empty series array");
                return {
                    values: [],
                    labels: []
                };
            }
            const firstItem = ser[0];
            if (typeof firstItem === "object" && firstItem !== null && firstItem.data) {
                this.extractPieDataFromSeriesObjects(ser, values, labels);
            } else {
                console.warn(
                    "ApexCharts: Unsupported series format for pie/donut/radialBar. Expected series objects with data property."
                );
                return {
                    values: [],
                    labels: []
                };
            }
            return {
                values,
                labels
            };
        }
        // Extract data from series objects: [{ data: [...], parsing: {...} }]
        /**
         * @param {any[]} seriesArray
         * @param {any[]} values
         * @param {any[]} labels
         */
        extractPieDataFromSeriesObjects(seriesArray, values, labels) {
            seriesArray.forEach((serie, serieIndex) => {
                if (!serie.data || !Array.isArray(serie.data)) {
                    console.warn(`ApexCharts: Series ${serieIndex} has no valid data array`);
                    return;
                }
                serie.data.forEach((dataPoint) => {
                    if (typeof dataPoint === "object" && dataPoint !== null) {
                        if (dataPoint.x !== void 0 && dataPoint.y !== void 0) {
                            labels.push(String(dataPoint.x));
                            values.push(Utils$1.parseNumber(dataPoint.y));
                        } else {
                            console.warn(
                                "ApexCharts: Invalid data point format for pie chart. Expected {x, y} format:",
                                dataPoint
                            );
                        }
                    } else {
                        console.warn(
                            "ApexCharts: Expected object data point, got:",
                            typeof dataPoint
                        );
                    }
                });
            });
        }
        /** User possibly set string categories in xaxis.categories or labels prop
         * Or didn't set xaxis labels at all - in which case we manually do it.
         * If user passed series data as [[3, 2], [4, 5]] or [{ x: 3, y: 55 }],
         * this shouldn't be called
         * @param {any[]} ser - the series which user passed to the config
         */
        handleExternalLabelsData(ser) {
            const cnf = this.w.config;
            if (cnf.xaxis.categories.length > 0) {
                this.w.labelData.labels = cnf.xaxis.categories;
            } else if (cnf.labels.length > 0) {
                this.w.labelData.labels = cnf.labels.slice();
            } else if (this.fallbackToCategory) {
                this.w.labelData.labels = /** @type {string[]} */
                    /** @type {unknown} */
                    this.w.labelData.labels[0];
                if (this.w.rangeData.seriesRange.length) {
                    this.w.rangeData.seriesRange.map((srt) => {
                        srt.forEach((sr) => {
                            if (this.w.labelData.labels.indexOf(sr.x) < 0 && sr.x) {
                                this.w.labelData.labels.push(sr.x);
                            }
                        });
                    });
                    const _labels = this.w.labelData.labels;
                    if (_labels.length > 0 && (typeof _labels[0] === "number" || typeof _labels[0] === "string")) {
                        this.w.labelData.labels = [...new Set(_labels)];
                    } else {
                        const _seen = /* @__PURE__ */ new Map();
                        for (const _label of _labels) {
                            const _key = JSON.stringify(_label);
                            if (!_seen.has(_key)) _seen.set(_key, _label);
                        }
                        this.w.labelData.labels = Array.from(_seen.values());
                    }
                }
                if (cnf.xaxis.convertedCatToNumeric) {
                    const defaults = new Defaults(cnf);
                    defaults.convertCatToNumericXaxis(cnf, this.w.seriesData.seriesX[0]);
                    this._generateExternalLabels(ser);
                }
            } else {
                this._generateExternalLabels(ser);
            }
        }
        /**
         * @param {any[]} ser
         */
        _generateExternalLabels(ser) {
            const gl = this.w.globals;
            const cnf = this.w.config;
            let labelArr = [];
            if (gl.axisCharts) {
                if (this.w.seriesData.series.length > 0) {
                    if (this.isFormatXY()) {
                        const seriesDataFiltered = cnf.series.map(
                            (serie) => {
                                const seen = /* @__PURE__ */ new Map();
                                for (const point of serie.data) {
                                    if (!seen.has(point.x)) seen.set(point.x, point);
                                }
                                return Array.from(seen.values());
                            }
                        );
                        const len = seriesDataFiltered.reduce(
                            (p, c, i, a) => a[p].length > c.length ? p : i,
                            0
                        );
                        for (let i = 0; i < seriesDataFiltered[len].length; i++) {
                            labelArr.push(i + 1);
                        }
                    } else {
                        for (let i = 0; i < this.w.seriesData.series[gl.maxValsInArrayIndex].length; i++) {
                            labelArr.push(i + 1);
                        }
                    }
                }
                this.w.seriesData.seriesX = [];
                for (let i = 0; i < ser.length; i++) {
                    this.w.seriesData.seriesX.push(labelArr);
                }
                if (!this.w.globals.isBarHorizontal) {
                    this.w.axisFlags.isXNumeric = true;
                }
            }
            if (labelArr.length === 0) {
                labelArr = gl.axisCharts ? [] : (
                    /**
                     * @param {Record<string, any>} gls
                     * @param {number} glsi
                     */
                    this.w.seriesData.series.map((gls, glsi) => {
                        return glsi + 1;
                    })
                );
                for (let i = 0; i < ser.length; i++) {
                    this.w.seriesData.seriesX.push(labelArr);
                }
            }
            this.w.labelData.labels = /** @type {string[]} */
                /** @type {unknown} */
                labelArr;
            if (cnf.xaxis.convertedCatToNumeric) {
                this.w.labelData.categoryLabels = labelArr.map((l) => {
                    return cnf.xaxis.labels.formatter(l);
                });
            }
            this.w.axisFlags.noLabelsProvided = true;
        }
        /**
         * @param {any[]} series
         */
        parseRawDataIfNeeded(series) {
            const cnf = this.w.config;
            const gl = this.w.globals;
            const globalParsing = cnf.parsing;
            if (this.w.axisFlags.dataWasParsed) {
                return series;
            }
            if (!globalParsing && !series.some((s) => s.parsing)) {
                return series;
            }
            const processedSeries = series.map((serie, index) => {
                var _a, _b, _c;
                if (!serie.data || !Array.isArray(serie.data) || serie.data.length === 0) {
                    return serie;
                }
                const effectiveParsing = {
                    x: ((_a = serie.parsing) == null ? void 0 : _a.x) || (globalParsing == null ? void 0 : globalParsing.x),
                    y: ((_b = serie.parsing) == null ? void 0 : _b.y) || (globalParsing == null ? void 0 : globalParsing.y),
                    z: ((_c = serie.parsing) == null ? void 0 : _c.z) || (globalParsing == null ? void 0 : globalParsing.z)
                };
                if (!effectiveParsing.x && !effectiveParsing.y) {
                    return serie;
                }
                const firstDataPoint = serie.data[0];
                if (typeof firstDataPoint === "object" && firstDataPoint !== null && (Object.prototype.hasOwnProperty.call(firstDataPoint, "x") || Object.prototype.hasOwnProperty.call(firstDataPoint, "y")) || Array.isArray(firstDataPoint)) {
                    return serie;
                }
                if (!effectiveParsing.x || !effectiveParsing.y || Array.isArray(effectiveParsing.y) && effectiveParsing.y.length === 0) {
                    console.warn(
                        `ApexCharts: Series ${index} has parsing config but missing x or y field specification`
                    );
                    return serie;
                }
                const transformedData = serie.data.map(
                    (item, itemIndex) => {
                        if (typeof item !== "object" || item === null) {
                            console.warn(
                                `ApexCharts: Series ${index}, data point ${itemIndex} is not an object, skipping parsing`
                            );
                            return item;
                        }
                        const x = this.getNestedValue(item, effectiveParsing.x);
                        let y;
                        let z = void 0;
                        if (Array.isArray(effectiveParsing.y)) {
                            const yValues = effectiveParsing.y.map(
                                (fieldName) => this.getNestedValue(item, fieldName)
                            );
                            if (this.w.config.chart.type === "bubble") {
                                if (yValues.length < 2) {
                                    console.warn(
                                        `ApexCharts: series[${index}] bubble chart requires parseData.y to have at least 2 fields (y and z). Got: ${JSON.stringify(effectiveParsing.y)}`
                                    );
                                }
                                y = yValues[0];
                            } else {
                                y = yValues;
                            }
                        } else {
                            y = this.getNestedValue(item, effectiveParsing.y);
                        }
                        if (effectiveParsing.z) {
                            z = this.getNestedValue(item, effectiveParsing.z);
                        }
                        if (x === void 0) {
                            console.warn(
                                `ApexCharts: Series ${index}, data point ${itemIndex} missing field '${effectiveParsing.x}'`
                            );
                        }
                        if (y === void 0) {
                            console.warn(
                                `ApexCharts: Series ${index}, data point ${itemIndex} missing field '${effectiveParsing.y}'`
                            );
                        }
                        const result = {
                            x,
                            y,
                            z: void 0
                        };
                        if (this.w.config.chart.type === "bubble" && Array.isArray(effectiveParsing.y) && effectiveParsing.y.length === 2) {
                            const zValue = this.getNestedValue(item, effectiveParsing.y[1]);
                            if (zValue !== void 0) {
                                result.z = zValue;
                            }
                        }
                        if (z !== void 0) {
                            result.z = z;
                        }
                        return result;
                    }
                );
                return __spreadProps(__spreadValues({}, serie), {
                    data: transformedData,
                    __apexParsed: true
                });
            });
            this.w.axisFlags.dataWasParsed = true;
            if (!gl.originalSeries) {
                gl.originalSeries = Utils$1.clone(series);
            }
            return processedSeries;
        }
        /**
         * Get nested object value using dot notation path
         * @param {Object} obj - The object to search in
         * @param {string} path - Dot notation path (e.g., 'user.profile.name')
         * @returns {*} The value at the path, or undefined if not found
         */
        getNestedValue(obj, path) {
            if (!obj || typeof obj !== "object" || !path) {
                return void 0;
            }
            if (path.indexOf(".") === -1) {
                return (
                    /** @type {any} */
                    obj[path]
                );
            }
            const keys = path.split(".");
            let current = obj;
            for (let i = 0; i < keys.length; i++) {
                if (current === null || current === void 0 || typeof current !== "object") {
                    return void 0;
                }
                current = /** @type {any} */
                    current[keys[i]];
            }
            return current;
        }
        // Segregate user provided data into appropriate vars
        /**
         * @param {any[]} ser
         */
        parseData(ser) {
            var _a, _b, _c, _d, _e, _f;
            const w = this.w;
            const cnf = w.config;
            const gl = w.globals;
            ser = this.parseRawDataIfNeeded(ser);
            if (((_a = cnf.chart.dataReducer) == null ? void 0 : _a.enabled) && gl.axisCharts && !gl.dataReducerRawSeries) {
                gl.dataReducerRawSeries = ser.map((s) => ({
                    data: Array.isArray(s == null ? void 0 : s.data) ? s.data.slice() : s == null ? void 0 : s.data
                }));
                let rawMinX = Infinity;
                let rawMaxX = -Infinity;
                for (const s of ser) {
                    const d = s == null ? void 0 : s.data;
                    if (!Array.isArray(d) || d.length === 0) continue;
                    const isXY = !Array.isArray(d[0]);
                    const firstX = isXY ? (_b = d[0]) == null ? void 0 : _b.x : (_c = d[0]) == null ? void 0 : _c[0];
                    const lastX = isXY ? (_d = d[d.length - 1]) == null ? void 0 : _d.x : (_e = d[d.length - 1]) == null ? void 0 : _e[0];
                    if (typeof firstX === "number") rawMinX = Math.min(rawMinX, firstX);
                    if (typeof lastX === "number") rawMaxX = Math.max(rawMaxX, lastX);
                }
                if (rawMinX !== Infinity) {
                    gl.dataReducerRawMinX = rawMinX;
                    gl.dataReducerRawMaxX = rawMaxX;
                }
            }
            cnf.series = ser;
            if (gl.dataReducerRawSeries && ((_f = cnf.chart.dataReducer) == null ? void 0 : _f.enabled)) {
                const stash = gl.dataReducerRawSeries;
                gl.initialSeries = ser.map((s, i) => {
                    var _a2, _b2, _c2;
                    return __spreadProps(__spreadValues({}, s), {
                        data: (_c2 = (_b2 = (_a2 = stash[i]) == null ? void 0 : _a2.data) == null ? void 0 : _b2.slice()) != null ? _c2 : s.data
                    });
                });
            } else {
                gl.initialSeries = Utils$1.clone(ser);
            }
            this.excludeCollapsedSeriesInYAxis();
            this.fallbackToCategory = false;
            this.resetGlobals();
            this.isMultipleY();
            if (gl.axisCharts) {
                this.parseDataAxisCharts(ser);
                this.coreUtils.getLargestSeries();
            } else {
                this.parseDataNonAxisCharts(ser);
            }
            if (cnf.chart.stacked) {
                const series = new Series(this.w);
                this.w.seriesData.series = series.setNullSeriesToZeroValues(
                    this.w.seriesData.series
                );
            }
            this.coreUtils.getSeriesTotals();
            if (gl.axisCharts) {
                this.w.seriesData.stackedSeriesTotals = this.coreUtils.getStackedSeriesTotals();
                this.w.seriesData.stackedSeriesTotalsByGroups = this.coreUtils.getStackedSeriesTotalsByGroups();
            }
            this.coreUtils.getPercentSeries();
            if (!this.w.axisFlags.dataFormatXNumeric && (!this.w.axisFlags.isXNumeric || cnf.xaxis.type === "numeric" && cnf.labels.length === 0 && cnf.xaxis.categories.length === 0)) {
                this.handleExternalLabelsData(ser);
            }
            const catLabels = this.coreUtils.getCategoryLabels(this.w.labelData.labels);
            for (let l = 0; l < catLabels.length; l++) {
                if (Array.isArray(catLabels[l])) {
                    this.w.axisFlags.isMultiLineX = true;
                    break;
                }
            }
            return {
                // w.seriesData (future slice)
                seriesData: {
                    series: this.w.seriesData.series,
                    seriesNames: this.w.seriesData.seriesNames,
                    seriesX: this.w.seriesData.seriesX,
                    seriesZ: this.w.seriesData.seriesZ,
                    seriesColors: this.w.seriesData.seriesColors,
                    seriesGoals: this.w.seriesData.seriesGoals,
                    initialSeries: gl.initialSeries,
                    originalSeries: gl.originalSeries,
                    stackedSeriesTotals: this.w.seriesData.stackedSeriesTotals,
                    stackedSeriesTotalsByGroups: this.w.seriesData.stackedSeriesTotalsByGroups,
                    noLabelsProvided: this.w.axisFlags.noLabelsProvided
                },
                // w.rangeData (future slice)
                rangeData: {
                    seriesRangeStart: this.w.rangeData.seriesRangeStart,
                    seriesRangeEnd: this.w.rangeData.seriesRangeEnd,
                    seriesRange: this.w.rangeData.seriesRange
                },
                // w.candleData (future slice)
                candleData: {
                    seriesCandleO: this.w.candleData.seriesCandleO,
                    seriesCandleH: this.w.candleData.seriesCandleH,
                    seriesCandleM: this.w.candleData.seriesCandleM,
                    seriesCandleL: this.w.candleData.seriesCandleL,
                    seriesCandleC: this.w.candleData.seriesCandleC
                },
                // w.labelData (future slice)
                labelData: {
                    labels: this.w.labelData.labels,
                    categoryLabels: this.w.labelData.categoryLabels
                },
                // w.axisFlags (future slice)
                axisFlags: {
                    isXNumeric: this.w.axisFlags.isXNumeric,
                    dataFormatXNumeric: this.w.axisFlags.dataFormatXNumeric,
                    isDataXYZ: this.w.axisFlags.isDataXYZ,
                    isRangeData: this.w.axisFlags.isRangeData,
                    isRangeBar: this.w.axisFlags.isRangeBar,
                    isMultiLineX: this.w.axisFlags.isMultiLineX,
                    dataWasParsed: this.w.axisFlags.dataWasParsed,
                    hasXaxisGroups: this.w.labelData.hasXaxisGroups,
                    groups: this.w.labelData.groups,
                    seriesGroups: this.w.labelData.seriesGroups
                }
            };
        }
        /**
         * Slice a sorted-by-x series to a [xmin, xmax] window using binary search.
         *
         * Pads with one extra point on each side so lines extend cleanly to the
         * chart edges. Either bound may be null/undefined to disable that side.
         *
         * @param {any[]} data - Series data in [{x,y}] or [[x,y]] format, sorted by x.
         * @param {number|null|undefined} xmin
         * @param {number|null|undefined} xmax
         * @returns {any[]} Sliced array (new array, never the input reference).
         */
        static sliceByXRange(data, xmin, xmax) {
            const len = data.length;
            if (len === 0) return data;
            const isXY = !Array.isArray(data[0]);
            const getX = isXY ? (p) => p.x : (p) => p[0];
            let lo = 0;
            if (xmin != null) {
                let l = 0;
                let r = len - 1;
                while (l <= r) {
                    const m = l + r >> 1;
                    if (getX(data[m]) < xmin) l = m + 1;
                    else r = m - 1;
                }
                lo = Math.max(0, l - 1);
            }
            let hi = len;
            if (xmax != null) {
                let l = 0;
                let r = len - 1;
                while (l <= r) {
                    const m = l + r >> 1;
                    if (getX(data[m]) > xmax) r = m - 1;
                    else l = m + 1;
                }
                hi = Math.min(len, l + 1);
            }
            return lo === 0 && hi === len ? data.slice() : data.slice(lo, hi);
        }
        /**
         * Largest-Triangle-Three-Bucket (LTTB) downsampling.
         *
         * Reduces `data` to `targetPoints` points while preserving the visual shape
         * of the series as perceived by the human eye.
         *
         * @param {any[]} data   - Raw series data in [{x,y}] or [[x,y]] format.
         * @param {number} targetPoints - Desired output length (>= 3).
         * @returns {any[]} Downsampled array in the same format as the input.
         */
        static lttbDownsample(data, targetPoints) {
            const len = data.length;
            if (targetPoints >= len || targetPoints < 3) return data;
            const isXY = !Array.isArray(data[0]);
            const getX = isXY ? (p) => p.x : (p) => p[0];
            const getY = isXY ? (p) => p.y : (p) => p[1];
            const sampled = [];
            sampled.push(data[0]);
            const bucketSize = (len - 2) / (targetPoints - 2);
            let a = 0;
            for (let i = 0; i < targetPoints - 2; i++) {
                const avgRangeStart = Math.floor((i + 1) * bucketSize) + 1;
                const avgRangeEnd = Math.min(Math.floor((i + 2) * bucketSize) + 1, len);
                let avgX = 0;
                let avgY = 0;
                const avgRangeLen = avgRangeEnd - avgRangeStart;
                for (let j = avgRangeStart; j < avgRangeEnd; j++) {
                    avgX += getX(data[j]);
                    avgY += getY(data[j]);
                }
                avgX /= avgRangeLen;
                avgY /= avgRangeLen;
                const rangeStart = Math.floor(i * bucketSize) + 1;
                const rangeEnd = Math.min(Math.floor((i + 1) * bucketSize) + 1, len);
                const pointAX = getX(data[a]);
                const pointAY = getY(data[a]);
                let maxArea = -1;
                let maxAreaIdx = rangeStart;
                for (let j = rangeStart; j < rangeEnd; j++) {
                    const area = Math.abs(
                        (pointAX - avgX) * (getY(data[j]) - pointAY) - (pointAX - getX(data[j])) * (avgY - pointAY)
                    ) * 0.5;
                    if (area > maxArea) {
                        maxArea = area;
                        maxAreaIdx = j;
                    }
                }
                sampled.push(data[maxAreaIdx]);
                a = maxAreaIdx;
            }
            sampled.push(data[len - 1]);
            return sampled;
        }
        excludeCollapsedSeriesInYAxis() {
            const w = this.w;
            const yAxisIndexes = [];
            w.globals.seriesYAxisMap.forEach((yAxisArr, yi) => {
                let collapsedCount = 0;
                yAxisArr.forEach((seriesIndex) => {
                    if (w.globals.collapsedSeriesIndices.indexOf(seriesIndex) !== -1) {
                        collapsedCount++;
                    }
                });
                if (collapsedCount > 0 && collapsedCount == yAxisArr.length) {
                    yAxisIndexes.push(yi);
                }
            });
            w.globals.ignoreYAxisIndexes = yAxisIndexes.map((x) => x);
        }
    }
    class UpdateHelpers {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {import('../../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
        }
        /**
         * private method to update Options.
         *
         * @param {Record<string, any>} options - A new config object can be passed which will be merged with the existing config object
         * @param {boolean} redraw - should redraw from beginning or should use existing paths and redraw from there
         * @param {boolean} animate - should animate or not on updating Options
         * @param {boolean} overwriteInitialConfig - should update the initial config or not
         */
        _updateOptions(options2, redraw = false, animate = true, updateSyncedCharts = true, overwriteInitialConfig = false) {
            return new Promise((resolve) => {
                let charts = [this.ctx];
                if (updateSyncedCharts) {
                    charts = this.ctx.getSyncedCharts();
                }
                if (this.w.globals.isExecCalled) {
                    charts = [this.ctx];
                    this.w.globals.isExecCalled = false;
                }
                charts.forEach((ch, chartIndex) => {
                    var _a, _b;
                    const w = ch.w;
                    w.globals.shouldAnimate = animate;
                    if (!redraw) {
                        w.globals.resized = true;
                        w.globals.dataChanged = true;
                        if (animate) {
                            ch.series.getPreviousPaths();
                        }
                    }
                    if (animate && options2 && typeof options2 === "object") {
                        const newType = (_a = options2 == null ? void 0 : options2.chart) == null ? void 0 : _a.type;
                        const fromType = w.config.chart.requestedType || w.config.chart.type;
                        if (newType && newType !== fromType) {
                            (_b = ch.morphTypeChange) == null ? void 0 : _b.captureBeforeDestroy({
                                fromType,
                                toType: newType,
                                newSeries: options2.series || w.config.series
                            });
                        }
                    }
                    if (options2 && typeof options2 === "object") {
                        ch.config = new Config(options2);
                        const incomingType = options2.chart && options2.chart.type;
                        const isAliasRequest = incomingType === "funnel" || incomingType === "pyramid" || incomingType === "gauge";
                        const wasAlias = !!w.config.chart.requestedType;
                        if (incomingType && !isAliasRequest && wasAlias) {
                            options2.chart = options2.chart || {};
                            options2.chart.requestedType = incomingType;
                            const prev = w.config.chart.requestedType;
                            if (prev === "funnel" || prev === "pyramid") {
                                options2.plotOptions = options2.plotOptions || {};
                                options2.plotOptions.bar = options2.plotOptions.bar || {};
                                if (options2.plotOptions.bar.isFunnel === void 0) {
                                    options2.plotOptions.bar.isFunnel = false;
                                }
                                if (options2.plotOptions.bar.isPyramid === void 0) {
                                    options2.plotOptions.bar.isPyramid = false;
                                }
                            }
                        }
                        ch.config.normalizeAliasedChartType(options2);
                        options2 = CoreUtils.extendArrayProps(ch.config, options2, w);
                        if (ch.w.globals.chartID !== this.w.globals.chartID) {
                            delete options2.series;
                        }
                        w.config = Utils$1.extend(w.config, options2);
                        if (overwriteInitialConfig) {
                            w.globals.lastXAxis = options2.xaxis ? Utils$1.clone(options2.xaxis) : [];
                            w.globals.lastYAxis = options2.yaxis ? Utils$1.clone(options2.yaxis) : [];
                            w.globals.initialConfig = Utils$1.extend({}, w.config);
                            w.globals.initialSeries = Utils$1.clone(w.config.series);
                            if (options2.series) {
                                for (let i = 0; i < w.globals.collapsedSeriesIndices.length; i++) {
                                    const series = w.config.series[w.globals.collapsedSeriesIndices[i]];
                                    w.globals.collapsedSeries[i].data = w.globals.axisCharts ? (
                                        /** @type {any} */
                                        series.data.slice()
                                    ) : series;
                                }
                                for (let i = 0; i < w.globals.ancillaryCollapsedSeriesIndices.length; i++) {
                                    const series = w.config.series[w.globals.ancillaryCollapsedSeriesIndices[i]];
                                    w.globals.ancillaryCollapsedSeries[i].data = w.globals.axisCharts ? (
                                        /** @type {any} */
                                        series.data.slice()
                                    ) : series;
                                }
                                ch.series.emptyCollapsedSeries(w.config.series);
                            }
                        }
                    }
                    return ch.update(options2).then(() => {
                        if (chartIndex === charts.length - 1) {
                            resolve(ch);
                        }
                    });
                });
            });
        }
        /**
         * Private method to update Series.
         *
         * @param {any[]} newSeries - New series which will override the existing
         * @param {boolean} animate
         */
        _updateSeries(newSeries, animate, overwriteInitialSeries = false) {
            return new Promise((resolve) => {
                const w = this.w;
                w.globals.shouldAnimate = animate;
                w.globals.dataChanged = true;
                PerformanceCache.invalidateSelectors(w);
                if (animate) {
                    this.ctx.series.getPreviousPaths();
                }
                const prevSeriesCount = w.config.series.length;
                w.globals.dataReducerRawSeries = null;
                this.ctx.data.resetParsingFlags();
                const parsedState = this.ctx.data.parseData(newSeries);
                this.ctx._writeParsedSeriesData(parsedState.seriesData);
                this.ctx._writeParsedRangeData(parsedState.rangeData);
                this.ctx._writeParsedCandleData(parsedState.candleData);
                this.ctx._writeParsedLabelData(parsedState.labelData);
                this.ctx._writeParsedAxisFlags(parsedState.axisFlags);
                if (overwriteInitialSeries) {
                    if (w.globals.initialConfig) {
                        w.globals.initialConfig.series = Utils$1.clone(w.config.series);
                    }
                    w.globals.initialSeries = Utils$1.clone(w.config.series);
                }
                if (this._canUseFastPath(newSeries, prevSeriesCount, w)) {
                    return this.ctx.fastUpdate(animate).then(() => {
                        resolve(this.ctx);
                    });
                }
                return this.ctx.update().then(() => {
                    resolve(this.ctx);
                });
            });
        }
        /**
         * Returns true if the data-only fast path can be used for this update.
         * Fast path skips rebuilding grid, axes, legend, annotations, and tooltip DOM.
         *
         * Requirements:
         * - Chart has been fully rendered (DOM exists)
         * - Axis chart (non-axis charts like pie always need full rebuild due to radial layout)
         * - Series count unchanged (grid column/row counts depend on it)
         * - No series currently collapsing (collapsed series changes visible data range)
         * - Not a combo chart (combo charts mix types and need coordinated axis recalc)
         * - Not currently zoomed (zoomed charts have altered x-labels that need recalculation)
         * @param {any[]} newSeries
         * @param {number} prevSeriesCount
         * @param {import('../../types/internal').ChartStateW} w
         */
        _canUseFastPath(newSeries, prevSeriesCount, w) {
            if (!w.dom.elGraphical) return false;
            if (!w.globals.axisCharts) return false;
            if (newSeries.length !== prevSeriesCount) return false;
            if (w.globals.collapsedSeries.length > 0) return false;
            if (w.globals.ancillaryCollapsedSeries.length > 0) return false;
            if (w.globals.risingSeries.length > 0) return false;
            if (w.globals.comboCharts) return false;
            if (w.interact.zoomed) return false;
            return true;
        }
        /**
         * @param {any} s
         * @param {number} i
         */
        _extendSeries(s, i) {
            const w = this.w;
            const ser = w.config.series[i];
            return __spreadProps(__spreadValues({},
                /** @type {Record<string,any>} */
                w.config.series[i]
            ), {
                name: s.name ? s.name : (
                    /** @type {any} */
                    ser == null ? void 0 : ser.name
                ),
                color: s.color ? s.color : (
                    /** @type {any} */
                    ser == null ? void 0 : ser.color
                ),
                type: s.type ? s.type : (
                    /** @type {any} */
                    ser == null ? void 0 : ser.type
                ),
                group: s.group ? s.group : (
                    /** @type {any} */
                    ser == null ? void 0 : ser.group
                ),
                hidden: typeof s.hidden !== "undefined" ? s.hidden : (
                    /** @type {any} */
                    ser == null ? void 0 : ser.hidden
                ),
                data: s.data ? s.data : (
                    /** @type {any} */
                    ser == null ? void 0 : ser.data
                ),
                zIndex: typeof s.zIndex !== "undefined" ? s.zIndex : i
            });
        }
        /**
         * @param {number} seriesIndex
         * @param {number} dataPointIndex
         */
        toggleDataPointSelection(seriesIndex, dataPointIndex) {
            const w = this.w;
            let elPath = null;
            const parent = `.apexcharts-series[data\\:realIndex='${seriesIndex}']`;
            if (w.globals.axisCharts) {
                elPath = w.dom.Paper.findOne(
                    `${parent} path[j='${dataPointIndex}'], ${parent} circle[j='${dataPointIndex}'], ${parent} rect[j='${dataPointIndex}']`
                );
            } else {
                if (typeof dataPointIndex === "undefined") {
                    elPath = w.dom.Paper.findOne(`${parent} path[j='${seriesIndex}']`);
                    if (w.config.chart.type === "pie" || w.config.chart.type === "polarArea" || w.config.chart.type === "donut") {
                        this.ctx.pie.pieClicked(seriesIndex);
                    }
                }
            }
            if (elPath) {
                const graphics = new Graphics(this.w);
                graphics.pathMouseDown(
                    elPath,
                    /** @type {any} */
                    null
                );
            } else {
                console.warn("toggleDataPointSelection: Element not found");
                return null;
            }
            return elPath.node ? elPath.node : null;
        }
        /**
         * @param {Record<string, any>} options
         */
        forceXAxisUpdate(options2) {
            const w = this.w;
            const minmax = ["min", "max"];
            minmax.forEach((a) => {
                if (typeof options2.xaxis[a] !== "undefined") {
                    w.config.xaxis[a] = options2.xaxis[a];
                    w.globals.lastXAxis[a] = options2.xaxis[a];
                }
            });
            if (options2.xaxis.categories && options2.xaxis.categories.length) {
                w.config.xaxis.categories = options2.xaxis.categories;
            }
            if (w.config.xaxis.convertedCatToNumeric) {
                const defaults = new Defaults(options2);
                options2 = defaults.convertCatToNumericXaxis(options2, this.ctx);
            }
            return options2;
        }
        /**
         * @param {Record<string, any>} options
         */
        forceYAxisUpdate(options2) {
            if (options2.chart && options2.chart.stacked && options2.chart.stackType === "100%") {
                if (Array.isArray(options2.yaxis)) {
                    options2.yaxis.forEach(
                        (yaxe, index) => {
                            options2.yaxis[index].min = 0;
                            options2.yaxis[index].max = 100;
                        }
                    );
                } else {
                    options2.yaxis.min = 0;
                    options2.yaxis.max = 100;
                }
            }
            return options2;
        }
        /**
         * This function reverts the yaxis and xaxis min/max values to what it was when the chart was defined.
         * This function fixes an important bug where a user might load a new series after zooming in/out of previous series which resulted in wrong min/max
         * Also, this should never be called internally on zoom/pan - the reset should only happen when user calls the updateSeries() function externally
         * The function also accepts an object {xaxis, yaxis} which when present is set as the new xaxis/yaxis
         * @param {Record<string, any>} opts
         */
        revertDefaultAxisMinMax(opts) {
            const w = this.w;
            let xaxis = w.globals.lastXAxis;
            let yaxis = w.globals.lastYAxis;
            if (opts && opts.xaxis) {
                xaxis = opts.xaxis;
            }
            if (opts && opts.yaxis) {
                yaxis = opts.yaxis;
            }
            const _xaxis = (
                /** @type {any} */
                xaxis
            );
            w.config.xaxis.min = _xaxis.min;
            w.config.xaxis.max = _xaxis.max;
            const getLastYAxis = (index) => {
                if (typeof yaxis[index] !== "undefined") {
                    const _y = (
                        /** @type {any} */
                        yaxis[index]
                    );
                    w.config.yaxis[index].min = _y.min;
                    w.config.yaxis[index].max = _y.max;
                }
            };
            w.config.yaxis.map((yaxe, index) => {
                if (w.interact.zoomed) {
                    getLastYAxis(index);
                } else {
                    if (typeof yaxis[index] !== "undefined") {
                        getLastYAxis(index);
                    } else {
                        if (typeof this.ctx.opts.yaxis[index] !== "undefined") {
                            yaxe.min = this.ctx.opts.yaxis[index].min;
                            yaxe.max = this.ctx.opts.yaxis[index].max;
                        }
                    }
                }
            });
        }
    }
    class Utils {
        /**
         * @param {import('./Tooltip').default} tooltipContext
         */
        constructor(tooltipContext) {
            this.w = tooltipContext.w;
            this.ttCtx = tooltipContext;
        }
        /**
         ** When hovering over series, you need to capture which series is being hovered on.
         ** This function will return both capturedseries index as well as inner index of that series
         * @memberof Utils
         * @param {{ hoverArea: any, elGrid: any, clientX: any, clientY: any, context?: any }} opts
         */
        getNearestValues({
            hoverArea,
            elGrid,
            clientX,
            clientY
        }) {
            var _a, _b;
            const w = this.w;
            const seriesBound = elGrid.getBoundingClientRect();
            const hoverWidth = seriesBound.width;
            const hoverHeight = seriesBound.height;
            let xDivisor = hoverWidth / (w.globals.dataPoints - 1);
            const yDivisor = hoverHeight / w.globals.dataPoints;
            const hasBars = this.hasBars();
            if ((w.globals.comboCharts || hasBars) && !w.config.xaxis.convertedCatToNumeric) {
                xDivisor = hoverWidth / w.globals.dataPoints;
            }
            const hoverX = clientX - seriesBound.left - w.globals.barPadForNumericAxis;
            const hoverY = clientY - seriesBound.top;
            const notInRect = hoverX < 0 || hoverY < 0 || hoverX > hoverWidth || hoverY > hoverHeight;
            if (notInRect) {
                hoverArea.classList.remove("hovering-zoom");
                hoverArea.classList.remove("hovering-pan");
            } else {
                if (w.interact.zoomEnabled) {
                    hoverArea.classList.remove("hovering-pan");
                    hoverArea.classList.add("hovering-zoom");
                } else if (w.interact.panEnabled) {
                    hoverArea.classList.remove("hovering-zoom");
                    hoverArea.classList.add("hovering-pan");
                }
            }
            let j = Math.round(hoverX / xDivisor);
            const jHorz = Math.floor(hoverY / yDivisor);
            if (hasBars && !w.config.xaxis.convertedCatToNumeric) {
                j = Math.ceil(hoverX / xDivisor);
                j = j - 1;
            }
            let capturedSeries = null;
            let closest = null;
            let seriesXValArr = w.globals.seriesXvalues.map(
                (seriesXVal) => {
                    return seriesXVal.filter(
                        (s) => Utils$1.isNumber(s)
                    );
                }
            );
            const seriesYValArr = w.globals.seriesYvalues.map(
                (seriesYVal) => {
                    return seriesYVal.filter(
                        (s) => Utils$1.isNumber(s)
                    );
                }
            );
            if (w.axisFlags.isXNumeric) {
                const chartGridEl = this.ttCtx.getElGrid();
                if (!chartGridEl) return {
                    hoverX,
                    hoverY
                };
                const chartGridElBoundingRect = chartGridEl.getBoundingClientRect();
                const transformedHoverX = hoverX * (chartGridElBoundingRect.width / hoverWidth);
                const transformedHoverY = hoverY * (chartGridElBoundingRect.height / hoverHeight);
                closest = this.closestInMultiArray(
                    transformedHoverX,
                    transformedHoverY,
                    seriesXValArr,
                    seriesYValArr
                );
                capturedSeries = closest.index;
                j = (_a = closest.j) != null ? _a : 0;
                if (capturedSeries !== null && w.globals.hasNullValues) {
                    seriesXValArr = w.globals.seriesXvalues[capturedSeries];
                    closest = this.closestInArray(transformedHoverX, seriesXValArr);
                    j = (_b = closest.j) != null ? _b : 0;
                }
            }
            w.interact.capturedSeriesIndex = capturedSeries === null ? -1 : capturedSeries;
            if (!j || j < 1) j = 0;
            if (w.globals.isBarHorizontal) {
                w.interact.capturedDataPointIndex = jHorz;
            } else {
                w.interact.capturedDataPointIndex = j;
            }
            return {
                capturedSeries,
                j: w.globals.isBarHorizontal ? jHorz : j,
                hoverX,
                hoverY
            };
        }
        /**
         * @param {any[]} Xarrays
         */
        getFirstActiveXArray(Xarrays) {
            const w = this.w;
            let activeIndex = 0;
            const firstActiveSeriesIndex = Xarrays.map(
                (xarr, index) => {
                    return xarr.length > 0 ? index : -1;
                }
            );
            for (let a = 0; a < firstActiveSeriesIndex.length; a++) {
                if (firstActiveSeriesIndex[a] !== -1 && w.globals.collapsedSeriesIndices.indexOf(a) === -1 && w.globals.ancillaryCollapsedSeriesIndices.indexOf(a) === -1) {
                    activeIndex = firstActiveSeriesIndex[a];
                    break;
                }
            }
            return activeIndex;
        }
        /**
         * @param {number} hoverX
         * @param {number} hoverY
         * @param {any[]} Xarrays
         * @param {any[]} Yarrays
         */
        closestInMultiArray(hoverX, hoverY, Xarrays, Yarrays) {
            const w = this.w;
            const isActiveSeries = (seriesIndex) => {
                return w.globals.collapsedSeriesIndices.indexOf(seriesIndex) === -1 && w.globals.ancillaryCollapsedSeriesIndices.indexOf(seriesIndex) === -1;
            };
            const chartType = w.config.chart.type;
            const isLineArea = !w.globals.comboCharts && (chartType === "line" || chartType === "area");
            let closestDist = Infinity;
            let closestSeriesIndex = null;
            let closestPointIndex = null;
            if (w.globals.allSeriesHasEqualX) {
                let bucketDistX = Infinity;
                for (let i = 0; i < Xarrays.length; i++) {
                    if (!isActiveSeries(i)) continue;
                    const xArr = Xarrays[i];
                    const yArr = Yarrays[i];
                    const len = Math.min(xArr.length, yArr.length);
                    for (let j = 0; j < len; j++) {
                        const distX = Math.abs(hoverX - xArr[j]);
                        if (distX < bucketDistX) {
                            bucketDistX = distX;
                            closestPointIndex = j;
                        }
                    }
                }
                if (closestPointIndex !== null) {
                    if (isLineArea) {
                        let bestSegDist = Infinity;
                        for (let i = 0; i < Xarrays.length; i++) {
                            if (!isActiveSeries(i)) continue;
                            const xArr = Xarrays[i];
                            const yArr = Yarrays[i];
                            const len = Math.min(xArr.length, yArr.length);
                            if (len < 2) {
                                const yVal = yArr[closestPointIndex];
                                if (typeof yVal !== "number") continue;
                                const d = Math.abs(hoverY - yVal);
                                if (d < bestSegDist) {
                                    bestSegDist = d;
                                    closestSeriesIndex = i;
                                }
                                continue;
                            }
                            for (let j = 0; j < len - 1; j++) {
                                const seg = this._distanceToSegment(
                                    hoverX,
                                    hoverY,
                                    xArr[j],
                                    yArr[j],
                                    xArr[j + 1],
                                    yArr[j + 1]
                                );
                                if (seg.dist < bestSegDist) {
                                    bestSegDist = seg.dist;
                                    closestSeriesIndex = i;
                                }
                            }
                        }
                    } else {
                        let bestY = Infinity;
                        for (let i = 0; i < Xarrays.length; i++) {
                            if (!isActiveSeries(i)) continue;
                            const yVal = Yarrays[i][closestPointIndex];
                            if (typeof yVal !== "number") continue;
                            const distY = Math.abs(hoverY - yVal);
                            if (distY < bestY) {
                                bestY = distY;
                                closestSeriesIndex = i;
                            }
                        }
                    }
                }
                return {
                    index: closestSeriesIndex,
                    j: closestPointIndex
                };
            }
            for (let i = 0; i < Xarrays.length; i++) {
                if (!isActiveSeries(i)) {
                    continue;
                }
                const xArr = Xarrays[i];
                const yArr = Yarrays[i];
                const len = Math.min(xArr.length, yArr.length);
                if (isLineArea && len >= 2) {
                    for (let j = 0; j < len - 1; j++) {
                        const seg = this._distanceToSegment(
                            hoverX,
                            hoverY,
                            xArr[j],
                            yArr[j],
                            xArr[j + 1],
                            yArr[j + 1]
                        );
                        if (seg.dist < closestDist) {
                            closestDist = seg.dist;
                            closestSeriesIndex = i;
                            closestPointIndex = seg.t < 0.5 ? j : j + 1;
                        }
                    }
                    continue;
                }
                for (let j = 0; j < len; j++) {
                    const xVal = xArr[j];
                    const distX = hoverX - xVal;
                    const yVal = yArr[j];
                    const distY = hoverY - yVal;
                    const dist = Math.sqrt(distX * distX + distY * distY);
                    if (dist < closestDist) {
                        closestDist = dist;
                        closestSeriesIndex = i;
                        closestPointIndex = j;
                    }
                }
            }
            return {
                index: closestSeriesIndex,
                j: closestPointIndex
            };
        }
        /**
         * Perpendicular distance from point (px, py) to the line segment
         * (ax, ay) → (bx, by). Returns the distance plus the projection
         * parameter t (0 = at A, 1 = at B, clamped) so callers know which
         * endpoint the projection landed nearest.
         * @param {number} px
         * @param {number} py
         * @param {number} ax
         * @param {number} ay
         * @param {number} bx
         * @param {number} by
         * @returns {{ dist: number, t: number }}
         */
        _distanceToSegment(px, py, ax, ay, bx, by) {
            const dx = bx - ax;
            const dy = by - ay;
            const lenSq = dx * dx + dy * dy;
            let t = lenSq === 0 ? 0 : ((px - ax) * dx + (py - ay) * dy) / lenSq;
            if (t < 0) t = 0;
            else if (t > 1) t = 1;
            const cx = ax + t * dx;
            const cy = ay + t * dy;
            const ex = px - cx;
            const ey = py - cy;
            return {
                dist: Math.sqrt(ex * ex + ey * ey),
                t
            };
        }
        /**
         * @param {number} val
         * @param {any[]} arr
         */
        closestInArray(val, arr) {
            const curr = arr[0];
            let currIndex = null;
            let diff = Math.abs(val - curr);
            for (let i = 0; i < arr.length; i++) {
                const newdiff = Math.abs(val - arr[i]);
                if (newdiff < diff) {
                    diff = newdiff;
                    currIndex = i;
                }
            }
            return {
                j: currIndex
            };
        }
        /**
         * When there are multiple series, it is possible to have different x values for each series.
         * But it may be possible in those multiple series, that there is same x value for 2 or more
         * series.
         * @memberof Utils
         * @param {number} j - the inner index of series (series[i][j])
         * @return {boolean}
         */
        isXoverlap(j) {
            const w = this.w;
            const xSameForAllSeriesJArr = [];
            const seriesX = w.seriesData.seriesX.filter(
                (s) => typeof s[0] !== "undefined"
            );
            if (seriesX.length > 0) {
                for (let i = 0; i < seriesX.length - 1; i++) {
                    if (typeof seriesX[i][j] !== "undefined" && typeof seriesX[i + 1][j] !== "undefined") {
                        if (seriesX[i][j] !== seriesX[i + 1][j]) {
                            xSameForAllSeriesJArr.push("unEqual");
                        }
                    }
                }
            }
            if (xSameForAllSeriesJArr.length === 0) {
                return true;
            }
            return false;
        }
        isInitialSeriesSameLen() {
            var _a, _b, _c;
            let sameLen = true;
            const initialSeries = (
                /** @type {any[]} */
                ((_a = this.w.globals.initialSeries) == null ? void 0 : _a.filter(
                    /**
                     * @param {Record<string, any>} s
                     * @param {number} i
                     */
                    (s, i) => {
                        var _a2;
                        return !((_a2 = this.w.globals.collapsedSeriesIndices) == null ? void 0 : _a2.includes(i));
                    }
                )) || []
            );
            for (let i = 0; i < initialSeries.length - 1; i++) {
                if (!((_b = initialSeries[i]) == null ? void 0 : _b.data) || !((_c = initialSeries[i + 1]) == null ? void 0 : _c.data)) return true;
                if (initialSeries[i].data.length !== initialSeries[i + 1].data.length) {
                    sameLen = false;
                    break;
                }
            }
            return sameLen;
        }
        /**
         * @param {any[]} allbars
         */
        getBarsHeight(allbars) {
            const bars = [...allbars];
            const totalHeight = bars.reduce((acc, bar) => acc + bar.getBBox().height, 0);
            return totalHeight;
        }
        /**
         * @param {number} capturedSeries
         */
        getElMarkers(capturedSeries) {
            if (typeof capturedSeries == "number") {
                return this.w.dom.baseEl.querySelectorAll(
                    `.apexcharts-series[data\\:realIndex='${capturedSeries}'] .apexcharts-series-markers-wrap > *`
                );
            }
            return this.w.dom.baseEl.querySelectorAll(
                ".apexcharts-series-markers-wrap > *"
            );
        }
        getAllMarkers(filterCollapsed = false) {
            let markersWraps = (
                /** @type {any[]} */
                [
                    ...this.w.dom.baseEl.querySelectorAll(".apexcharts-series-markers-wrap")
                ]
            );
            if (filterCollapsed) {
                markersWraps = markersWraps.filter((m) => {
                    const realIndex = Number(m.getAttribute("data:realIndex"));
                    return this.w.globals.collapsedSeriesIndices.indexOf(realIndex) === -1;
                });
            }
            markersWraps.sort((a, b) => {
                var indexA = Number(a.getAttribute("data:realIndex"));
                var indexB = Number(b.getAttribute("data:realIndex"));
                return indexB < indexA ? 1 : indexB > indexA ? -1 : 0;
            });
            const markers = [];
            markersWraps.forEach((m) => {
                markers.push(m.querySelector(".apexcharts-marker"));
            });
            return markers;
        }
        /**
         * @param {number} capturedSeries
         */
        hasMarkers(capturedSeries) {
            const markers = this.getElMarkers(capturedSeries);
            return markers.length > 0;
        }
        /**
         * @param {any} point
         * @param {number} size
         */
        getPathFromPoint(point, size) {
            const cx = Number(point.getAttribute("cx"));
            const cy = Number(point.getAttribute("cy"));
            const shape = point.getAttribute("shape");
            return new Graphics(this.w).getMarkerPath(cx, cy, shape, size);
        }
        getElBars() {
            return this.w.dom.baseEl.querySelectorAll(
                ".apexcharts-bar-series,  .apexcharts-candlestick-series, .apexcharts-boxPlot-series, .apexcharts-rangebar-series"
            );
        }
        hasBars() {
            const bars = this.getElBars();
            return bars.length > 0;
        }
        /**
         * @param {number} index
         */
        getHoverMarkerSize(index) {
            const w = this.w;
            let hoverSize = w.config.markers.hover.size;
            if (hoverSize === void 0) {
                hoverSize = w.globals.markers.size[index] + w.config.markers.hover.sizeOffset;
            }
            return hoverSize;
        }
        /**
         * @param {string} state
         */
        toggleAllTooltipSeriesGroups(state) {
            const w = this.w;
            const ttCtx = this.ttCtx;
            if (ttCtx.allTooltipSeriesGroups.length === 0) {
                ttCtx.allTooltipSeriesGroups = w.dom.baseEl.querySelectorAll(
                    ".apexcharts-tooltip-series-group"
                );
            }
            const allTooltipSeriesGroups = ttCtx.allTooltipSeriesGroups;
            for (let i = 0; i < allTooltipSeriesGroups.length; i++) {
                if (state === "enable") {
                    allTooltipSeriesGroups[i].classList.add("apexcharts-active");
                    allTooltipSeriesGroups[i].style.display = w.config.tooltip.items.display;
                } else {
                    allTooltipSeriesGroups[i].classList.remove("apexcharts-active");
                    allTooltipSeriesGroups[i].style.display = "none";
                }
            }
        }
    }
    class Labels {
        /**
         * @param {import('./Tooltip').default} tooltipContext
         */
        constructor(tooltipContext) {
            this.w = tooltipContext.w;
            this.ttCtx = tooltipContext;
            this.tooltipUtil = new Utils(tooltipContext);
        }
        /** @param {{ shared?: boolean, ttItems?: any, i?: number, j?: any, y1?: any, y2?: any, e?: any }} opts */
        drawSeriesTexts({
            shared = true,
            ttItems,
            i = 0,
            j = null,
            y1,
            y2,
            e
        }) {
            const w = this.w;
            if (w.config.tooltip.custom !== void 0) {
                this.handleCustomTooltip({
                    i,
                    j,
                    y1,
                    y2,
                    w
                });
            } else {
                this.toggleActiveInactiveSeries(shared, i);
            }
            const values = this.getValuesToPrint({
                i,
                j
            });
            this.printLabels({
                i,
                j,
                values,
                ttItems,
                shared,
                e
            });
            const tooltipEl = this.ttCtx.getElTooltip();
            if (tooltipEl) {
                this.ttCtx.tooltipRect.ttWidth = tooltipEl.getBoundingClientRect().width;
                this.ttCtx.tooltipRect.ttHeight = tooltipEl.getBoundingClientRect().height;
            }
        }
        /** @param {{i: any, j: any, values: any, ttItems: any, shared: any, e: any}} opts */
        printLabels({
            i,
            j,
            values,
            ttItems,
            shared,
            e
        }) {
            const w = this.w;
            const {
                xVal,
                zVal,
                xAxisTTVal
            } = values;
            const seriesLen = w.seriesData.series.length;
            const basePColor = j !== null && w.config.plotOptions.bar.distributed ? w.globals.colors[j] : w.globals.colors[i];
            for (let t = 0; t < seriesLen; t++) {
                const tIndex = w.config.tooltip.inverseOrder ? seriesLen - 1 - t : t;
                const row = this.computeSeriesRow({
                    i,
                    j,
                    t,
                    tIndex,
                    shared,
                    e,
                    basePColor
                });
                this.DOMHandling({
                    i,
                    t: tIndex,
                    j,
                    ttItems,
                    values: {
                        val: row.val,
                        goalVals: row.goalVals,
                        xVal,
                        xAxisTTVal,
                        zVal
                    },
                    seriesName: row.seriesName,
                    shared,
                    pColor: row.pColor
                });
            }
        }
        /**
         * Compute the per-series row values (seriesName, val, goalVals, pColor)
         * for one iteration of the tooltip's series loop. Extracted from
         * printLabels() to keep the outer loop scannable.
         * @param {{i: number, j: any, t: number, tIndex: number, shared: boolean, e: any, basePColor: string}} opts
         */
        computeSeriesRow({
            i,
            j,
            tIndex,
            shared,
            e,
            basePColor
        }) {
            const w = this.w;
            let f = this.getFormatters(i);
            let pColor = basePColor;
            let val;
            let goalVals = (
                /** @type {any[]} */
                []
            );
            let seriesName = w.config.chart.type === "treemap" ? f.yLbTitleFormatter(
                String(
                    /** @type {any} */
                    w.config.series[i].data[j].x
                ), {
                    series: w.seriesData.series,
                    seriesIndex: i,
                    dataPointIndex: j,
                    w
                }
            ) : this.getSeriesName({
                fn: f.yLbTitleFormatter,
                index: i,
                seriesIndex: i,
                j
            });
            if (w.globals.axisCharts) {
                if (shared) {
                    f = this.getFormatters(tIndex);
                    seriesName = this.getSeriesName({
                        fn: f.yLbTitleFormatter,
                        index: tIndex,
                        seriesIndex: i,
                        j
                    });
                    pColor = w.globals.colors[tIndex];
                    val = this.formatYValue(f, tIndex, j);
                    goalVals = this.formatGoalVals(f, tIndex, j);
                } else {
                    pColor = this.resolvePatternColor(e, pColor);
                    val = this.formatYValue(f, i, j);
                    goalVals = this.formatGoalVals(f, i, j);
                }
            }
            if (j === null) {
                val = f.yLbFormatter(w.seriesData.series[i], __spreadProps(__spreadValues({}, w), {
                    seriesIndex: i,
                    dataPointIndex: i
                }));
            }
            return {
                seriesName,
                val,
                goalVals,
                pColor
            };
        }
        /**
         * Run the y-value formatter for a given (seriesIndex, dataPointIndex),
         * handling the range-data case (start - end concatenation).
         * @param {{yLbFormatter: Function}} f
         * @param {number} index
         * @param {any} j
         */
        formatYValue(f, index, j) {
            var _a, _b, _c, _d;
            const w = this.w;
            if (w.axisFlags.isRangeData) {
                return f.yLbFormatter((_b = (_a = w.rangeData.seriesRangeStart) == null ? void 0 : _a[index]) == null ? void 0 : _b[j], {
                    series: w.rangeData.seriesRangeStart,
                    seriesIndex: index,
                    dataPointIndex: j,
                    w
                }) + " - " + f.yLbFormatter((_d = (_c = w.rangeData.seriesRangeEnd) == null ? void 0 : _c[index]) == null ? void 0 : _d[j], {
                    series: w.rangeData.seriesRangeEnd,
                    seriesIndex: index,
                    dataPointIndex: j,
                    w
                });
            }
            return f.yLbFormatter(w.seriesData.series[index][j], {
                series: w.seriesData.series,
                seriesIndex: index,
                dataPointIndex: j,
                w
            });
        }
        /**
         * Format the goal-line values attached to a given (seriesIndex, dataPointIndex).
         * Returns an empty array when no goals exist.
         * @param {{yLbFormatter: Function}} f
         * @param {number} index
         * @param {any} j
         */
        formatGoalVals(f, index, j) {
            var _a;
            const w = this.w;
            const goals = (_a = w.seriesData.seriesGoals[index]) == null ? void 0 : _a[j];
            if (!Array.isArray(goals)) return [];
            return goals.map((goal) => ({
                attrs: goal,
                val: f.yLbFormatter(goal.value, {
                    seriesIndex: index,
                    dataPointIndex: j,
                    w
                })
            }));
        }
        /**
         * When the hovered element has a pattern fill (url(#…Pattern…)), reach
         * into the pattern's first child to pull a stroke color. Otherwise
         * return the raw fill attribute or the fallback.
         * @param {any} e
         * @param {string} fallback
         */
        resolvePatternColor(e, fallback) {
            var _a, _b, _c;
            const w = this.w;
            const targetFill = (_a = e == null ? void 0 : e.target) == null ? void 0 : _a.getAttribute("fill");
            if (!targetFill) return fallback;
            if (targetFill.indexOf("url") === -1) return targetFill;
            if (targetFill.indexOf("Pattern") === -1) return fallback;
            const patternEl = w.dom.baseEl.querySelector(
                targetFill.substr(4).slice(0, -1)
            );
            return (_c = (_b = patternEl == null ? void 0 : patternEl.childNodes[0]) == null ? void 0 : _b.getAttribute("stroke")) != null ? _c : fallback;
        }
        /**
         * @param {number} i
         */
        getFormatters(i) {
            const w = this.w;
            let yLbFormatter = w.formatters.yLabelFormatters[i];
            let yLbTitleFormatter;
            if (w.formatters.ttVal !== void 0) {
                if (Array.isArray(w.formatters.ttVal)) {
                    yLbFormatter = /** @type {any} */
                        w.formatters.ttVal[i] && /** @type {any} */
                        w.formatters.ttVal[i].formatter;
                    yLbTitleFormatter = /** @type {any} */
                        w.formatters.ttVal[i] && /** @type {any} */
                        w.formatters.ttVal[i].title && /** @type {any} */
                        w.formatters.ttVal[i].title.formatter;
                } else {
                    yLbFormatter = /** @type {any} */
                        w.formatters.ttVal.formatter;
                    if (typeof /** @type {any} */ w.formatters.ttVal.title.formatter === "function") {
                        yLbTitleFormatter = /** @type {any} */
                            w.formatters.ttVal.title.formatter;
                    }
                }
            } else {
                yLbTitleFormatter = w.config.tooltip.y.title.formatter;
            }
            if (typeof yLbFormatter !== "function") {
                if (w.formatters.yLabelFormatters[0]) {
                    yLbFormatter = w.formatters.yLabelFormatters[0];
                } else {
                    yLbFormatter = function(label) {
                        return label;
                    };
                }
            }
            if (typeof yLbTitleFormatter !== "function") {
                yLbTitleFormatter = function(label) {
                    return label ? label + ": " : "";
                };
            }
            return {
                yLbFormatter,
                yLbTitleFormatter
            };
        }
        /** @param {{fn: any, index: any, seriesIndex: any, j: any}} opts */
        getSeriesName({
            fn,
            index,
            seriesIndex,
            j
        }) {
            const w = this.w;
            return fn(String(w.seriesData.seriesNames[index]), {
                series: w.seriesData.series,
                seriesIndex,
                dataPointIndex: j,
                w
            });
        }
        /** @param {{ t?: any, j?: any, i?: any, ttItems?: any, values?: any, seriesName?: any, shared?: any, pColor?: any }} opts */
        DOMHandling({
            t,
            j,
            ttItems,
            values,
            seriesName,
            shared,
            pColor
        }) {
            const w = this.w;
            const ttCtx = this.ttCtx;
            const {
                val,
                goalVals,
                xVal,
                xAxisTTVal,
                zVal
            } = values;
            let ttItemsChildren = null;
            ttItemsChildren = ttItems[t].children;
            if (w.config.tooltip.fillSeriesColor) {
                ttItems[t].style.backgroundColor = pColor;
                ttItemsChildren[0].style.display = "none";
            }
            if (ttCtx.showTooltipTitle) {
                if (ttCtx.tooltipTitle === null) {
                    ttCtx.tooltipTitle = w.dom.baseEl.querySelector(
                        ".apexcharts-tooltip-title"
                    );
                }
                if (ttCtx.tooltipTitle) {
                    ttCtx.tooltipTitle.innerHTML = xVal;
                }
            }
            if (ttCtx.isXAxisTooltipEnabled) {
                if (ttCtx.xaxisTooltipText) {
                    ttCtx.xaxisTooltipText.innerHTML = xAxisTTVal !== "" ? xAxisTTVal : xVal;
                }
            }
            const ttYLabel = ttItems[t].querySelector(
                ".apexcharts-tooltip-text-y-label"
            );
            if (ttYLabel) {
                ttYLabel.innerHTML = seriesName ? seriesName : "";
            }
            const ttYVal = ttItems[t].querySelector(".apexcharts-tooltip-text-y-value");
            if (ttYVal) {
                ttYVal.innerHTML = typeof val !== "undefined" ? val : "";
            }
            if (ttItemsChildren[0] && ttItemsChildren[0].classList.contains("apexcharts-tooltip-marker")) {
                if (w.config.tooltip.marker.fillColors && Array.isArray(w.config.tooltip.marker.fillColors)) {
                    pColor = w.config.tooltip.marker.fillColors[t];
                }
                if (w.config.tooltip.fillSeriesColor) {
                    ttItemsChildren[0].style.backgroundColor = pColor;
                } else {
                    ttItemsChildren[0].style.color = pColor;
                }
            }
            if (!w.config.tooltip.marker.show) {
                ttItemsChildren[0].style.display = "none";
            }
            const ttGLabel = ttItems[t].querySelector(
                ".apexcharts-tooltip-text-goals-label"
            );
            const ttGVal = ttItems[t].querySelector(
                ".apexcharts-tooltip-text-goals-value"
            );
            if (goalVals.length && w.seriesData.seriesGoals[t]) {
                const createGoalsHtml = () => {
                    let gLabels = "<div>";
                    let gVals = "<div>";
                    goalVals.forEach((goal) => {
                        gLabels += ` <div style="display: flex"><span class="apexcharts-tooltip-marker" style="background-color: ${goal.attrs.strokeColor}; height: 3px; border-radius: 0; top: 5px;"></span> ${goal.attrs.name}</div>`;
                        gVals += `<div>${goal.val}</div>`;
                    });
                    ttGLabel.innerHTML = gLabels + `</div>`;
                    ttGVal.innerHTML = gVals + `</div>`;
                };
                if (shared) {
                    if (w.seriesData.seriesGoals[t][j] && Array.isArray(w.seriesData.seriesGoals[t][j])) {
                        createGoalsHtml();
                    } else {
                        ttGLabel.innerHTML = "";
                        ttGVal.innerHTML = "";
                    }
                } else {
                    createGoalsHtml();
                }
            } else {
                ttGLabel.innerHTML = "";
                ttGVal.innerHTML = "";
            }
            if (zVal !== null) {
                const ttZLabel = ttItems[t].querySelector(
                    ".apexcharts-tooltip-text-z-label"
                );
                ttZLabel.innerHTML = w.config.tooltip.z.title;
                const ttZVal = ttItems[t].querySelector(
                    ".apexcharts-tooltip-text-z-value"
                );
                ttZVal.innerHTML = typeof zVal !== "undefined" ? zVal : "";
            }
            if (shared && ttItemsChildren[0]) {
                if (w.config.tooltip.hideEmptySeries) {
                    const ttItemMarker = ttItems[t].querySelector(
                        ".apexcharts-tooltip-marker"
                    );
                    const ttItemText = ttItems[t].querySelector(".apexcharts-tooltip-text");
                    if (parseFloat(val) == 0) {
                        ttItemMarker.style.display = "none";
                        ttItemText.style.display = "none";
                    } else {
                        ttItemMarker.style.display = "block";
                        ttItemText.style.display = "block";
                    }
                }
                if (typeof val === "undefined" || val === null || w.globals.ancillaryCollapsedSeriesIndices.indexOf(t) > -1 || w.globals.collapsedSeriesIndices.indexOf(t) > -1 || Array.isArray(ttCtx.tConfig.enabledOnSeries) && ttCtx.tConfig.enabledOnSeries.indexOf(t) === -1) {
                    ttItemsChildren[0].parentNode.style.display = "none";
                } else {
                    ttItemsChildren[0].parentNode.style.display = w.config.tooltip.items.display;
                }
            } else {
                if (Array.isArray(ttCtx.tConfig.enabledOnSeries) && ttCtx.tConfig.enabledOnSeries.indexOf(t) === -1) {
                    ttItemsChildren[0].parentNode.style.display = "none";
                }
            }
        }
        /**
         * @param {boolean} shared
         * @param {number} i
         */
        toggleActiveInactiveSeries(shared, i) {
            const w = this.w;
            if (shared) {
                this.tooltipUtil.toggleAllTooltipSeriesGroups("enable");
            } else {
                this.tooltipUtil.toggleAllTooltipSeriesGroups("disable");
                const firstTooltipSeriesGroup = w.dom.baseEl.querySelector(
                    `.apexcharts-tooltip-series-group-${i}`
                );
                if (firstTooltipSeriesGroup) {
                    const ftsGroup = (
                        /** @type {HTMLElement} */
                        firstTooltipSeriesGroup
                    );
                    ftsGroup.classList.add("apexcharts-active");
                    ftsGroup.style.display = w.config.tooltip.items.display;
                }
            }
        }
        /** @param {{i: any, j: any}} opts */
        getValuesToPrint({
            i,
            j
        }) {
            var _a, _b, _c, _d, _e, _f, _g, _h;
            const w = this.w;
            const filteredSeriesX = w.seriesData.seriesX.map(
                (ser) => ser.length > 0 ? ser : []
            );
            let xVal = "";
            let xAxisTTVal = "";
            let zVal = null;
            let val = null;
            const customFormatterOpts = {
                series: w.seriesData.series,
                seriesIndex: i,
                dataPointIndex: j,
                w
            };
            const zFormatter = w.formatters.ttZFormatter;
            if (j === null) {
                val = w.seriesData.series[i];
            } else {
                if (w.axisFlags.isXNumeric && w.config.chart.type !== "treemap") {
                    xVal = filteredSeriesX[i][j];
                    if (filteredSeriesX[i].length === 0) {
                        const firstActiveSeriesIndex = this.tooltipUtil.getFirstActiveXArray(filteredSeriesX);
                        xVal = filteredSeriesX[firstActiveSeriesIndex][j];
                    }
                } else {
                    const dataFormat = new Data(this.w);
                    if (dataFormat.isFormatXY()) {
                        xVal = typeof /** @type {any} */
                        w.config.series[i].data[j] !== "undefined" ? (
                            /** @type {any} */
                            w.config.series[i].data[j].x
                        ) : "";
                    } else {
                        xVal = typeof w.labelData.labels[j] !== "undefined" ? w.labelData.labels[j] : "";
                    }
                }
            }
            const bufferXVal = xVal;
            if (w.axisFlags.isXNumeric && w.config.xaxis.type === "datetime") {
                const xFormat = new Formatters(this.w);
                xVal = xFormat.xLabelFormat(
                    /** @type {Function} */
                    w.formatters.ttKeyFormatter,
                    bufferXVal,
                    bufferXVal, {
                        i: void 0,
                        dateFormatter: new DateTime(this.w).formatDate,
                        w: this.w
                    }
                );
            } else {
                if (w.globals.isBarHorizontal) {
                    xVal = w.formatters.yLabelFormatters[0](bufferXVal, customFormatterOpts);
                } else {
                    xVal = (_c = (_b = (_a = w.formatters).xLabelFormatter) == null ? void 0 : _b.call(_a, bufferXVal, customFormatterOpts)) != null ? _c : bufferXVal;
                }
            }
            if (w.config.tooltip.x.formatter !== void 0) {
                xVal = (_f = (_e = (_d = w.formatters).ttKeyFormatter) == null ? void 0 : _e.call(_d, bufferXVal, customFormatterOpts)) != null ? _f : bufferXVal;
            }
            if (w.seriesData.seriesZ.length > 0 && w.seriesData.seriesZ[i].length > 0) {
                zVal = zFormatter == null ? void 0 : zFormatter(w.seriesData.seriesZ[i][j], w);
            }
            if (typeof w.config.xaxis.tooltip.formatter === "function") {
                xAxisTTVal = (_h = (_g = w.formatters).xaxisTooltipFormatter) == null ? void 0 : _h.call(
                    _g,
                    bufferXVal,
                    customFormatterOpts
                );
            } else {
                xAxisTTVal = xVal;
            }
            return {
                val: Array.isArray(val) ? val.join(" ") : val,
                xVal: Array.isArray(xVal) ? xVal.join(" ") : xVal,
                xAxisTTVal: Array.isArray(xAxisTTVal) ? xAxisTTVal.join(" ") : xAxisTTVal,
                zVal
            };
        }
        /** @param {{i: any, j: any, y1: any, y2: any, w: any}} opts */
        handleCustomTooltip({
            i,
            j,
            y1,
            y2,
            w
        }) {
            const tooltipEl = this.ttCtx.getElTooltip();
            let fn = w.config.tooltip.custom;
            if (Array.isArray(fn) && fn[i]) {
                fn = fn[i];
            }
            const customTooltip = fn({
                series: w.seriesData.series,
                seriesIndex: i,
                dataPointIndex: j,
                y1,
                y2,
                w
            });
            if (tooltipEl) {
                if (typeof customTooltip === "string" || typeof customTooltip === "number") {
                    tooltipEl.innerHTML = String(customTooltip);
                } else if (customTooltip instanceof Element || typeof customTooltip.nodeName === "string") {
                    tooltipEl.innerHTML = "";
                    tooltipEl.appendChild(customTooltip.cloneNode(true));
                }
            }
        }
    }
    class Position {
        /**
         * @param {import('./Tooltip').default} tooltipContext
         */
        constructor(tooltipContext) {
            this.ttCtx = tooltipContext;
            this.w = tooltipContext.w;
        }
        /**
         * This will move the crosshair (the vertical/horz line that moves along with mouse)
         * Along with this, this function also calls the xaxisMove function
         * @memberof Position
         * @param {number} cx - point's x position, wherever point's x is, you need to move crosshair
         * @param {number | null} [j]
         */
        moveXCrosshairs(cx, j = null) {
            const ttCtx = this.ttCtx;
            const w = this.w;
            const xcrosshairs = ttCtx.getElXCrosshairs();
            let x = cx - ttCtx.xcrosshairsWidth / 2;
            const tickAmount = w.labelData.labels.slice().length;
            if (j !== null) {
                x = w.layout.gridWidth / tickAmount * j;
            }
            if (xcrosshairs !== null && !w.globals.isBarHorizontal) {
                xcrosshairs.setAttribute("x", String(x));
                xcrosshairs.setAttribute("x1", String(x));
                xcrosshairs.setAttribute("x2", String(x));
                xcrosshairs.setAttribute("y2", String(w.layout.gridHeight));
                xcrosshairs.classList.add("apexcharts-active");
            }
            if (x < 0) {
                x = 0;
            }
            if (x > w.layout.gridWidth) {
                x = w.layout.gridWidth;
            }
            if (ttCtx.isXAxisTooltipEnabled) {
                let tx = x;
                if (w.config.xaxis.crosshairs.width === "tickWidth" || w.config.xaxis.crosshairs.width === "barWidth") {
                    tx = x + ttCtx.xcrosshairsWidth / 2;
                }
                this.moveXAxisTooltip(tx);
            }
        }
        /**
         * This will move the crosshair (the vertical/horz line that moves along with mouse)
         * Along with this, this function also calls the xaxisMove function
         * @memberof Position
         * @param {number} cy - point's y position, wherever point's y is, you need to move crosshair
         */
        moveYCrosshairs(cy) {
            const ttCtx = this.ttCtx;
            if (ttCtx.ycrosshairs !== null) {
                Graphics.setAttrs(ttCtx.ycrosshairs, {
                    y1: cy,
                    y2: cy
                });
            }
            if (ttCtx.ycrosshairsHidden !== null) {
                Graphics.setAttrs(ttCtx.ycrosshairsHidden, {
                    y1: cy,
                    y2: cy
                });
            }
        }
        /**
         ** AxisTooltip is the small rectangle which appears on x axis with x value, when user moves
         * @memberof Position
         * @param {number} cx - point's x position, wherever point's x is, you need to move
         */
        moveXAxisTooltip(cx) {
            var _a, _b;
            const w = this.w;
            const ttCtx = this.ttCtx;
            if (ttCtx.xaxisTooltip !== null && ttCtx.xcrosshairsWidth !== 0) {
                ttCtx.xaxisTooltip.classList.add("apexcharts-active");
                const cy = ttCtx.xaxisOffY + w.config.xaxis.tooltip.offsetY + w.layout.translateY + 5 + w.config.xaxis.offsetY;
                const xaxisTTText = ttCtx.xaxisTooltip.getBoundingClientRect();
                const xaxisTTTextWidth = xaxisTTText.width;
                cx = cx - xaxisTTTextWidth / 2;
                if (!isNaN(cx)) {
                    cx = cx + w.layout.translateX;
                    const graphics = new Graphics(this.w);
                    const textRect = graphics.getTextRects(
                        (_b = (_a = ttCtx.xaxisTooltipText) == null ? void 0 : _a.innerHTML) != null ? _b : "",
                        w.config.xaxis.labels.style.fontSize
                    );
                    if (ttCtx.xaxisTooltipText) {
                        ttCtx.xaxisTooltipText.style.minWidth = textRect.width + "px";
                    }
                    ttCtx.xaxisTooltip.style.left = cx + "px";
                    ttCtx.xaxisTooltip.style.top = cy + "px";
                }
            }
        }
        /**
         * @param {number} index
         */
        moveYAxisTooltip(index) {
            var _a, _b;
            const w = this.w;
            const ttCtx = this.ttCtx;
            if (ttCtx.yaxisTTEls === null) {
                ttCtx.yaxisTTEls = /** @type {any[]} */ [
                    ...w.dom.baseEl.querySelectorAll(".apexcharts-yaxistooltip")
                ];
            }
            const ycrosshairsHiddenRectY1 = parseInt(
                (_b = (_a = ttCtx.ycrosshairsHidden) == null ? void 0 : _a.getAttribute("y1")) != null ? _b : "0",
                10
            );
            let cy = w.layout.translateY + ycrosshairsHiddenRectY1;
            if (ttCtx.yaxisTTEls) {
                const yAxisTTRect = ttCtx.yaxisTTEls[index].getBoundingClientRect();
                const yAxisTTHeight = yAxisTTRect.height;
                let cx;
                const labelsGroup = (
                    /** @type {SVGGElement | null} */
                    w.dom.baseEl.querySelector(
                        `.apexcharts-yaxis[rel='${index}'] .apexcharts-yaxis-texts-g`
                    )
                );
                const elWrapRect = w.dom.elWrap.getBoundingClientRect();
                if (labelsGroup) {
                    const lr = labelsGroup.getBoundingClientRect();
                    if (lr.width > 0) {
                        const labelsCenterInElWrap = lr.left + lr.width / 2 - elWrapRect.left;
                        cx = labelsCenterInElWrap - yAxisTTRect.width / 2;
                    }
                }
                if (cx == null) {
                    const GAP = 4;
                    cx = w.config.yaxis[index].opposite ? w.globals.translateYAxisX[index] + GAP : w.globals.translateYAxisX[index] - yAxisTTRect.width - GAP;
                }
                cy = cy - yAxisTTHeight / 2;
                if (w.globals.ignoreYAxisIndexes.indexOf(index) === -1 && cy > 0 && cy < w.layout.gridHeight) {
                    ttCtx.yaxisTTEls[index].classList.add("apexcharts-active");
                    ttCtx.yaxisTTEls[index].style.top = cy + "px";
                    ttCtx.yaxisTTEls[index].style.left = cx + w.config.yaxis[index].tooltip.offsetX + "px";
                } else {
                    ttCtx.yaxisTTEls[index].classList.remove("apexcharts-active");
                }
            }
        }
        /**
         ** moves the whole tooltip by changing x, y attrs
         * @memberof Position
         * @param {number} cx - point's x position, wherever point's x is, you need to move tooltip
         * @param {number} cy - point's y position, wherever point's y is, you need to move tooltip
         * @param {number | null} [markerSize] - point's size
         */
        moveTooltip(cx, cy, markerSize = null) {
            const ttCtx = this.ttCtx;
            const tooltipEl = ttCtx.getElTooltip();
            if (!tooltipEl) return;
            const pos = this.computeTooltipPosition(cx, cy, markerSize);
            if (pos === null) return;
            this.applyTooltipPosition(tooltipEl, pos);
        }
        /**
         * Pure-ish (reads from `this.ttCtx` + `this.w` but performs no DOM writes)
         * computation of the tooltip box position, edge placement (for arrow),
         * and arrow vertical offset. Returns null when inputs are not numeric.
         *
         * @param {number} cx
         * @param {number} cy
         * @param {number | null} [markerSize]
         * @returns {{ x: number, y: number, placement: 'left'|'right', arrowY: number|null } | null}
         */
        computeTooltipPosition(cx, cy, markerSize = null) {
            var _a, _b, _c, _d, _e, _f, _g;
            const w = this.w;
            const ttCtx = this.ttCtx;
            const tooltipRect = ttCtx.tooltipRect;
            const arrowEnabled = !!w.config.tooltip.arrow;
            const pointSize = markerSize !== null ? parseFloat(String(markerSize)) : 1;
            const ttH = tooltipRect.ttHeight || 0;
            const ttW = tooltipRect.ttWidth || 0;
            const cxNum = parseFloat(String(cx));
            const cyNum = parseFloat(String(cy));
            if (isNaN(cxNum)) return null;
            let x = cxNum + pointSize + 5;
            const pointY = cyNum + w.layout.translateY;
            let y = arrowEnabled ? pointY - ttH / 2 + pointSize / 2 : cyNum + pointSize / 2;
            let placement = "right";
            if (x > w.layout.gridWidth / 2) {
                x = x - ttW - pointSize - 10;
                placement = "left";
            }
            if (x > w.layout.gridWidth - ttW - 10) {
                x = w.layout.gridWidth - ttW;
            }
            if (x < -20) {
                x = -20;
            }
            if (w.config.tooltip.followCursor) {
                const elGrid = ttCtx.getElGrid();
                if (!elGrid) return null;
                const seriesBound = elGrid.getBoundingClientRect();
                x = ttCtx.e.clientX - seriesBound.left;
                if (x > w.layout.gridWidth / 2) {
                    x = x - ttW;
                    placement = "left";
                } else {
                    placement = "right";
                }
                y = ttCtx.e.clientY + w.layout.translateY - seriesBound.top;
                if (y > w.layout.gridHeight / 2) {
                    y = y - ttH;
                }
            } else {
                if (!w.globals.isBarHorizontal) {
                    if (arrowEnabled) {
                        const gridTop = w.layout.translateY;
                        const gridBottom = w.layout.translateY + w.layout.gridHeight;
                        if (y + ttH > gridBottom) {
                            y = gridBottom - ttH;
                        }
                        if (y < gridTop) {
                            y = gridTop;
                        }
                    } else {
                        if (ttH / 2 + y > w.layout.gridHeight) {
                            y = w.layout.gridHeight - ttH + w.layout.translateY;
                        }
                    }
                }
            }
            if (isNaN(x)) return null;
            x = x + w.layout.translateX;
            const a11y = (_b = (_a = w.config) == null ? void 0 : _a.chart) == null ? void 0 : _b.accessibility;
            if ((a11y == null ? void 0 : a11y.enabled) && ((_d = (_c = a11y == null ? void 0 : a11y.keyboard) == null ? void 0 : _c.navigation) == null ? void 0 : _d.enabled) && ((_g = (_f = (_e = w.dom) == null ? void 0 : _e.baseEl) == null ? void 0 : _f.querySelector) == null ? void 0 : _g.call(_f, ".apexcharts-keyboard-focused"))) {
                const refPointY = arrowEnabled ? pointY : cyNum;
                const margin = (pointSize || 1) + 12;
                const tooltipTop = y;
                const tooltipBottom = y + ttH;
                if (!isNaN(refPointY) && ttH > 0 && tooltipTop < refPointY + margin && tooltipBottom > refPointY - margin) {
                    y = refPointY - ttH - margin;
                    if (y < 0) {
                        y = refPointY + margin;
                    }
                }
            }
            let arrowY = null;
            if (arrowEnabled && ttH > 0) {
                const localY = pointY - y;
                const minArrowY = 10;
                const maxArrowY = ttH - 10;
                arrowY = Math.max(minArrowY, Math.min(maxArrowY, localY));
            }
            return {
                x,
                y,
                placement,
                arrowY
            };
        }
        /**
         * Single DOM-writer used by every positioning path on the main tooltip.
         * Replaces the duplicated `style.left/top` writes that previously lived
         * in Position.moveTooltip, Tooltip.drawFixedTooltipRect, and Intersect.
         *
         * @param {HTMLElement} tooltipEl
         * @param {{
         *   x: number,
         *   y: number,
         *   placement?: 'left'|'right'|'top'|'bottom',
         *   arrowY?: number|null,
         *   arrowX?: number|null,
         * }} pos
         */
        applyTooltipPosition(tooltipEl, pos) {
            if (!tooltipEl) return;
            const firstPaint = tooltipEl.dataset.positioned !== "true";
            if (firstPaint) {
                tooltipEl.style.transitionProperty = "none";
            }
            tooltipEl.style.left = pos.x + "px";
            tooltipEl.style.top = pos.y + "px";
            if (pos.placement) {
                tooltipEl.dataset.placement = pos.placement;
            }
            if (pos.arrowY != null) {
                tooltipEl.style.setProperty("--apx-tt-arrow-y", pos.arrowY + "px");
            }
            if (pos.arrowX != null) {
                tooltipEl.style.setProperty("--apx-tt-arrow-x", pos.arrowX + "px");
            }
            if (firstPaint) {
                void tooltipEl.offsetWidth;
                tooltipEl.dataset.positioned = "true";
                requestAnimationFrame(() => {
                    tooltipEl.style.transitionProperty = "";
                });
            }
        }
        /**
         * @param {number} i
         * @param {number} j
         */
        moveMarkers(i, j) {
            var _a;
            const w = this.w;
            const ttCtx = this.ttCtx;
            if (w.globals.markers.size[i] > 0) {
                const allPoints = w.dom.baseEl.querySelectorAll(
                    ` .apexcharts-series[data\\:realIndex='${i}'] .apexcharts-marker`
                );
                for (let p = 0; p < allPoints.length; p++) {
                    if (parseInt((_a = allPoints[p].getAttribute("rel")) != null ? _a : "0", 10) === j) {
                        ttCtx.marker.resetPointsSize();
                        ttCtx.marker.enlargeCurrentPoint(j, allPoints[p]);
                    }
                }
            } else {
                ttCtx.marker.resetPointsSize();
                this.moveDynamicPointOnHover(j, i);
            }
        }
        // This function is used when you need to show markers/points only on hover -
        // DIFFERENT X VALUES in multiple series
        /**
         * @param {number} j
         * @param {number} capturedSeries
         */
        moveDynamicPointOnHover(j, capturedSeries) {
            var _a, _b, _c, _d, _e;
            const w = this.w;
            const ttCtx = this.ttCtx;
            let cx = 0;
            let cy = 0;
            const graphics = new Graphics(this.w);
            const pointsArr = w.globals.pointsArray;
            const hoverSize = ttCtx.tooltipUtil.getHoverMarkerSize(capturedSeries);
            const serType = (
                /** @type {any} */
                w.config.series[capturedSeries].type
            );
            if (serType && (serType === "column" || serType === "candlestick" || serType === "boxPlot")) {
                return;
            }
            cx = (_b = (_a = pointsArr[capturedSeries]) == null ? void 0 : _a[j]) == null ? void 0 : _b[0];
            cy = ((_d = (_c = pointsArr[capturedSeries]) == null ? void 0 : _c[j]) == null ? void 0 : _d[1]) || 0;
            const point = w.dom.baseEl.querySelector(
                `.apexcharts-series[data\\:realIndex='${capturedSeries}'] .apexcharts-series-markers path`
            );
            if (point && cy < w.layout.gridHeight && cy > 0) {
                const shape = (_e = point.getAttribute("shape")) != null ? _e : "circle";
                const path = graphics.getMarkerPath(cx, cy, shape, hoverSize * 1.5);
                point.setAttribute("d", path);
            }
            this.moveXCrosshairs(cx);
            if (!ttCtx.fixedTooltip) {
                this.moveTooltip(cx, cy, hoverSize);
            }
        }
        // This function is used when you need to show markers/points only on hover -
        // SAME X VALUES in multiple series
        /**
         * @param {number} j
         */
        moveDynamicPointsOnHover(j) {
            var _a, _b;
            const ttCtx = this.ttCtx;
            const w = ttCtx.w;
            let cx = 0;
            let cy = 0;
            let activeSeries = 0;
            const pointsArr = w.globals.pointsArray;
            const series = new Series(this.w);
            const graphics = new Graphics(this.w);
            activeSeries = series.getActiveConfigSeriesIndex("asc", [
                "line",
                "area",
                "scatter",
                "bubble"
            ]);
            const hoverSize = ttCtx.tooltipUtil.getHoverMarkerSize(activeSeries);
            if ((_a = pointsArr[activeSeries]) == null ? void 0 : _a[j]) {
                cx = pointsArr[activeSeries][j][0];
                cy = pointsArr[activeSeries][j][1];
            }
            if (isNaN(cx)) {
                return;
            }
            const points = ttCtx.tooltipUtil.getAllMarkers();
            if (points.length) {
                for (let p = 0; p < w.seriesData.series.length; p++) {
                    const pointArr = pointsArr[p];
                    if (w.globals.comboCharts) {
                        if (typeof pointArr === "undefined") {
                            points.splice(p, 0, null);
                        }
                    }
                    if (pointArr && pointArr.length) {
                        let pcy = pointsArr[p][j][1];
                        let pcy2;
                        points[p].setAttribute("cx", cx);
                        const shape = (_b = points[p].getAttribute("shape")) != null ? _b : "circle";
                        if (w.config.chart.type === "rangeArea" && !w.globals.comboCharts) {
                            const rangeStartIndex = j + w.seriesData.series[p].length;
                            pcy2 = pointsArr[p][rangeStartIndex][1];
                            const pcyDiff = Math.abs(pcy - pcy2) / 2;
                            pcy = pcy - pcyDiff;
                        }
                        if (pcy !== null && !isNaN(pcy) && pcy < w.layout.gridHeight + hoverSize && pcy + hoverSize > 0) {
                            const path = graphics.getMarkerPath(cx, pcy, shape, hoverSize);
                            points[p].setAttribute("d", path);
                        } else {
                            points[p].setAttribute("d", "");
                        }
                    }
                }
            }
            this.moveXCrosshairs(cx);
            if (!ttCtx.fixedTooltip) {
                this.moveTooltip(cx, cy || w.layout.gridHeight, hoverSize);
            }
        }
        /**
         * @param {number} j
         * @param {number} capturedSeries
         */
        moveStickyTooltipOverBars(j, capturedSeries) {
            var _a, _b, _c;
            const w = this.w;
            const ttCtx = this.ttCtx;
            let barLen = w.globals.columnSeries ? (
                /** @type {any} */
                w.globals.columnSeries.length
            ) : w.seriesData.series.length;
            if (w.config.chart.stacked) {
                barLen = w.globals.barGroups.length;
            }
            let i = barLen >= 2 && barLen % 2 === 0 ? Math.floor(barLen / 2) : Math.floor(barLen / 2) + 1;
            if (w.globals.isBarHorizontal) {
                const series = new Series(this.w);
                i = series.getActiveConfigSeriesIndex("desc") + 1;
            }
            let jBar = w.dom.baseEl.querySelector(
                `.apexcharts-bar-series .apexcharts-series[rel='${i}'] path[j='${j}'], .apexcharts-candlestick-series .apexcharts-series[rel='${i}'] path[j='${j}'], .apexcharts-boxPlot-series .apexcharts-series[rel='${i}'] path[j='${j}'], .apexcharts-rangebar-series .apexcharts-series[rel='${i}'] path[j='${j}']`
            );
            if (!jBar && typeof capturedSeries === "number") {
                jBar = w.dom.baseEl.querySelector(
                    `.apexcharts-bar-series .apexcharts-series[data\\:realIndex='${capturedSeries}'] path[j='${j}'],
        .apexcharts-candlestick-series .apexcharts-series[data\\:realIndex='${capturedSeries}'] path[j='${j}'],
        .apexcharts-boxPlot-series .apexcharts-series[data\\:realIndex='${capturedSeries}'] path[j='${j}'],
        .apexcharts-rangebar-series .apexcharts-series[data\\:realIndex='${capturedSeries}'] path[j='${j}']`
                );
            }
            let bcx = jBar ? parseFloat((_a = jBar.getAttribute("cx")) != null ? _a : "0") : 0;
            let bcy = jBar ? parseFloat((_b = jBar.getAttribute("cy")) != null ? _b : "0") : 0;
            const bw = jBar ? parseFloat((_c = jBar.getAttribute("barWidth")) != null ? _c : "0") : 0;
            const elGrid = ttCtx.getElGrid();
            if (!elGrid) return;
            const seriesBound = elGrid.getBoundingClientRect();
            const isBoxOrCandle = jBar && (jBar.classList.contains("apexcharts-candlestick-area") || jBar.classList.contains("apexcharts-boxPlot-area"));
            if (w.axisFlags.isXNumeric) {
                if (jBar && !isBoxOrCandle) {
                    const center = this._datapointCenterXFromBars(j, seriesBound);
                    if (center != null) {
                        bcx = center;
                    } else {
                        bcx = bcx - (barLen % 2 !== 0 ? bw / 2 : 0);
                    }
                }
                if (jBar && // fixes apexcharts.js#2354
                    isBoxOrCandle) {
                    bcx = bcx - bw / 2;
                }
            } else {
                if (!w.globals.isBarHorizontal) {
                    bcx = ttCtx.xAxisTicksPositions[j - 1] + ttCtx.dataPointsDividedWidth / 2;
                    if (isNaN(bcx)) {
                        bcx = ttCtx.xAxisTicksPositions[j] - ttCtx.dataPointsDividedWidth / 2;
                    }
                }
            }
            if (!w.globals.isBarHorizontal) {
                if (w.config.tooltip.followCursor) {
                    bcy = ttCtx.e.clientY - seriesBound.top - ttCtx.tooltipRect.ttHeight / 2;
                } else {
                    if (bcy + ttCtx.tooltipRect.ttHeight + 15 > w.layout.gridHeight) {
                        bcy = w.layout.gridHeight;
                    }
                }
            } else {
                bcy = bcy - ttCtx.tooltipRect.ttHeight;
            }
            if (!w.globals.isBarHorizontal) {
                this.moveXCrosshairs(bcx);
            }
            if (!ttCtx.fixedTooltip) {
                if (w.globals.isBarHorizontal && !w.config.tooltip.followCursor) {
                    const placed = this.placeHorizontalSharedTooltip(j);
                    if (placed) return;
                }
                this.moveTooltip(bcx, bcy || w.layout.gridHeight);
            }
        }
        /**
         * Place tooltip above (or flipped: below) the union rect of all bars at
         * dataPointIndex `j` for horizontal-bar-likes. Returns true when a
         * Compute the true horizontal center of dataPointIndex `j` in grid-local
         * coords from the union of every visible bar's `getBoundingClientRect()`.
         * Used as a replacement for the (buggy on numeric/datetime xaxis) `cx`
         * attribute math in `moveStickyTooltipOverBars`. Returns null when no
         * usable bars are found.
         * @param {number} j
         * @param {DOMRect} gridRect
         * @returns {number | null}
         */
        _datapointCenterXFromBars(j, gridRect) {
            var _a, _b;
            const w = this.w;
            const bars = w.dom.baseEl.querySelectorAll(
                `.apexcharts-bar-series path[j='${j}'],.apexcharts-rangebar-series path[j='${j}']`
            );
            if (!bars.length) return null;
            let unionLeft = Infinity;
            let unionRight = -Infinity;
            for (const bar of bars) {
                const parent = (
                    /** @type {Element|null} */
                    bar.parentNode
                );
                if ((_b = (_a = parent == null ? void 0 : parent.classList) == null ? void 0 : _a.contains) == null ? void 0 : _b.call(_a, "apexcharts-series-collapsed")) continue;
                const r = (
                    /** @type {Element} */
                    bar.getBoundingClientRect()
                );
                if (r.width === 0 && r.height === 0) continue;
                if (r.left < unionLeft) unionLeft = r.left;
                if (r.right > unionRight) unionRight = r.right;
            }
            if (!isFinite(unionLeft)) return null;
            return (unionLeft + unionRight) / 2 - gridRect.left - (w.globals.barPadForNumericAxis || 0);
        }
        /**
         * Place tooltip above (or flipped: below) the union rect of all bars at
         * dataPointIndex `j` for horizontal-bar-likes. Returns true when a
         * placement was applied; false when no bars found (caller falls back).
         * @param {number} j
         * @returns {boolean}
         */
        placeHorizontalSharedTooltip(j) {
            var _a, _b;
            const w = this.w;
            const ttCtx = this.ttCtx;
            const tooltipEl = ttCtx.getElTooltip();
            if (!tooltipEl) return false;
            const elGrid = ttCtx.getElGrid();
            if (!elGrid) return false;
            const gridRect = elGrid.getBoundingClientRect();
            const bars = w.dom.baseEl.querySelectorAll(
                `.apexcharts-bar-series path[j='${j}'],.apexcharts-rangebar-series path[j='${j}'],.apexcharts-boxPlot-series path[j='${j}']`
            );
            if (!bars.length) return false;
            let unionLeft = Infinity;
            let unionRight = -Infinity;
            let unionTop = Infinity;
            let unionBottom = -Infinity;
            for (const bar of bars) {
                const parent = (
                    /** @type {Element|null} */
                    bar.parentNode
                );
                if ((_b = (_a = parent == null ? void 0 : parent.classList) == null ? void 0 : _a.contains) == null ? void 0 : _b.call(_a, "apexcharts-series-collapsed")) continue;
                const r = (
                    /** @type {Element} */
                    bar.getBoundingClientRect()
                );
                if (r.width === 0 && r.height === 0) continue;
                if (r.left < unionLeft) unionLeft = r.left;
                if (r.right > unionRight) unionRight = r.right;
                if (r.top < unionTop) unionTop = r.top;
                if (r.bottom > unionBottom) unionBottom = r.bottom;
            }
            if (!isFinite(unionLeft)) return false;
            const ttW = ttCtx.tooltipRect.ttWidth || 0;
            const ttH = ttCtx.tooltipRect.ttHeight || 0;
            const ARROW_TIP_OVERHANG = 7;
            const rowCenterX = (unionLeft + unionRight) / 2 - gridRect.left + w.layout.translateX;
            const rowTopElWrap = unionTop - gridRect.top + w.layout.translateY;
            const rowBottomElWrap = unionBottom - gridRect.top + w.layout.translateY;
            const gridTop = w.layout.translateY;
            const gridBottom = w.layout.translateY + w.layout.gridHeight;
            const gridLeft = w.layout.translateX;
            const gridRight = w.layout.translateX + w.layout.gridWidth;
            let placement = "top";
            let finalY = rowTopElWrap - ttH - ARROW_TIP_OVERHANG;
            if (finalY < gridTop) {
                const belowTop = rowBottomElWrap + ARROW_TIP_OVERHANG;
                if (belowTop + ttH <= gridBottom) {
                    placement = "bottom";
                    finalY = belowTop;
                }
            }
            let finalX = rowCenterX - ttW / 2;
            if (finalX < gridLeft) finalX = gridLeft;
            if (finalX + ttW > gridRight) finalX = gridRight - ttW;
            const arrowX = Math.max(10, Math.min(ttW - 10, rowCenterX - finalX));
            this.applyTooltipPosition(tooltipEl, {
                x: finalX,
                y: finalY,
                placement,
                arrowY: null,
                arrowX
            });
            return true;
        }
    }

    function renderMarkerSVG(shape) {
        const svg = (body) => `<svg viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">${body}</svg>`;
        switch (shape) {
            case "square":
            case "rect":
                return svg('<rect x="1" y="1" width="10" height="10" rx="1" fill="currentColor"/>');
            case "line":
                return svg('<rect x="0" y="5" width="12" height="2" rx="1" fill="currentColor"/>');
            case "diamond":
                return svg('<path d="M6 0.5 L11.5 6 L6 11.5 L0.5 6 Z" fill="currentColor"/>');
            case "triangle":
                return svg('<path d="M6 1 L11.2 10.5 L0.8 10.5 Z" fill="currentColor"/>');
            case "cross":
                return svg(
                    '<path d="M2 2 L10 10 M10 2 L2 10" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>'
                );
            case "plus":
                return svg(
                    '<path d="M6 1 L6 11 M1 6 L11 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>'
                );
            case "star":
                return svg(
                    '<path d="M6 0.5 L7.5 4.4 L11.5 4.7 L8.4 7.2 L9.5 11.1 L6 8.9 L2.5 11.1 L3.6 7.2 L0.5 4.7 L4.5 4.4 Z" fill="currentColor"/>'
                );
            case "sparkle":
                return svg(
                    '<path d="M6 0.5 L7 5 L11.5 6 L7 7 L6 11.5 L5 7 L0.5 6 L5 5 Z" fill="currentColor"/>'
                );
            case "circle":
            default:
                return svg('<circle cx="6" cy="6" r="5" fill="currentColor"/>');
        }
    }
    class Marker {
        /**
         * @param {import('./Tooltip').default} tooltipContext
         */
        constructor(tooltipContext) {
            this.w = tooltipContext.w;
            this.ttCtx = tooltipContext;
            this.ctx = tooltipContext.ctx;
            this.tooltipPosition = new Position(tooltipContext);
        }
        drawDynamicPoints() {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const marker = new Markers(this.w, this.ctx);
            const elsSeries = (
                /** @type {any[]} */
                [
                    ...w.dom.baseEl.querySelectorAll(".apexcharts-series")
                ]
            );
            if (w.config.chart.stacked) {
                elsSeries.sort((a, b) => {
                    return parseFloat(a.getAttribute("data:realIndex")) - parseFloat(b.getAttribute("data:realIndex"));
                });
            }
            for (let i = 0; i < elsSeries.length; i++) {
                const pointsMain = elsSeries[i].querySelector(
                    `.apexcharts-series-markers-wrap`
                );
                if (pointsMain !== null) {
                    let PointClasses = `apexcharts-marker w${(Math.random() + 1).toString(36).substring(4)}`;
                    if ((w.config.chart.type === "line" || w.config.chart.type === "area") && !w.globals.comboCharts && !w.config.tooltip.intersect) {
                        PointClasses += " no-pointer-events";
                    }
                    const elPointOptions = marker.getMarkerConfig({
                        cssClass: PointClasses,
                        seriesIndex: Number(pointsMain.getAttribute("data:realIndex"))
                        // fixes apexcharts/apexcharts.js #1427
                    });
                    const point = graphics.drawMarker(0, 0, elPointOptions);
                    point.node.setAttribute("default-marker-size", 0);
                    const elPointsG = BrowserAPIs.createElementNS(SVGNS, "g");
                    elPointsG.classList.add("apexcharts-series-markers");
                    elPointsG.appendChild(point.node);
                    pointsMain.appendChild(elPointsG);
                }
            }
        }
        /**
         * @param {any} rel
         * @param {any} point
         * @param {number | null} [x]
         * @param {number | null} [y]
         */
        enlargeCurrentPoint(rel, point, x = null, y = null) {
            const w = this.w;
            if (w.config.chart.type !== "bubble") {
                this.newPointSize(rel, point);
            }
            let cx = point.getAttribute("cx");
            let cy = point.getAttribute("cy");
            if (x !== null && y !== null) {
                cx = x;
                cy = y;
            }
            this.tooltipPosition.moveXCrosshairs(cx);
            if (!this.fixedTooltip) {
                if (w.config.chart.type === "radar") {
                    const elGrid = this.ttCtx.getElGrid();
                    if (!elGrid) return;
                    const seriesBound = elGrid.getBoundingClientRect();
                    cx = this.ttCtx.e.clientX - seriesBound.left;
                }
                this.tooltipPosition.moveTooltip(cx, cy, w.config.markers.hover.size);
            }
        }
        /**
         * @param {number} j
         */
        enlargePoints(j) {
            var _a, _b;
            const w = this.w;
            const me = this;
            const ttCtx = this.ttCtx;
            const col = j;
            const points = w.dom.baseEl.querySelectorAll(
                ".apexcharts-series:not(.apexcharts-series-collapsed) .apexcharts-marker"
            );
            let newSize = w.config.markers.hover.size;
            for (let p = 0; p < points.length; p++) {
                const rel = points[p].getAttribute("rel");
                const index = points[p].getAttribute("index");
                if (newSize === void 0) {
                    newSize = w.globals.markers.size[
                        /** @type {any} */
                        index
                    ] + w.config.markers.hover.sizeOffset;
                }
                if (col === parseInt(rel != null ? rel : "0", 10)) {
                    me.newPointSize(col, points[p]);
                    const cx = (_a = points[p].getAttribute("cx")) != null ? _a : "0";
                    const cy = (_b = points[p].getAttribute("cy")) != null ? _b : "0";
                    me.tooltipPosition.moveXCrosshairs(parseFloat(cx));
                    if (!ttCtx.fixedTooltip) {
                        me.tooltipPosition.moveTooltip(
                            parseFloat(cx),
                            parseFloat(cy),
                            newSize
                        );
                    }
                } else {
                    me.oldPointSize(points[p]);
                }
            }
        }
        /**
         * @param {any} rel
         * @param {any} point
         */
        newPointSize(rel, point) {
            const w = this.w;
            let newSize = w.config.markers.hover.size;
            const elPoint = rel === 0 ? point.parentNode.firstChild : point.parentNode.lastChild;
            if (elPoint.getAttribute("default-marker-size") !== "0") {
                const index = parseInt(elPoint.getAttribute("index"), 10);
                if (newSize === void 0) {
                    newSize = w.globals.markers.size[index] + w.config.markers.hover.sizeOffset;
                }
                if (newSize < 0) {
                    newSize = 0;
                }
                const path = this.ttCtx.tooltipUtil.getPathFromPoint(point, newSize);
                point.setAttribute("d", path);
            }
        }
        /**
         * @param {any} point
         */
        oldPointSize(point) {
            const size = parseFloat(point.getAttribute("default-marker-size"));
            const path = this.ttCtx.tooltipUtil.getPathFromPoint(point, size);
            point.setAttribute("d", path);
        }
        resetPointsSize() {
            var _a;
            const w = this.w;
            const points = w.dom.baseEl.querySelectorAll(
                ".apexcharts-series:not(.apexcharts-series-collapsed) .apexcharts-marker"
            );
            for (let p = 0; p < points.length; p++) {
                const size = parseFloat(
                    (_a = points[p].getAttribute("default-marker-size")) != null ? _a : "0"
                );
                if (Utils$1.isNumber(size) && size > 0) {
                    const path = this.ttCtx.tooltipUtil.getPathFromPoint(points[p], size);
                    points[p].setAttribute("d", path);
                } else {
                    points[p].setAttribute("d", "M0,0");
                }
            }
        }
    }
    class Intersect {
        /**
         * @param {import('./Tooltip').default} tooltipContext
         */
        constructor(tooltipContext) {
            this.w = tooltipContext.w;
            const w = this.w;
            this.ttCtx = tooltipContext;
            this.isVerticalGroupedRangeBar = !w.globals.isBarHorizontal && w.config.chart.type === "rangeBar" && w.config.plotOptions.bar.rangeBarGroupRows;
        }
        // a helper function to get an element's attribute value
        /**
         * @param {Event} e
         * @param {string} attr
         */
        getAttr(e, attr) {
            var _a;
            return parseFloat(
                /** @type {Element} */
                (_a = e.target.getAttribute(attr)) != null ? _a : ""
            );
        }
        // handle tooltip for heatmaps and treemaps
        /** @param {{e: any, opt: any, x: any, y: any, type: any}} opts */
        handleHeatTreeTooltip({
            e,
            opt,
            x,
            y,
            type
        }) {
            var _a, _b;
            const ttCtx = this.ttCtx;
            const w = this.w;
            if (e.target.classList.contains(`apexcharts-${type}-rect`)) {
                const i = this.getAttr(e, "i");
                const j = this.getAttr(e, "j");
                const cx = this.getAttr(e, "cx");
                const cy = this.getAttr(e, "cy");
                const width = this.getAttr(e, "width");
                const height = this.getAttr(e, "height");
                ttCtx.tooltipLabels.drawSeriesTexts({
                    ttItems: opt.ttItems,
                    i,
                    j,
                    shared: false,
                    e
                });
                w.interact.capturedSeriesIndex = i;
                w.interact.capturedDataPointIndex = j;
                x = cx + ttCtx.tooltipRect.ttWidth / 2 + width;
                y = cy + ttCtx.tooltipRect.ttHeight / 2 - height / 2;
                ttCtx.tooltipPosition.moveXCrosshairs(cx + width / 2);
                if (x > w.layout.gridWidth / 2) {
                    x = cx - ttCtx.tooltipRect.ttWidth / 2 + width;
                }
                if (ttCtx.w.config.tooltip.followCursor) {
                    const seriesBound = w.dom.elWrap.getBoundingClientRect();
                    x = ((_a = w.interact.clientX) != null ? _a : 0) - seriesBound.left - (x > w.layout.gridWidth / 2 ? ttCtx.tooltipRect.ttWidth : 0);
                    y = ((_b = w.interact.clientY) != null ? _b : 0) - seriesBound.top - (y > w.layout.gridHeight / 2 ? ttCtx.tooltipRect.ttHeight : 0);
                }
            }
            return {
                x,
                y
            };
        }
        /**
         * handle tooltips for line/area/scatter charts where tooltip.intersect is true
         * when user hovers over the marker directly, this function is executed
         */
        /** @param {{e: any, opt: any, x: any, y: any}} opts */
        handleMarkerTooltip({
            e,
            opt,
            x,
            y
        }) {
            const w = this.w;
            const ttCtx = this.ttCtx;
            let i;
            let j;
            if (e.target.classList.contains("apexcharts-marker")) {
                const cx = parseInt(opt.paths.getAttribute("cx"), 10);
                const cy = parseInt(opt.paths.getAttribute("cy"), 10);
                const val = parseFloat(opt.paths.getAttribute("val"));
                j = parseInt(opt.paths.getAttribute("rel"), 10);
                i = parseInt(
                    opt.paths.parentNode.parentNode.parentNode.getAttribute("rel"),
                    10
                ) - 1;
                if (ttCtx.intersect) {
                    const el = Utils$1.findAncestor(opt.paths, "apexcharts-series");
                    if (el) {
                        i = parseInt(el.getAttribute("data:realIndex"), 10);
                    }
                }
                ttCtx.tooltipLabels.drawSeriesTexts({
                    ttItems: opt.ttItems,
                    i,
                    j,
                    shared: ttCtx.showOnIntersect ? false : w.config.tooltip.shared,
                    e
                });
                if (e.type === "mouseup") {
                    ttCtx.markerClick(e, i, j);
                }
                w.interact.capturedSeriesIndex = i;
                w.interact.capturedDataPointIndex = j;
                const arrowEnabled = !!w.config.tooltip.arrow;
                x = cx;
                if (arrowEnabled) {
                    y = cy;
                } else {
                    y = cy + w.layout.translateY - ttCtx.tooltipRect.ttHeight * 1.4;
                    if (val < 0) {
                        y = cy;
                    }
                }
                if (ttCtx.w.config.tooltip.followCursor) {
                    const elGrid = ttCtx.getElGrid();
                    if (!elGrid) return {
                        x,
                        y
                    };
                    const seriesBound = elGrid.getBoundingClientRect();
                    y = ttCtx.e.clientY + w.layout.translateY - seriesBound.top;
                }
                ttCtx.marker.enlargeCurrentPoint(j, opt.paths, x, y);
            }
            return {
                x,
                y
            };
        }
        /**
         * handle tooltips for bar/column charts
         */
        /** @param {{e: any, opt: any}} opts */
        handleBarTooltip({
            e,
            opt
        }) {
            var _a, _b, _c;
            const w = this.w;
            const ttCtx = this.ttCtx;
            const tooltipEl = ttCtx.getElTooltip();
            let bx = 0;
            let x = 0;
            let y = 0;
            let i = 0;
            let strokeWidth;
            const barXY = this.getBarTooltipXY({
                e,
                opt
            });
            if (barXY.j === null && barXY.barHeight === 0 && barXY.barWidth === 0) {
                return;
            }
            i = barXY.i;
            const j = barXY.j;
            w.interact.capturedSeriesIndex = i;
            w.interact.capturedDataPointIndex = j !== null ? j : w.interact.capturedDataPointIndex;
            if (w.globals.isBarHorizontal && ttCtx.tooltipUtil.hasBars() || !w.config.tooltip.shared) {
                x = barXY.x;
                y = barXY.y;
                strokeWidth = Array.isArray(w.config.stroke.width) ? w.config.stroke.width[i] : w.config.stroke.width;
                bx = x;
            } else {
                if (!w.globals.comboCharts && !w.config.tooltip.shared) {
                    bx = bx / 2;
                }
            }
            if (isNaN(y)) {
                y = w.globals.svgHeight - ttCtx.tooltipRect.ttHeight;
            }
            if (x + ttCtx.tooltipRect.ttWidth > w.layout.gridWidth) {
                x = x - ttCtx.tooltipRect.ttWidth;
            } else if (x < 0) {
                x = 0;
            }
            if (ttCtx.w.config.tooltip.followCursor) {
                const elGrid = ttCtx.getElGrid();
                if (!elGrid) return;
            }
            if (ttCtx.tooltip === null) {
                ttCtx.tooltip = w.dom.baseEl.querySelector(".apexcharts-tooltip");
            }
            if (!w.config.tooltip.shared) {
                if (w.globals.comboBarCount > 0) {
                    ttCtx.tooltipPosition.moveXCrosshairs(bx + strokeWidth / 2);
                } else {
                    ttCtx.tooltipPosition.moveXCrosshairs(bx);
                }
            }
            if (!ttCtx.fixedTooltip && (!w.config.tooltip.shared || w.globals.isBarHorizontal && ttCtx.tooltipUtil.hasBars())) {
                y = y + w.layout.translateY - ttCtx.tooltipRect.ttHeight / 2;
                if (tooltipEl) {
                    const ttW = ttCtx.tooltipRect.ttWidth || 0;
                    const ttH = ttCtx.tooltipRect.ttHeight || 0;
                    const arrowEnabled = !!w.config.tooltip.arrow;
                    const {
                        barAnchorXInGrid,
                        barAnchorYInGrid,
                        barRectInGrid
                    } = barXY;
                    const ARROW_TIP_OVERHANG = 7;
                    const elGridRect = (_a = ttCtx.getElGrid()) == null ? void 0 : _a.getBoundingClientRect();
                    const elWrapRect = w.dom.elWrap.getBoundingClientRect();
                    const gridOffsetXInElWrap = elGridRect ? elGridRect.left - elWrapRect.left : w.layout.translateX;
                    let placement;
                    let arrowY = null;
                    let arrowX = null;
                    let finalX = x + gridOffsetXInElWrap;
                    let finalY = y;
                    if (arrowEnabled && w.globals.isBarHorizontal && barRectInGrid != null) {
                        const gridTop = w.layout.translateY;
                        const gridBottom = w.layout.translateY + w.layout.gridHeight;
                        const gridLeft = gridOffsetXInElWrap;
                        const gridRight = gridOffsetXInElWrap + w.layout.gridWidth;
                        const barCenterXInElWrap = (barRectInGrid.left + barRectInGrid.right) / 2 + gridOffsetXInElWrap;
                        const barTopInElWrap = barRectInGrid.top + w.layout.translateY;
                        const barBottomInElWrap = barRectInGrid.bottom + w.layout.translateY;
                        let proposedTop = barTopInElWrap - ttH - ARROW_TIP_OVERHANG;
                        placement = "top";
                        if (proposedTop < gridTop) {
                            const belowTop = barBottomInElWrap + ARROW_TIP_OVERHANG;
                            if (belowTop + ttH <= gridBottom) {
                                placement = "bottom";
                                proposedTop = belowTop;
                            }
                        }
                        finalY = proposedTop;
                        finalX = barCenterXInElWrap - ttW / 2;
                        if (finalX < gridLeft) finalX = gridLeft;
                        if (finalX + ttW > gridRight) finalX = gridRight - ttW;
                        arrowX = Math.max(
                            10,
                            Math.min(ttW - 10, barCenterXInElWrap - finalX)
                        );
                    } else if (arrowEnabled && barAnchorXInGrid != null && barAnchorYInGrid != null) {
                        const barCenterXInElWrap = barAnchorXInGrid + gridOffsetXInElWrap;
                        const gridCenterXInElWrap = gridOffsetXInElWrap + w.layout.gridWidth / 2;
                        const barLeftInElWrap = ((_b = barRectInGrid == null ? void 0 : barRectInGrid.left) != null ? _b : barAnchorXInGrid) + gridOffsetXInElWrap;
                        const barRightInElWrap = ((_c = barRectInGrid == null ? void 0 : barRectInGrid.right) != null ? _c : barAnchorXInGrid) + gridOffsetXInElWrap;
                        if (barCenterXInElWrap < gridCenterXInElWrap) {
                            placement = "right";
                            finalX = barRightInElWrap + ARROW_TIP_OVERHANG;
                        } else {
                            placement = "left";
                            finalX = barLeftInElWrap - ttW - ARROW_TIP_OVERHANG;
                        }
                        if (barRectInGrid) {
                            const barCenterYInElWrap = (barRectInGrid.top + barRectInGrid.bottom) / 2 + w.layout.translateY;
                            finalY = barCenterYInElWrap - ttH / 2;
                            const gridTop = w.layout.translateY;
                            const gridBottom = w.layout.translateY + w.layout.gridHeight;
                            if (finalY < gridTop) finalY = gridTop;
                            if (finalY + ttH > gridBottom) finalY = gridBottom - ttH;
                        }
                        if (ttH > 0 && barRectInGrid) {
                            const barCenterYInElWrap = (barRectInGrid.top + barRectInGrid.bottom) / 2 + w.layout.translateY;
                            arrowY = Math.max(
                                10,
                                Math.min(ttH - 10, barCenterYInElWrap - finalY)
                            );
                        }
                    }
                    ttCtx.tooltipPosition.applyTooltipPosition(tooltipEl, {
                        x: finalX,
                        y: finalY,
                        placement,
                        arrowY,
                        arrowX
                    });
                }
            }
        }
        /** @param {{e: any, opt: any}} opts */
        getBarTooltipXY({
            e,
            opt
        }) {
            const w = this.w;
            let j = null;
            const ttCtx = this.ttCtx;
            let i = 0;
            let x = 0;
            let y = 0;
            let barWidth = 0;
            let barHeight = 0;
            let barCx = null;
            let barCy = null;
            let barAnchorXInGrid = null;
            let barAnchorYInGrid = null;
            let barRectInGrid = null;
            const cl = e.target.classList;
            if (cl.contains("apexcharts-bar-area") || cl.contains("apexcharts-candlestick-area") || cl.contains("apexcharts-boxPlot-area") || cl.contains("apexcharts-rangebar-area")) {
                const bar = e.target;
                const barRect = bar.getBoundingClientRect();
                const seriesBound = opt.elGrid.getBoundingClientRect();
                const bh = barRect.height;
                barHeight = barRect.height;
                const bw = barRect.width;
                const cx = parseInt(bar.getAttribute("cx"), 10);
                const cy = parseInt(bar.getAttribute("cy"), 10);
                barCx = cx;
                barCy = cy;
                barWidth = parseFloat(bar.getAttribute("barWidth"));
                const rectLeftInGrid = barRect.left - seriesBound.left;
                const rectTopInGrid = barRect.top - seriesBound.top;
                const rectCenterXInGrid = rectLeftInGrid + bw / 2;
                const rectCenterYInGrid = rectTopInGrid + bh / 2;
                barAnchorXInGrid = rectCenterXInGrid;
                barAnchorYInGrid = w.globals.isBarHorizontal ? rectCenterYInGrid : rectTopInGrid;
                barRectInGrid = {
                    left: rectLeftInGrid,
                    top: rectTopInGrid,
                    right: rectLeftInGrid + bw,
                    bottom: rectTopInGrid + bh
                };
                const clientX = e.type === "touchmove" ? e.touches[0].clientX : e.clientX;
                j = parseInt(bar.getAttribute("j"), 10);
                i = parseInt(bar.parentNode.getAttribute("rel"), 10) - 1;
                const y1 = bar.getAttribute("data-range-y1");
                const y2 = bar.getAttribute("data-range-y2");
                if (w.globals.comboCharts) {
                    i = parseInt(bar.parentNode.getAttribute("data:realIndex"), 10);
                }
                const handleXForColumns = (x2) => {
                    if (w.axisFlags.isXNumeric) {
                        x2 = cx - bw / 2;
                    } else {
                        if (this.isVerticalGroupedRangeBar) {
                            x2 = cx + bw / 2;
                        } else {
                            x2 = cx - ttCtx.dataPointsDividedWidth + bw / 2;
                        }
                    }
                    return x2;
                };
                const handleYForBars = () => {
                    return cy - ttCtx.dataPointsDividedHeight + bh / 2 - ttCtx.tooltipRect.ttHeight / 2;
                };
                ttCtx.tooltipLabels.drawSeriesTexts({
                    ttItems: opt.ttItems,
                    i,
                    j,
                    y1: y1 ? parseInt(y1, 10) : null,
                    y2: y2 ? parseInt(y2, 10) : null,
                    shared: ttCtx.showOnIntersect ? false : w.config.tooltip.shared,
                    e
                });
                if (w.config.tooltip.followCursor) {
                    if (w.globals.isBarHorizontal) {
                        x = clientX - seriesBound.left + 15;
                        y = handleYForBars();
                    } else {
                        x = handleXForColumns(x);
                        y = e.clientY - seriesBound.top - ttCtx.tooltipRect.ttHeight / 2 - 15;
                    }
                } else {
                    if (w.globals.isBarHorizontal) {
                        x = cx;
                        if (ttCtx.xyRatios && x < ttCtx.xyRatios.baseLineInvertedY) {
                            x = cx - ttCtx.tooltipRect.ttWidth;
                        }
                        y = handleYForBars();
                    } else {
                        x = handleXForColumns(x);
                        y = cy;
                    }
                }
            }
            return {
                x,
                y,
                barHeight,
                barWidth,
                i,
                j,
                // SVG attribute values — left for any caller that still wants them.
                barCx,
                barCy,
                // Arrow anchor in grid-local coords (rect-derived; column→top,
                // horizontal→center). Used by handleBarTooltip to place the arrow
                // exactly on the bar's data point.
                barAnchorXInGrid,
                barAnchorYInGrid,
                // Full rendered bar rect (grid-local). Used for top/bottom
                // placement and flip-on-overflow detection.
                barRectInGrid
            };
        }
    }
    class AxesTooltip {
        /**
         * @param {import('./Tooltip').default} tooltipContext
         */
        constructor(tooltipContext) {
            this.w = tooltipContext.w;
            this.ttCtx = tooltipContext;
        }
        /**
         * This method adds the secondary tooltip which appears below x axis
         * @memberof Tooltip
         **/
        drawXaxisTooltip() {
            const w = this.w;
            const ttCtx = this.ttCtx;
            const isBottom = w.config.xaxis.position === "bottom";
            ttCtx.xaxisOffY = isBottom ? w.layout.gridHeight + 1 : -w.layout.xAxisHeight - w.config.xaxis.axisTicks.height + 3;
            const tooltipCssClass = isBottom ? "apexcharts-xaxistooltip apexcharts-xaxistooltip-bottom" : "apexcharts-xaxistooltip apexcharts-xaxistooltip-top";
            const renderTo = w.dom.elWrap;
            if (ttCtx.isXAxisTooltipEnabled) {
                const xaxisTooltip = w.dom.baseEl.querySelector(
                    ".apexcharts-xaxistooltip"
                );
                if (xaxisTooltip === null) {
                    ttCtx.xaxisTooltip = BrowserAPIs.createElementNS(
                        "http://www.w3.org/1999/xhtml",
                        "div"
                    );
                    ttCtx.xaxisTooltip.setAttribute(
                        "class",
                        tooltipCssClass + " apexcharts-theme-" + w.config.tooltip.theme
                    );
                    renderTo.appendChild(ttCtx.xaxisTooltip);
                    ttCtx.xaxisTooltipText = BrowserAPIs.createElementNS(
                        "http://www.w3.org/1999/xhtml",
                        "div"
                    );
                    ttCtx.xaxisTooltipText.classList.add("apexcharts-xaxistooltip-text");
                    ttCtx.xaxisTooltipText.style.fontFamily = w.config.xaxis.tooltip.style.fontFamily || w.config.chart.fontFamily;
                    ttCtx.xaxisTooltipText.style.fontSize = w.config.xaxis.tooltip.style.fontSize;
                    ttCtx.xaxisTooltip.appendChild(ttCtx.xaxisTooltipText);
                }
            }
        }
        /**
         * This method adds the secondary tooltip which appears below x axis
         * @memberof Tooltip
         **/
        drawYaxisTooltip() {
            const w = this.w;
            const ttCtx = this.ttCtx;
            for (let i = 0; i < w.config.yaxis.length; i++) {
                const isRight = w.config.yaxis[i].opposite || w.config.yaxis[i].crosshairs.opposite;
                ttCtx.yaxisOffX = isRight ? w.layout.gridWidth + 1 : 1;
                const tooltipCssClass = isRight ? `apexcharts-yaxistooltip apexcharts-yaxistooltip-${i} apexcharts-yaxistooltip-right` : `apexcharts-yaxistooltip apexcharts-yaxistooltip-${i} apexcharts-yaxistooltip-left`;
                const renderTo = w.dom.elWrap;
                const yaxisTooltip = w.dom.baseEl.querySelector(
                    `.apexcharts-yaxistooltip apexcharts-yaxistooltip-${i}`
                );
                if (yaxisTooltip === null) {
                    ttCtx.yaxisTooltip = BrowserAPIs.createElementNS(
                        "http://www.w3.org/1999/xhtml",
                        "div"
                    );
                    ttCtx.yaxisTooltip.setAttribute(
                        "class",
                        tooltipCssClass + " apexcharts-theme-" + w.config.tooltip.theme
                    );
                    renderTo.appendChild(ttCtx.yaxisTooltip);
                    if (i === 0) ttCtx.yaxisTooltipText = [];
                    ttCtx.yaxisTooltipText[i] = BrowserAPIs.createElementNS("http://www.w3.org/1999/xhtml", "div");
                    ttCtx.yaxisTooltipText[i].classList.add(
                        "apexcharts-yaxistooltip-text"
                    );
                    ttCtx.yaxisTooltip.appendChild(
                        /** @type {any} */
                        ttCtx.yaxisTooltipText[i]
                    );
                }
            }
        }
        /**
         * @memberof Tooltip
         **/
        setXCrosshairWidth() {
            var _a, _b;
            const w = this.w;
            const ttCtx = this.ttCtx;
            const xcrosshairs = ttCtx.getElXCrosshairs();
            ttCtx.xcrosshairsWidth = parseInt(w.config.xaxis.crosshairs.width, 10);
            if (!w.globals.comboCharts) {
                if (w.config.xaxis.crosshairs.width === "tickWidth") {
                    const count = w.labelData.labels.length;
                    ttCtx.xcrosshairsWidth = w.layout.gridWidth / count;
                } else if (w.config.xaxis.crosshairs.width === "barWidth") {
                    const bar = w.dom.baseEl.querySelector(".apexcharts-bar-area");
                    if (bar !== null) {
                        const barWidth = parseFloat((_a = bar.getAttribute("barWidth")) != null ? _a : "0");
                        ttCtx.xcrosshairsWidth = barWidth;
                    } else {
                        ttCtx.xcrosshairsWidth = 1;
                    }
                }
            } else {
                const bar = w.dom.baseEl.querySelector(".apexcharts-bar-area");
                if (bar !== null && w.config.xaxis.crosshairs.width === "barWidth") {
                    const barWidth = parseFloat((_b = bar.getAttribute("barWidth")) != null ? _b : "0");
                    ttCtx.xcrosshairsWidth = barWidth;
                } else {
                    if (w.config.xaxis.crosshairs.width === "tickWidth") {
                        const count = w.labelData.labels.length;
                        ttCtx.xcrosshairsWidth = w.layout.gridWidth / count;
                    }
                }
            }
            if (w.globals.isBarHorizontal) {
                ttCtx.xcrosshairsWidth = 0;
            }
            if (xcrosshairs !== null && ttCtx.xcrosshairsWidth > 0) {
                xcrosshairs.setAttribute("width", String(ttCtx.xcrosshairsWidth));
            }
        }
        handleYCrosshair() {
            const w = this.w;
            const ttCtx = this.ttCtx;
            ttCtx.ycrosshairs = w.dom.baseEl.querySelector(".apexcharts-ycrosshairs");
            ttCtx.ycrosshairsHidden = w.dom.baseEl.querySelector(
                ".apexcharts-ycrosshairs-hidden"
            );
        }
        /**
         * @param {number} index
         * @param {number} clientY
         * @param {import('../../types/internal').XYRatios} xyRatios
         */
        drawYaxisTooltipText(index, clientY, xyRatios) {
            const ttCtx = this.ttCtx;
            const w = this.w;
            const gl = w.globals;
            const yAxisSeriesArr = gl.seriesYAxisMap[index];
            if (ttCtx.yaxisTooltips[index] && yAxisSeriesArr.length > 0) {
                const lbFormatter = w.formatters.yLabelFormatters[index];
                const elGrid = ttCtx.getElGrid();
                if (!elGrid) return;
                const seriesBound = elGrid.getBoundingClientRect();
                const seriesIndex = yAxisSeriesArr[0];
                let translationsIndex = 0;
                if (xyRatios.yRatio.length > 1) {
                    translationsIndex = seriesIndex;
                }
                const hoverY = (clientY - seriesBound.top) * xyRatios.yRatio[translationsIndex];
                const height = gl.maxYArr[seriesIndex] - gl.minYArr[seriesIndex];
                let val = gl.minYArr[seriesIndex] + (height - hoverY);
                if (w.config.yaxis[index].reversed) {
                    val = gl.maxYArr[seriesIndex] - (height - hoverY);
                }
                ttCtx.tooltipPosition.moveYCrosshairs(clientY - seriesBound.top);
                ttCtx.yaxisTooltipText[index].innerHTML = lbFormatter(val);
                ttCtx.tooltipPosition.moveYAxisTooltip(index);
            }
        }
    }
    class Tooltip {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {import('../../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this.tConfig = w.config.tooltip;
            this.tooltipUtil = new Utils(this);
            this.tooltipLabels = new Labels(this);
            this.tooltipPosition = new Position(this);
            this.marker = new Marker(this);
            this.intersect = new Intersect(this);
            this.axesTooltip = new AxesTooltip(this);
            this.showOnIntersect = this.tConfig.intersect;
            this.showTooltipTitle = this.tConfig.x.show;
            this.fixedTooltip = this.tConfig.fixed.enabled;
            this.xaxisTooltip = null;
            this.xaxisTooltipText = null;
            this.yaxisTooltip = null;
            this.yaxisTooltipText = null;
            this.yaxisTTEls = null;
            this.xaxisOffY = 0;
            this.yaxisOffX = 0;
            this.xcrosshairsWidth = 0;
            this.ycrosshairs = null;
            this.ycrosshairsHidden = null;
            this.tooltip = null;
            this.e = null;
            this.isBarShared = !w.globals.isBarHorizontal && this.tConfig.shared;
            this.lastHoverTime = Date.now();
            this.dimensionUpdateScheduled = false;
            this.xyRatios = null;
            this.isXAxisTooltipEnabled = false;
            this.yaxisTooltips = [];
            this.allTooltipSeriesGroups = [];
            this.xAxisTicksPositions = null;
            this.dataPointsDividedHeight = 0;
            this.dataPointsDividedWidth = 0;
            this.tooltipTitle = null;
            this.legendLabels = null;
            this.ttItems = null;
            this.seriesBound = null;
            this.seriesHoverTimeout = void 0;
            this.clientX = 0;
            this.clientY = 0;
            this.barSeriesHeight = 0;
            this.tooltipRect = {
                x: 0,
                y: 0,
                ttWidth: 0,
                ttHeight: 0
            };
        }
        setupDimensionCache() {
            const w = this.w;
            const tooltipEl = this.getElTooltip();
            if (!tooltipEl) return;
            this.updateDimensionCache();
            if (typeof ResizeObserver !== "undefined" && !w.globals.resizeObserver) {
                w.globals.resizeObserver = new ResizeObserver(() => {
                    if (!this.dimensionUpdateScheduled) {
                        this.dimensionUpdateScheduled = true;
                        requestAnimationFrame(() => {
                            this.updateDimensionCache();
                            this.dimensionUpdateScheduled = false;
                        });
                    }
                });
                w.globals.resizeObserver.observe(tooltipEl);
            }
        }
        updateDimensionCache() {
            const w = this.w;
            const tooltipEl = this.getElTooltip();
            if (!tooltipEl) return;
            const rect = tooltipEl.getBoundingClientRect();
            w.globals.dimensionCache.tooltip = /** @type {any} */ {
                width: rect.width,
                height: rect.height,
                lastUpdate: Date.now()
            };
        }
        getCachedDimensions() {
            const w = this.w;
            if (w.globals.dimensionCache.tooltip) {
                const cache2 = (
                    /** @type {Record<string,any>} */
                    w.globals.dimensionCache.tooltip
                );
                const age = Date.now() - cache2.lastUpdate;
                if (age < 1e3) {
                    return {
                        ttWidth: cache2.width,
                        ttHeight: cache2.height
                    };
                }
            }
            this.updateDimensionCache();
            const cache = (
                /** @type {Record<string,any>} */
                w.globals.dimensionCache.tooltip
            );
            return cache ? {
                ttWidth: cache.width,
                ttHeight: cache.height
            } : {
                ttWidth: 0,
                ttHeight: 0
            };
        }
        /**
         * @param {{ w: import('../../types/internal').ChartStateW }} [ctx]
         * @returns {HTMLElement | null}
         */
        getElTooltip(ctx) {
            if (!ctx) ctx = this;
            if (!ctx.w.dom.baseEl) return null;
            return (
                /** @type {HTMLElement | null} */
                ctx.w.dom.baseEl.querySelector(".apexcharts-tooltip")
            );
        }
        getElXCrosshairs() {
            return this.w.dom.baseEl.querySelector(".apexcharts-xcrosshairs");
        }
        getElGrid() {
            return this.w.dom.baseEl.querySelector(".apexcharts-grid");
        }
        /**
         * @param {import('../../types/internal').XYRatios} xyRatios
         */
        drawTooltip(xyRatios) {
            const w = this.w;
            this.xyRatios = xyRatios;
            this.isXAxisTooltipEnabled = w.config.xaxis.tooltip.enabled && w.globals.axisCharts;
            this.yaxisTooltips = w.config.yaxis.map((y) => {
                return y.show && y.tooltip.enabled && w.globals.axisCharts ? true : false;
            });
            this.allTooltipSeriesGroups = [];
            if (!w.globals.axisCharts) {
                this.showTooltipTitle = false;
            }
            const existingTooltip = this.getElTooltip();
            if (existingTooltip == null ? void 0 : existingTooltip.parentNode) {
                existingTooltip.parentNode.removeChild(existingTooltip);
            }
            this.tooltipTitle = null;
            const tooltipEl = BrowserAPIs.createElementNS(
                "http://www.w3.org/1999/xhtml",
                "div"
            );
            tooltipEl.classList.add("apexcharts-tooltip");
            if (w.config.tooltip.cssClass) {
                tooltipEl.classList.add(w.config.tooltip.cssClass);
            }
            tooltipEl.classList.add(`apexcharts-theme-${this.tConfig.theme || "light"}`);
            if (this.tConfig.fillSeriesColor) {
                tooltipEl.classList.add("apexcharts-tooltip-fill-series");
            }
            if (this.tConfig.style && this.tConfig.style.background) {
                tooltipEl.style.setProperty(
                    "--apx-tt-bg",
                    this.tConfig.style.background
                );
            }
            const isSharedMulti = this.tConfig.shared && w.config.series.length > 1 && !w.globals.isBarHorizontal;
            const shouldDrawArrow = this.tConfig.arrow && !this.tConfig.followCursor && !this.tConfig.fixed.enabled && !isSharedMulti && !this.tConfig.fillSeriesColor && w.globals.axisCharts;
            if (shouldDrawArrow) {
                const arrowEl = BrowserAPIs.createElementNS(
                    "http://www.w3.org/1999/xhtml",
                    "div"
                );
                arrowEl.classList.add("apexcharts-tooltip-arrow");
                tooltipEl.appendChild(arrowEl);
            }
            if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.announcements.enabled) {
                tooltipEl.setAttribute("role", "tooltip");
                tooltipEl.setAttribute("aria-live", "polite");
                tooltipEl.setAttribute("aria-atomic", "true");
                tooltipEl.setAttribute("aria-hidden", "true");
            }
            w.dom.elWrap.appendChild(tooltipEl);
            if (w.globals.axisCharts) {
                this.axesTooltip.drawXaxisTooltip();
                this.axesTooltip.drawYaxisTooltip();
                this.axesTooltip.setXCrosshairWidth();
                this.axesTooltip.handleYCrosshair();
                const xAxis = new XAxis(this.w, this.ctx, void 0);
                this.xAxisTicksPositions = xAxis.getXAxisTicksPositions();
            }
            if ((w.globals.comboCharts || this.tConfig.intersect || w.config.chart.type === "rangeBar") && !this.tConfig.shared) {
                this.showOnIntersect = true;
            }
            if (w.config.markers.size === 0 || w.globals.markers.largestSize === 0) {
                this.marker.drawDynamicPoints();
            }
            if (w.globals.collapsedSeries.length === w.seriesData.series.length) return;
            this.dataPointsDividedHeight = w.layout.gridHeight / w.globals.dataPoints;
            this.dataPointsDividedWidth = w.layout.gridWidth / w.globals.dataPoints;
            if (this.showTooltipTitle) {
                this.tooltipTitle = BrowserAPIs.createElementNS(
                    "http://www.w3.org/1999/xhtml",
                    "div"
                );
                this.tooltipTitle.classList.add("apexcharts-tooltip-title");
                this.tooltipTitle.style.fontFamily = this.tConfig.style.fontFamily || w.config.chart.fontFamily;
                this.tooltipTitle.style.fontSize = this.tConfig.style.fontSize;
                tooltipEl.appendChild(this.tooltipTitle);
            }
            let ttItemsCnt = w.seriesData.series.length;
            if ((w.globals.xyCharts || w.globals.comboCharts) && this.tConfig.shared) {
                if (!this.showOnIntersect) {
                    ttItemsCnt = w.seriesData.series.length;
                } else {
                    ttItemsCnt = 1;
                }
            }
            this.legendLabels = w.dom.baseEl.querySelectorAll(".apexcharts-legend-text");
            this.ttItems = this.createTTElements(ttItemsCnt);
            this.addSVGEvents();
            this.setupDimensionCache();
        }
        /**
         * @param {number} ttItemsCnt
         */
        createTTElements(ttItemsCnt) {
            const w = this.w;
            const ttItems = [];
            const tooltipEl = this.getElTooltip();
            if (!tooltipEl) return ttItems;
            for (let i = 0; i < ttItemsCnt; i++) {
                const gTxt = BrowserAPIs.createElementNS(
                    "http://www.w3.org/1999/xhtml",
                    "div"
                );
                gTxt.classList.add(
                    "apexcharts-tooltip-series-group",
                    `apexcharts-tooltip-series-group-${i}`
                );
                gTxt.style.order = String(
                    w.config.tooltip.inverseOrder ? ttItemsCnt - i : i + 1
                );
                const point = BrowserAPIs.createElementNS(
                    "http://www.w3.org/1999/xhtml",
                    "span"
                );
                point.classList.add("apexcharts-tooltip-marker");
                if (w.config.tooltip.fillSeriesColor) {
                    point.style.backgroundColor = w.globals.colors[i];
                } else {
                    point.style.color = w.globals.colors[i];
                }
                const mShape = w.config.markers.shape;
                let shape = mShape;
                if (Array.isArray(mShape)) {
                    shape = mShape[i];
                }
                point.setAttribute("shape", shape);
                point.innerHTML = renderMarkerSVG(shape);
                gTxt.appendChild(point);
                const gYZ = BrowserAPIs.createElementNS(
                    "http://www.w3.org/1999/xhtml",
                    "div"
                );
                gYZ.classList.add("apexcharts-tooltip-text");
                gYZ.style.fontFamily = this.tConfig.style.fontFamily || w.config.chart.fontFamily;
                gYZ.style.fontSize = this.tConfig.style.fontSize;
                ["y", "goals", "z"].forEach((g) => {
                    const gValText = BrowserAPIs.createElementNS(
                        "http://www.w3.org/1999/xhtml",
                        "div"
                    );
                    gValText.classList.add(`apexcharts-tooltip-${g}-group`);
                    const txtLabel = BrowserAPIs.createElementNS(
                        "http://www.w3.org/1999/xhtml",
                        "span"
                    );
                    txtLabel.classList.add(`apexcharts-tooltip-text-${g}-label`);
                    gValText.appendChild(txtLabel);
                    const txtValue = BrowserAPIs.createElementNS(
                        "http://www.w3.org/1999/xhtml",
                        "span"
                    );
                    txtValue.classList.add(`apexcharts-tooltip-text-${g}-value`);
                    gValText.appendChild(txtValue);
                    gYZ.appendChild(gValText);
                });
                gTxt.appendChild(gYZ);
                tooltipEl.appendChild(gTxt);
                ttItems.push(gTxt);
            }
            return ttItems;
        }
        addSVGEvents() {
            const w = this.w;
            const type = w.config.chart.type;
            const tooltipEl = this.getElTooltip();
            if (!tooltipEl) return;
            const commonBar = !!(type === "bar" || type === "candlestick" || type === "boxPlot" || type === "rangeBar");
            const chartWithmarkers = type === "area" || type === "line" || type === "scatter" || type === "bubble" || type === "radar";
            const hoverArea = w.dom.Paper.node;
            const elGrid = this.getElGrid();
            if (elGrid) {
                this.seriesBound = elGrid.getBoundingClientRect();
            }
            const tooltipY = [];
            const tooltipX = [];
            const seriesHoverParams = {
                hoverArea,
                elGrid,
                tooltipEl,
                tooltipY,
                tooltipX,
                ttItems: this.ttItems
            };
            let points;
            if (w.globals.axisCharts) {
                if (chartWithmarkers) {
                    points = w.dom.baseEl.querySelectorAll(
                        ".apexcharts-series[data\\:longestSeries='true'] .apexcharts-marker"
                    );
                } else if (commonBar) {
                    points = w.dom.baseEl.querySelectorAll(
                        ".apexcharts-series .apexcharts-bar-area, .apexcharts-series .apexcharts-candlestick-area, .apexcharts-series .apexcharts-boxPlot-area, .apexcharts-series .apexcharts-rangebar-area"
                    );
                } else if (type === "heatmap" || type === "treemap") {
                    points = w.dom.baseEl.querySelectorAll(
                        ".apexcharts-series .apexcharts-heatmap, .apexcharts-series .apexcharts-treemap"
                    );
                }
                if (points && points.length) {
                    for (let p = 0; p < points.length; p++) {
                        tooltipY.push(points[p].getAttribute("cy"));
                        tooltipX.push(points[p].getAttribute("cx"));
                    }
                }
            }
            const validSharedChartTypes = w.globals.xyCharts && !this.showOnIntersect || w.globals.comboCharts && !this.showOnIntersect || commonBar && this.tooltipUtil.hasBars() && this.tConfig.shared;
            if (validSharedChartTypes) {
                this.addPathsEventListeners([hoverArea], seriesHoverParams);
            } else if (commonBar && !w.globals.comboCharts || chartWithmarkers && this.showOnIntersect) {
                this.addDatapointEventsListeners(seriesHoverParams);
            } else if (!w.globals.axisCharts || type === "heatmap" || type === "treemap") {
                const seriesAll = w.dom.baseEl.querySelectorAll(".apexcharts-series");
                this.addPathsEventListeners(seriesAll, seriesHoverParams);
            }
            if (this.showOnIntersect) {
                const lineAreaPoints = w.dom.baseEl.querySelectorAll(
                    ".apexcharts-line-series .apexcharts-marker, .apexcharts-area-series .apexcharts-marker"
                );
                if (lineAreaPoints.length > 0) {
                    this.addPathsEventListeners(lineAreaPoints, seriesHoverParams);
                }
                if (this.tooltipUtil.hasBars() && !this.tConfig.shared) {
                    this.addDatapointEventsListeners(seriesHoverParams);
                }
            }
        }
        drawFixedTooltipRect() {
            const w = this.w;
            const tooltipEl = this.getElTooltip();
            if (!tooltipEl) return {
                x: 0,
                y: 0,
                ttWidth: 0,
                ttHeight: 0
            };
            const tooltipRect = tooltipEl.getBoundingClientRect();
            const ttWidth = tooltipRect.width + 10;
            const ttHeight = tooltipRect.height + 10;
            let x = this.tConfig.fixed.offsetX;
            let y = this.tConfig.fixed.offsetY;
            const fixed = this.tConfig.fixed.position.toLowerCase();
            if (fixed.indexOf("right") > -1) {
                x = x + w.globals.svgWidth - ttWidth + 10;
            }
            if (fixed.indexOf("bottom") > -1) {
                y = y + w.globals.svgHeight - ttHeight - 10;
            }
            this.tooltipPosition.applyTooltipPosition(tooltipEl, {
                x,
                y
            });
            return {
                x,
                y,
                ttWidth,
                ttHeight
            };
        }
        /**
         * @param {Record<string, any>} seriesHoverParams
         */
        addDatapointEventsListeners(seriesHoverParams) {
            const w = this.w;
            const points = w.dom.baseEl.querySelectorAll(
                ".apexcharts-series-markers .apexcharts-marker, .apexcharts-bar-area, .apexcharts-candlestick-area, .apexcharts-boxPlot-area, .apexcharts-rangebar-area"
            );
            this.addPathsEventListeners(points, seriesHoverParams);
        }
        /**
         * @param {any} paths
         * @param {Record<string, any>} opts
         */
        addPathsEventListeners(paths, opts) {
            const self2 = this;
            for (let p = 0; p < paths.length; p++) {
                const extendedOpts = {
                    paths: paths[p],
                    tooltipEl: opts.tooltipEl,
                    tooltipY: opts.tooltipY,
                    tooltipX: opts.tooltipX,
                    elGrid: opts.elGrid,
                    hoverArea: opts.hoverArea,
                    ttItems: opts.ttItems
                };
                const events = [
                    "mousemove",
                    "mouseup",
                    "touchmove",
                    "mouseout",
                    "touchend"
                ];
                events.map((ev) => {
                    return paths[p].addEventListener(
                        ev,
                        self2.onSeriesHover.bind(self2, extendedOpts), {
                            capture: false,
                            passive: true
                        }
                    );
                });
            }
        }
        /*
         ** Check to see if the tooltips should be updated based on a mouse / touch event
         * @param {Record<string, any>} opt
         * @param {Event} e
         */
        /** @param {Record<string, any>} opt @param {any} e */
        onSeriesHover(opt, e) {
            const targetDelay = 20;
            const timeSinceLastUpdate = Date.now() - this.lastHoverTime;
            if (timeSinceLastUpdate >= targetDelay) {
                this.seriesHover(opt, e);
            } else {
                clearTimeout(this.seriesHoverTimeout);
                this.seriesHoverTimeout = setTimeout(() => {
                    this.seriesHover(opt, e);
                }, targetDelay - timeSinceLastUpdate);
            }
        }
        /*
         ** The actual series hover function
         * @param {Record<string, any>} opt
         * @param {Event} e
         */
        /** @param {Record<string, any>} opt @param {any} e */
        seriesHover(opt, e) {
            this.lastHoverTime = Date.now();
            let chartGroups = [];
            const w = this.w;
            if (w.config.chart.group) {
                chartGroups = this.ctx.getGroupedCharts();
            }
            if (w.globals.axisCharts && (w.globals.minX === -Infinity && w.globals.maxX === Infinity || w.globals.dataPoints === 0)) {
                return;
            }
            if (chartGroups.length) {
                chartGroups.forEach((ch) => {
                    const tooltipEl = this.getElTooltip(ch);
                    const newOpts = {
                        paths: opt.paths,
                        tooltipEl,
                        tooltipY: opt.tooltipY,
                        tooltipX: opt.tooltipX,
                        elGrid: opt.elGrid,
                        hoverArea: opt.hoverArea,
                        ttItems: ch.w.globals.tooltip.ttItems
                    };
                    if (ch.w.globals.minX === this.w.globals.minX && ch.w.globals.maxX === this.w.globals.maxX) {
                        ch.w.globals.tooltip.seriesHoverByContext({
                            chartCtx: ch,
                            ttCtx: ch.w.globals.tooltip,
                            opt: newOpts,
                            e
                        });
                    }
                });
            } else {
                this.seriesHoverByContext({
                    chartCtx: this.ctx,
                    ttCtx: this.w.globals.tooltip,
                    opt,
                    e
                });
            }
        }
        /** @param {{chartCtx: any, ttCtx: any, opt: any, e: any}} opts */
        seriesHoverByContext({
            chartCtx,
            ttCtx,
            opt,
            e
        }) {
            const w = chartCtx.w;
            const tooltipEl = this.getElTooltip(chartCtx);
            if (!tooltipEl) return;
            const cachedDims = ttCtx.getCachedDimensions();
            ttCtx.tooltipRect = {
                x: 0,
                y: 0,
                ttWidth: cachedDims.ttWidth,
                ttHeight: cachedDims.ttHeight
            };
            ttCtx.e = e;
            if (ttCtx.tooltipUtil.hasBars() && !w.globals.comboCharts && !ttCtx.isBarShared) {
                if (this.tConfig.onDatasetHover.highlightDataSeries) {
                    const series = new Series(chartCtx.w);
                    series.toggleSeriesOnHover(e, e.target.parentNode);
                }
            }
            if (w.globals.axisCharts) {
                ttCtx.axisChartsTooltips({
                    e,
                    opt,
                    tooltipRect: ttCtx.tooltipRect
                });
            } else {
                ttCtx.nonAxisChartsTooltips({
                    e,
                    opt,
                    tooltipRect: ttCtx.tooltipRect
                });
            }
            if (ttCtx.fixedTooltip) {
                ttCtx.drawFixedTooltipRect();
            }
        }
        // tooltip handling for line/area/bar/columns/scatter
        /** @param {{e: any, opt: any}} opts */
        axisChartsTooltips({
            e,
            opt
        }) {
            var _a;
            const w = this.w;
            let x, y;
            const seriesBound = opt.elGrid.getBoundingClientRect();
            const clientX = e.type === "touchmove" ? e.touches[0].clientX : e.clientX;
            const clientY = e.type === "touchmove" ? e.touches[0].clientY : e.clientY;
            this.clientY = clientY;
            this.clientX = clientX;
            w.interact.capturedSeriesIndex = -1;
            w.interact.capturedDataPointIndex = -1;
            if (clientY < seriesBound.top || clientY > seriesBound.top + seriesBound.height) {
                this.handleMouseOut(opt);
                return;
            }
            if (Array.isArray(this.tConfig.enabledOnSeries) && !w.config.tooltip.shared) {
                const index = parseInt(opt.paths.getAttribute("index"), 10);
                if (this.tConfig.enabledOnSeries.indexOf(index) < 0) {
                    this.handleMouseOut(opt);
                    return;
                }
            }
            const tooltipEl = this.getElTooltip();
            if (!tooltipEl) return;
            const xcrosshairs = this.getElXCrosshairs();
            let syncedCharts = [];
            if (w.config.chart.group) {
                syncedCharts = this.ctx.getSyncedCharts();
            }
            const isStickyTooltip = w.globals.xyCharts || w.config.chart.type === "bar" && !w.globals.isBarHorizontal && this.tooltipUtil.hasBars() && this.tConfig.shared || w.globals.comboCharts && this.tooltipUtil.hasBars();
            if (e.type === "mousemove" || e.type === "touchmove" || e.type === "mouseup") {
                if (w.globals.collapsedSeries.length + w.globals.ancillaryCollapsedSeries.length === w.seriesData.series.length) {
                    return;
                }
                if (xcrosshairs !== null) {
                    xcrosshairs.classList.add("apexcharts-active");
                }
                const hasYAxisTooltip = (_a = this.yaxisTooltips) == null ? void 0 : _a.filter(
                    (b) => {
                        return b === true;
                    }
                );
                const _yc = (
                    /** @type {any} */
                    this.ycrosshairs
                );
                if (_yc !== null && (hasYAxisTooltip == null ? void 0 : hasYAxisTooltip.length)) {
                    _yc.classList.add("apexcharts-active");
                }
                if (isStickyTooltip && !this.showOnIntersect || syncedCharts.length > 1) {
                    this.handleStickyTooltip(e, clientX, clientY, opt);
                } else {
                    if (w.config.chart.type === "heatmap" || w.config.chart.type === "treemap") {
                        const markerXY = this.intersect.handleHeatTreeTooltip({
                            e,
                            opt,
                            x,
                            y,
                            type: w.config.chart.type
                        });
                        x = markerXY.x;
                        y = markerXY.y;
                        tooltipEl.style.left = x + "px";
                        tooltipEl.style.top = y + "px";
                    } else {
                        if (this.tooltipUtil.hasBars()) {
                            this.intersect.handleBarTooltip({
                                e,
                                opt
                            });
                        }
                        if (this.tooltipUtil.hasMarkers(0)) {
                            this.intersect.handleMarkerTooltip({
                                e,
                                opt,
                                x,
                                y
                            });
                        }
                    }
                }
                if (this.yaxisTooltips && this.yaxisTooltips.length) {
                    for (let yt = 0; yt < w.config.yaxis.length; yt++) {
                        this.axesTooltip.drawYaxisTooltipText(
                            yt,
                            clientY,
                            /** @type {import('../../types/internal').XYRatios} */
                            this.xyRatios
                        );
                    }
                }
                w.dom.baseEl.classList.add("apexcharts-tooltip-active");
                opt.tooltipEl.classList.add("apexcharts-active");
                if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.announcements.enabled) {
                    opt.tooltipEl.removeAttribute("aria-hidden");
                }
            } else if (e.type === "mouseout" || e.type === "touchend") {
                this.handleMouseOut(opt);
            }
        }
        // tooltip handling for pie/donuts
        /** @param {{e: any, opt: any, tooltipRect: any}} opts */
        nonAxisChartsTooltips({
            e,
            opt,
            tooltipRect
        }) {
            var _a, _b, _c, _d;
            const w = this.w;
            const rel = opt.paths.getAttribute("rel");
            const tooltipEl = this.getElTooltip();
            if (!tooltipEl) return;
            const seriesBound = w.dom.elWrap.getBoundingClientRect();
            if (e.type === "mousemove" || e.type === "touchmove") {
                w.dom.baseEl.classList.add("apexcharts-tooltip-active");
                tooltipEl.classList.add("apexcharts-active");
                if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.announcements.enabled) {
                    tooltipEl.removeAttribute("aria-hidden");
                }
                this.tooltipLabels.drawSeriesTexts({
                    ttItems: opt.ttItems,
                    i: parseInt(rel, 10) - 1,
                    shared: false
                });
                let x, y;
                const arcPath = opt.paths.querySelector("path[data\\:cx]") || opt.paths;
                if (w.config.tooltip.intersect && arcPath.hasAttribute("data:cx") && arcPath.hasAttribute("data:cy")) {
                    const svgBound = w.dom.Paper.node.getBoundingClientRect();
                    x = svgBound.left - seriesBound.left + parseFloat(arcPath.getAttribute("data:cx")) - tooltipRect.ttWidth / 2;
                    y = svgBound.top - seriesBound.top + parseFloat(arcPath.getAttribute("data:cy")) - tooltipRect.ttHeight - 10;
                } else {
                    x = ((_a = w.interact.clientX) != null ? _a : 0) - seriesBound.left - tooltipRect.ttWidth / 2;
                    y = ((_b = w.interact.clientY) != null ? _b : 0) - seriesBound.top - tooltipRect.ttHeight - 10;
                }
                tooltipEl.style.left = x + "px";
                tooltipEl.style.top = y + "px";
                if (w.config.legend.tooltipHoverFormatter) {
                    const legendFormatter = w.config.legend.tooltipHoverFormatter;
                    const i = rel - 1;
                    const legendEl = (
                        /** @type {HTMLElement | undefined} */
                        (_c = this.legendLabels) == null ? void 0 : _c[i]
                    );
                    if (!legendEl) return;
                    const legendName = legendEl.getAttribute("data:default-text");
                    const text = legendFormatter(legendName, {
                        seriesIndex: i,
                        dataPointIndex: i,
                        w
                    });
                    legendEl.innerHTML = text;
                }
            } else if (e.type === "mouseout" || e.type === "touchend") {
                tooltipEl.classList.remove("apexcharts-active");
                w.dom.baseEl.classList.remove("apexcharts-tooltip-active");
                if (w.config.legend.tooltipHoverFormatter) {
                    (_d = this.legendLabels) == null ? void 0 : _d.forEach((l) => {
                        const defaultText = l.getAttribute("data:default-text");
                        l.innerHTML = decodeURIComponent(
                            defaultText != null ? defaultText : ""
                        );
                    });
                }
            }
        }
        /**
         * @param {Event} e
         * @param {number} clientX
         * @param {number} clientY
         * @param {Record<string, any>} opt
         */
        handleStickyTooltip(e, clientX, clientY, opt) {
            const w = this.w;
            const capj = this.tooltipUtil.getNearestValues({
                context: this,
                hoverArea: opt.hoverArea,
                elGrid: opt.elGrid,
                clientX,
                clientY
            });
            const j = capj.j;
            let capturedSeries = capj.capturedSeries;
            if (capturedSeries !== null && w.globals.collapsedSeriesIndices.includes(capturedSeries != null ? capturedSeries : -1))
                capturedSeries = null;
            const bounds = opt.elGrid.getBoundingClientRect();
            if (capj.hoverX < 0 || capj.hoverX > bounds.width) {
                this.handleMouseOut(opt);
                return;
            }
            if (capturedSeries !== null) {
                this.handleStickyCapturedSeries(e, capturedSeries != null ? capturedSeries : -1, opt, j != null ? j : 0);
            } else {
                if (this.tooltipUtil.isXoverlap(j != null ? j : 0) || w.globals.isBarHorizontal) {
                    const firstVisibleSeries = w.seriesData.series.findIndex(
                        /**
                         * @param {any} s
                         * @param {number} i
                         */
                        (s, i) => !w.globals.collapsedSeriesIndices.includes(i)
                    );
                    this.create(e, this, firstVisibleSeries, j != null ? j : 0, opt.ttItems);
                }
            }
        }
        /**
         * @param {Event} e
         * @param {number} capturedSeries
         * @param {Record<string, any>} opt
         * @param {number} j
         */
        handleStickyCapturedSeries(e, capturedSeries, opt, j) {
            const w = this.w;
            if (!this.tConfig.shared) {
                const ignoreNull = w.seriesData.series[capturedSeries][j] === null;
                if (ignoreNull) {
                    this.handleMouseOut(opt);
                    return;
                }
            }
            if (typeof w.seriesData.series[capturedSeries][j] !== "undefined") {
                if (this.tConfig.shared && this.tooltipUtil.isXoverlap(j) && this.tooltipUtil.isInitialSeriesSameLen()) {
                    this.create(e, this, capturedSeries, j, opt.ttItems);
                } else {
                    this.create(e, this, capturedSeries, j, opt.ttItems, false);
                }
            } else {
                if (this.tooltipUtil.isXoverlap(j)) {
                    const firstVisibleSeries = w.seriesData.series.findIndex(
                        /**
                         * @param {any} s
                         * @param {number} i
                         */
                        (s, i) => !w.globals.collapsedSeriesIndices.includes(i)
                    );
                    this.create(e, this, firstVisibleSeries, j, opt.ttItems);
                }
            }
        }
        deactivateHoverFilter() {
            const w = this.w;
            const graphics = new Graphics(this.w, this.ctx);
            const allPaths = w.dom.Paper.find(`.apexcharts-bar-area`);
            for (let b = 0; b < allPaths.length; b++) {
                graphics.pathMouseLeave(
                    /** @type {any} */
                    allPaths[b],
                    /** @type {any} */
                    void 0
                );
            }
        }
        /**
         * @param {Record<string, any>} opt
         */
        handleMouseOut(opt) {
            var _a, _b;
            const w = this.w;
            const xcrosshairs = this.getElXCrosshairs();
            w.dom.baseEl.classList.remove("apexcharts-tooltip-active");
            opt.tooltipEl.classList.remove("apexcharts-active");
            delete opt.tooltipEl.dataset.positioned;
            if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.announcements.enabled) {
                opt.tooltipEl.setAttribute("aria-hidden", "true");
            }
            this.deactivateHoverFilter();
            if (w.config.chart.type !== "bubble") {
                this.marker.resetPointsSize();
            }
            if (xcrosshairs !== null) {
                xcrosshairs.classList.remove("apexcharts-active");
            }
            const _yc2 = (
                /** @type {any} */
                this.ycrosshairs
            );
            if (_yc2 !== null) {
                _yc2.classList.remove("apexcharts-active");
            }
            if (this.isXAxisTooltipEnabled) {
                (_a = this.xaxisTooltip) == null ? void 0 : _a.classList.remove("apexcharts-active");
            }
            if (this.yaxisTooltips && this.yaxisTooltips.length) {
                if (this.yaxisTTEls === null) {
                    this.yaxisTTEls = /** @type {HTMLElement[]} */ [
                        ...w.dom.baseEl.querySelectorAll(".apexcharts-yaxistooltip")
                    ];
                }
                for (let i = 0; i < this.yaxisTTEls.length; i++) {
                    this.yaxisTTEls[i].classList.remove("apexcharts-active");
                }
            }
            if (w.config.legend.tooltipHoverFormatter) {
                (_b = this.legendLabels) == null ? void 0 : _b.forEach((l) => {
                    const defaultText = l.getAttribute("data:default-text");
                    l.innerHTML = decodeURIComponent(
                        defaultText != null ? defaultText : ""
                    );
                });
            }
        }
        /**
         * @param {Event} e
         * @param {number} seriesIndex
         * @param {number} dataPointIndex
         */
        markerClick(e, seriesIndex, dataPointIndex) {
            const w = this.w;
            if (typeof w.config.chart.events.markerClick === "function") {
                w.config.chart.events.markerClick(e, this.ctx, {
                    seriesIndex,
                    dataPointIndex,
                    w
                });
            }
            this.ctx.events.fireEvent("markerClick", [
                e,
                this.ctx,
                {
                    seriesIndex,
                    dataPointIndex,
                    w
                }
            ]);
        }
        /**
         * @param {Event} e
         * @param {any} context
         * @param {number} capturedSeries
         * @param {number} j
         * @param {any} ttItems
         * @param {boolean | null} shared
         */
        create(e, context, capturedSeries, j, ttItems, shared = null) {
            var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
            const w = this.w;
            const ttCtx = context;
            if (e.type === "mouseup") {
                this.markerClick(e, capturedSeries, j);
            }
            if (shared === null) shared = this.tConfig.shared;
            const hasMarkers = this.tooltipUtil.hasMarkers(capturedSeries);
            const bars = this.tooltipUtil.getElBars();
            const handlePoints = () => {
                if (w.globals.markers.largestSize > 0) {
                    ttCtx.marker.enlargePoints(j);
                } else {
                    ttCtx.tooltipPosition.moveDynamicPointsOnHover(j);
                }
            };
            if (w.config.legend.tooltipHoverFormatter) {
                const legendFormatter = w.config.legend.tooltipHoverFormatter;
                const els = (
                    /** @type {HTMLElement[]} */
                    Array.from((_a = this.legendLabels) != null ? _a : [])
                );
                els.forEach((l) => {
                    const legendName = l.getAttribute("data:default-text");
                    l.innerHTML = decodeURIComponent(legendName != null ? legendName : "");
                });
                for (let i = 0; i < els.length; i++) {
                    const l = els[i];
                    const lsIndex = parseInt((_b = l.getAttribute("i")) != null ? _b : "", 10);
                    const legendName = decodeURIComponent(
                        (_c = l.getAttribute("data:default-text")) != null ? _c : ""
                    );
                    const text = legendFormatter(legendName, {
                        seriesIndex: shared ? lsIndex : capturedSeries,
                        dataPointIndex: j,
                        w
                    });
                    if (!shared) {
                        l.innerHTML = lsIndex === capturedSeries ? text : legendName;
                        if (capturedSeries === lsIndex) {
                            break;
                        }
                    } else {
                        l.innerHTML = w.globals.collapsedSeriesIndices.indexOf(lsIndex) < 0 ? text : legendName;
                    }
                }
            }
            const _rangeData = (
                /** @type {any} */
                w.rangeData
            );
            const commonSeriesTextsParams = __spreadValues(__spreadValues({
                ttItems,
                i: capturedSeries,
                j
            }, ((_g = (_f = (_e = (_d = _rangeData.seriesRange) == null ? void 0 : _d[capturedSeries]) == null ? void 0 : _e[j]) == null ? void 0 : _f.y[0]) == null ? void 0 : _g.y1) !== void 0 && {
                y1: (_k = (_j = (_i = (_h = _rangeData.seriesRange) == null ? void 0 : _h[capturedSeries]) == null ? void 0 : _i[j]) == null ? void 0 : _j.y[0]) == null ? void 0 : _k.y1
            }), ((_o = (_n = (_m = (_l = _rangeData.seriesRange) == null ? void 0 : _l[capturedSeries]) == null ? void 0 : _m[j]) == null ? void 0 : _n.y[0]) == null ? void 0 : _o.y2) !== void 0 && {
                y2: (_s = (_r = (_q = (_p = _rangeData.seriesRange) == null ? void 0 : _p[capturedSeries]) == null ? void 0 : _q[j]) == null ? void 0 : _r.y[0]) == null ? void 0 : _s.y2
            });
            if (shared) {
                ttCtx.tooltipLabels.drawSeriesTexts(__spreadProps(__spreadValues({}, commonSeriesTextsParams), {
                    shared: this.showOnIntersect ? false : this.tConfig.shared
                }));
                if (hasMarkers) {
                    handlePoints();
                } else if (this.tooltipUtil.hasBars()) {
                    this.barSeriesHeight = this.tooltipUtil.getBarsHeight(
                        /** @type {any[]} */
                        [...bars]
                    );
                    if (this.barSeriesHeight > 0) {
                        const graphics = new Graphics(this.w, this.ctx);
                        const paths = w.dom.Paper.find(`.apexcharts-bar-area[j='${j}']`);
                        this.deactivateHoverFilter();
                        const points = ttCtx.tooltipUtil.getAllMarkers(true);
                        if (points.length && !this.barSeriesHeight) {
                            handlePoints();
                        }
                        ttCtx.tooltipPosition.moveStickyTooltipOverBars(j, capturedSeries);
                        for (let b = 0; b < paths.length; b++) {
                            graphics.pathMouseEnter(
                                /** @type {any} */
                                paths[b],
                                /** @type {any} */
                                void 0
                            );
                        }
                    }
                }
            } else {
                ttCtx.tooltipLabels.drawSeriesTexts(__spreadValues({
                    shared: false
                }, commonSeriesTextsParams));
                if (this.tooltipUtil.hasBars()) {
                    ttCtx.tooltipPosition.moveStickyTooltipOverBars(j, capturedSeries);
                }
                if (hasMarkers) {
                    ttCtx.tooltipPosition.moveMarkers(capturedSeries, j);
                }
            }
        }
    }
    class SVGElement {
        /**
         * @param {any} node
         */
        constructor(node) {
            this.node = node;
            if (node) {
                node.instance = this;
            }
            this._listeners = [];
            this._filter = null;
        }
        // ---- Attribute methods ----
        /**
         * @param {any} a
         * @param {any} [v]
         */
        attr(a, v) {
            if (typeof a === "string" && v === void 0) {
                return this.node.getAttribute(a);
            }
            const attrs = typeof a === "string" ? {
                [a]: v
            } : a;
            for (const key in attrs) {
                let val = attrs[key];
                if (val === null) {
                    this.node.removeAttribute(key);
                } else if (val !== void 0) {
                    if (typeof val === "number" && isNaN(val)) val = 0;
                    this.node.setAttribute(key, val);
                }
            }
            if (this.node.nodeName === "text" && attrs.x != null) {
                const tspans = this.node.querySelectorAll("tspan[data-newline]");
                for (let i = 0; i < tspans.length; i++) {
                    tspans[i].setAttribute("x", attrs.x);
                }
            }
            return this;
        }
        /**
         * @param {Record<string, string>} styles
         */
        css(styles) {
            for (const k in styles) {
                this.node.style[k] = styles[k];
            }
            return this;
        }
        /**
         * @param {any} v
         */
        fill(v) {
            if (typeof v === "object") {
                return this.attr(v);
            }
            return this.attr("fill", v);
        }
        /**
         * @param {any} v
         */
        stroke(v) {
            if (typeof v === "object") {
                if (v.color !== void 0) this.attr("stroke", v.color);
                if (v.width !== void 0) this.attr("stroke-width", v.width);
                if (v.dasharray !== void 0) this.attr("stroke-dasharray", v.dasharray);
                if (v.linecap !== void 0) this.attr("stroke-linecap", v.linecap);
                if (v.opacity !== void 0) this.attr("stroke-opacity", v.opacity);
                return this;
            }
            return this.attr("stroke", v);
        }
        /**
         * @param {number} w
         * @param {number} h
         */
        size(w, h) {
            return this.attr({
                width: w,
                height: h
            });
        }
        /**
         * @param {number} x
         * @param {number} y
         */
        move(x, y) {
            return this.attr({
                x,
                y
            });
        }
        /**
         * @param {number} cx
         * @param {number} cy
         */
        center(cx, cy) {
            if (this.node.nodeName === "g") {
                const box = this.bbox();
                const dx = cx - (box.x + box.width / 2);
                const dy = cy - (box.y + box.height / 2);
                return this.attr("transform", `translate(${dx}, ${dy})`);
            }
            return this.attr({
                cx,
                cy
            });
        }
        // ---- Tree operations ----
        /**
         * @param {any} child
         */
        add(child) {
            this.node.appendChild(child.node || child);
            return this;
        }
        /**
         * @param {any} parent
         */
        addTo(parent) {
            const p = parent.node || parent;
            p.appendChild(this.node);
            return this;
        }
        remove() {
            if (this.node.parentNode) {
                this.node.parentNode.removeChild(this.node);
            }
            return this;
        }
        clear() {
            while (this.node.firstChild) {
                this.node.removeChild(this.node.firstChild);
            }
            return this;
        }
        // ---- Query ----
        /**
         * @param {string} selector
         */
        find(selector) {
            return Array.from(this.node.querySelectorAll(selector)).map(
                (n) => n.instance || new SVGElement(n)
            );
        }
        /**
         * @param {string} selector
         */
        findOne(selector) {
            const n = this.node.querySelector(selector);
            return n ? n.instance || new SVGElement(n) : null;
        }
        // ---- Events ----
        /**
         * @param {Event} event
         * @param {Function} handler
         */
        on(event, handler) {
            const eventType = (
                /** @type {string} */
                /** @type {any} */
                event.split(
                    "."
                )[0]
            );
            this._listeners.push({
                event,
                eventType,
                handler
            });
            this.node.addEventListener(eventType, handler);
            return this;
        }
        /**
         * @param {Event} event
         * @param {Function} handler
         */
        off(event, handler) {
            if (!event && !handler) {
                this._listeners.forEach((l) => {
                    this.node.removeEventListener(l.eventType, l.handler);
                });
                this._listeners = [];
            } else if (event && !handler) {
                const eventType = (
                    /** @type {string} */
                    /** @type {any} */
                    event.split(".")[0]
                );
                this._listeners = this._listeners.filter((l) => {
                    if (l.eventType === eventType) {
                        this.node.removeEventListener(l.eventType, l.handler);
                        return false;
                    }
                    return true;
                });
            } else {
                const eventType = (
                    /** @type {string} */
                    /** @type {any} */
                    event.split(".")[0]
                );
                this._listeners = this._listeners.filter((l) => {
                    if (l.eventType === eventType && l.handler === handler) {
                        this.node.removeEventListener(l.eventType, l.handler);
                        return false;
                    }
                    return true;
                });
            }
            return this;
        }
        // ---- Iteration ----
        /**
         * @param {Function} fn
         * @param {boolean} deep
         */
        each(fn, deep) {
            const children = Array.from(this.node.children);
            children.forEach((child) => {
                const inst = child.instance || new SVGElement(child);
                fn.call(inst);
                if (deep) inst.each(fn, deep);
            });
            return this;
        }
        // ---- CSS classes ----
        /**
         * @param {string} cls
         */
        removeClass(cls) {
            if (cls === "*") {
                this.node.removeAttribute("class");
            } else {
                this.node.classList.remove(cls);
            }
            return this;
        }
        // ---- Children ----
        children() {
            return Array.from(this.node.childNodes).filter((n) => n.nodeType === 1).map((n) => n.instance || new SVGElement(n));
        }
        // ---- Visibility ----
        hide() {
            this.node.style.display = "none";
            return this;
        }
        show() {
            this.node.style.display = "";
            return this;
        }
        // ---- Measurement ----
        bbox() {
            if (typeof this.node.getBBox === "function") {
                try {
                    return this.node.getBBox();
                } catch (e) {}
            }
            return {
                x: 0,
                y: 0,
                width: 0,
                height: 0
            };
        }
        // ---- Text-specific ----
        /**
         * @param {string} text
         */
        tspan(text) {
            const tspan = BrowserAPIs.createElementNS(
                "http://www.w3.org/2000/svg",
                "tspan"
            );
            tspan.textContent = text;
            this.node.appendChild(tspan);
            return new SVGElement(tspan);
        }
        // ---- Path-specific ----
        /**
         * @param {string} d
         */
        plot(d) {
            if (typeof d === "string") {
                this.attr("d", d);
            }
            return this;
        }
        // ---- Animation (overridden by SVGAnimation mixin) ----
        animate() {
            throw new Error("Animation module not loaded");
        }
        // ---- Filter methods (set up by SVGFilter module) ----
        filterWith() {
            throw new Error("Filter module not loaded");
        }
        /**
         * @param {boolean} all
         */
        unfilter(all) {
            if (this._filter) {
                this.node.removeAttribute("filter");
                if (all && this._filter.node && this._filter.node.parentNode) {
                    this._filter.node.parentNode.removeChild(this._filter.node);
                }
                this._filter = null;
            }
            return this;
        }
        filterer() {
            return this._filter;
        }
    }
    let gradientCounter = 0;
    class SVGGradient extends SVGElement {
        /**
         * @param {any} container
         * @param {string} type
         * @param {object} builder
         */
        constructor(container, type, builder) {
            const tag = type === "radial" ? "radialGradient" : "linearGradient";
            const node = BrowserAPIs.createElementNS(SVGNS, tag);
            super(node);
            this._id = "SvgjsGradient" + ++gradientCounter;
            this.attr("id", this._id);
            if (typeof builder === "function") {
                builder(new StopBuilder(this));
            }
            let defs = container.node.querySelector("defs");
            if (!defs) {
                defs = BrowserAPIs.createElementNS(SVGNS, "defs");
                container.node.appendChild(defs);
            }
            defs.appendChild(this.node);
        }
        /**
         * @param {any} offset
         * @param {string} color
         * @param {number} opacity
         */
        stop(offset, color, opacity) {
            const s = BrowserAPIs.createElementNS(SVGNS, "stop");
            s.setAttribute("offset", offset);
            s.setAttribute("stop-color", color);
            if (opacity !== void 0) s.setAttribute("stop-opacity", String(opacity));
            this.node.appendChild(s);
            return this;
        }
        /**
         * @param {number} x
         * @param {number} y
         */
        from(x, y) {
            return this.attr({
                x1: x,
                y1: y
            });
        }
        /**
         * @param {number} x
         * @param {number} y
         */
        to(x, y) {
            return this.attr({
                x2: x,
                y2: y
            });
        }
        url() {
            return "url(#" + this._id + ")";
        }
        toString() {
            return this.url();
        }
        valueOf() {
            return this.url();
        }
        fill() {
            return this.url();
        }
    }
    class StopBuilder {
        /**
         * @param {any} gradient
         */
        constructor(gradient) {
            this.gradient = gradient;
        }
        /**
         * @param {any} offset
         * @param {string} color
         * @param {number} opacity
         */
        stop(offset, color, opacity) {
            this.gradient.stop(offset, color, opacity);
            return this;
        }
    }
    let patternCounter = 0;
    class SVGPattern extends SVGElement {
        /**
         * @param {any} container
         * @param {number} w
         * @param {number} h
         * @param {Function} builder
         */
        constructor(container, w, h, builder) {
            const node = BrowserAPIs.createElementNS(SVGNS, "pattern");
            super(node);
            this._id = "SvgjsPattern" + ++patternCounter;
            this.attr({
                id: this._id,
                width: w,
                height: h,
                patternUnits: "userSpaceOnUse"
            });
            if (typeof builder === "function") {
                const patternContainer = new SVGContainer(this.node);
                builder(patternContainer);
            }
            let defs = container.node.querySelector("defs");
            if (!defs) {
                defs = BrowserAPIs.createElementNS(SVGNS, "defs");
                container.node.appendChild(defs);
            }
            defs.appendChild(this.node);
        }
        url() {
            return "url(#" + this._id + ")";
        }
        toString() {
            return this.url();
        }
        valueOf() {
            return this.url();
        }
        fill() {
            return this.url();
        }
    }
    class SVGContainer extends SVGElement {
        /**
         * @param {number} x1
         * @param {number} y1
         * @param {number} x2
         * @param {number} y2
         */
        line(x1, y1, x2, y2) {
            const el = this._make("line");
            if (x1 !== void 0) {
                el.attr({
                    x1,
                    y1,
                    x2,
                    y2
                });
            }
            return el;
        }
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {number} h
         */
        rect(w, h) {
            const el = this._make("rect");
            if (w !== void 0) {
                el.attr({
                    width: w,
                    height: h
                });
            }
            return el;
        }
        /**
         * @param {number} d
         */
        circle(d) {
            const el = this._make("circle");
            if (d !== void 0) {
                el.attr({
                    r: d / 2,
                    cx: d / 2,
                    cy: d / 2
                });
            }
            return el;
        }
        /**
         * @param {string} d
         */
        path(d) {
            const el = this._make("path");
            if (d) el.attr("d", d);
            return el;
        }
        /**
         * @param {string} pts
         */
        polygon(pts) {
            const el = this._make("polygon");
            if (pts) el.attr("points", pts);
            return el;
        }
        group() {
            return this._makeContainer("g");
        }
        defs() {
            return this._makeContainer("defs");
        }
        /**
         * @param {string} textContent
         */
        plain(textContent) {
            const node = BrowserAPIs.createElementNS(SVGNS, "text");
            node.textContent = textContent;
            const el = new SVGElement(node);
            this.node.appendChild(node);
            return el;
        }
        /**
         * @param {object} builder
         */
        text(builder) {
            const node = BrowserAPIs.createElementNS(SVGNS, "text");
            const el = new SVGElement(node);
            this.node.appendChild(node);
            if (typeof builder === "function") {
                builder(new TspanBuilder(node));
            }
            return el;
        }
        /**
         * @param {string} url
         * @param {Function} callback
         */
        image(url, callback) {
            const node = BrowserAPIs.createElementNS(SVGNS, "image");
            node.setAttributeNS("http://www.w3.org/1999/xlink", "href", url);
            const el = new SVGElement(node);
            this.node.appendChild(node);
            if (typeof callback === "function") {
                const img = new Image();
                img.onload = function() {
                    el.size(img.width, img.height);
                    callback.call(el, {
                        width: img.width,
                        height: img.height
                    });
                };
                img.src = url;
            }
            return el;
        }
        /**
         * @param {string} type
         * @param {object} builder
         */
        gradient(type, builder) {
            return new SVGGradient(this, type, builder);
        }
        /**
         * @param {number} w
         * @param {number} h
         * @param {Function} builder
         */
        pattern(w, h, builder) {
            return new SVGPattern(this, w, h, builder);
        }
        /**
         * @param {string} tag
         */
        _make(tag) {
            const node = BrowserAPIs.createElementNS(SVGNS, tag);
            this.node.appendChild(node);
            return new SVGElement(node);
        }
        /**
         * @param {string} tag
         */
        _makeContainer(tag) {
            const node = BrowserAPIs.createElementNS(SVGNS, tag);
            this.node.appendChild(node);
            return new SVGContainer(node);
        }
    }
    class TspanBuilder {
        /**
         * @param {any} textNode
         */
        constructor(textNode) {
            this.textNode = textNode;
        }
        /**
         * @param {string} text
         */
        tspan(text) {
            const tspan = BrowserAPIs.createElementNS(SVGNS, "tspan");
            tspan.textContent = text;
            this.textNode.appendChild(tspan);
            return new TspanWrapper(tspan, this.textNode);
        }
    }
    class TspanWrapper {
        /**
         * @param {any} node
         * @param {any} textNode
         */
        constructor(node, textNode) {
            this.node = node;
            this.textNode = textNode;
        }
        newLine() {
            this.node.setAttribute("dy", "1.1em");
            this.node.dataset.newline = "1";
            return this;
        }
    }
    let filterCounter = 0;
    class SVGFilter extends SVGElement {
        constructor() {
            const node = BrowserAPIs.createElementNS(SVGNS, "filter");
            super(node);
            this._id = "SvgjsFilter" + ++filterCounter;
            this.attr("id", this._id);
        }
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {number} h
         * @param {number} x
         * @param {number} y
         */
        /**
         * @param {number} w
         * @param {number} h
         * @param {number} [x]
         * @param {number} [y]
         */
        size(w, h, x, y) {
            return this.attr({
                width: w,
                height: h,
                x,
                y
            });
        }
    }
    class FilterBuilder {
        /**
         * @param {any} filter
         */
        constructor(filter) {
            this.filter = filter;
        }
        /**
         * @param {object} attrs
         */
        colorMatrix(attrs) {
            return this._primitive("feColorMatrix", attrs);
        }
        /**
         * @param {object} attrs
         */
        offset(attrs) {
            return this._primitive("feOffset", attrs);
        }
        /**
         * @param {object} attrs
         */
        gaussianBlur(attrs) {
            return this._primitive("feGaussianBlur", attrs);
        }
        /**
         * @param {object} attrs
         */
        flood(attrs) {
            return this._primitive("feFlood", attrs);
        }
        /**
         * @param {object} attrs
         */
        composite(attrs) {
            return this._primitive("feComposite", attrs);
        }
        /**
         * @param {string[]} sources
         */
        merge(sources) {
            const m = BrowserAPIs.createElementNS(SVGNS, "feMerge");
            sources.forEach((src) => {
                const mn = BrowserAPIs.createElementNS(SVGNS, "feMergeNode");
                mn.setAttribute("in", src);
                m.appendChild(mn);
            });
            this.filter.node.appendChild(m);
            return new SVGElement(m);
        }
        /**
         * @param {string} tag
         * @param {Record<string, any>} attrs
         */
        _primitive(tag, attrs) {
            const el = BrowserAPIs.createElementNS(SVGNS, tag);
            for (const key in attrs) {
                el.setAttribute(key, attrs[key]);
            }
            this.filter.node.appendChild(el);
            return new SVGElement(el);
        }
    }

    function installFilterMethods(ElementClass) {
        ElementClass.prototype.filterWith = function(fn) {
            const filter = new SVGFilter();
            this._filter = filter;
            let svgRoot = this.node;
            while (svgRoot && svgRoot.nodeName !== "svg") {
                svgRoot = svgRoot.parentNode;
            }
            if (svgRoot) {
                let defs = svgRoot.querySelector("defs");
                if (!defs) {
                    defs = BrowserAPIs.createElementNS(SVGNS, "defs");
                    svgRoot.insertBefore(defs, svgRoot.firstChild);
                }
                defs.appendChild(filter.node);
            }
            fn(new FilterBuilder(filter));
            this.attr("filter", "url(#" + filter._id + ")");
            return this;
        };
        ElementClass.prototype.unfilter = function(all) {
            if (this._filter) {
                this.node.removeAttribute("filter");
                if (all && this._filter.node && this._filter.node.parentNode) {
                    this._filter.node.parentNode.removeChild(this._filter.node);
                }
                this._filter = null;
            }
            return this;
        };
        ElementClass.prototype.filterer = function() {
            return this._filter;
        };
    }
    /*!
     * Path morphing for SVG path animations
     * Based on svg.pathmorphing.js by Ulrich-Matthias Schäfer (MIT License)
     * Refactored to be standalone (no SVG.js dependency)
     *
     * Two algorithms are exported:
     *   - morphPaths()    — command-level interpolation; preserves curves but can
     *                       produce "wings/flips" when two shapes have very
     *                       different topology (e.g. bar rect → pie arc).
     *   - morphPolygons() — resamples both shapes into N evenly-spaced perimeter
     *                       points and tweens point-by-point with rotation-search
     *                       alignment; always smooth and non-self-intersecting,
     *                       at the cost of throwing away curve smoothness.
     */
    function parsePath(d) {
        if (!d || typeof d !== "string") return [
            ["M", 0, 0]
        ];
        const commands = [];
        const re = /([MmLlHhVvCcSsQqTtAaZz])\s*/g;
        const numRe = /[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?/gi;
        let match;
        const letters = [];
        const positions = [];
        while ((match = re.exec(d)) !== null) {
            letters.push(match[1]);
            positions.push(match.index);
        }
        for (let i = 0; i < letters.length; i++) {
            const start = positions[i] + letters[i].length;
            const end = i + 1 < positions.length ? positions[i + 1] : d.length;
            const paramStr = d.substring(start, end);
            const nums = [];
            let numMatch;
            numRe.lastIndex = 0;
            while ((numMatch = numRe.exec(paramStr)) !== null) {
                nums.push(parseFloat(numMatch[0]));
            }
            const cmd = letters[i].toUpperCase();
            if (cmd === "Z") {
                commands.push(["Z"]);
            } else if (cmd === "M" || cmd === "L" || cmd === "T") {
                for (let j = 0; j < nums.length; j += 2) {
                    commands.push([cmd, nums[j], nums[j + 1]]);
                }
            } else if (cmd === "H") {
                for (let j = 0; j < nums.length; j++) {
                    commands.push([cmd, nums[j]]);
                }
            } else if (cmd === "V") {
                for (let j = 0; j < nums.length; j++) {
                    commands.push([cmd, nums[j]]);
                }
            } else if (cmd === "C") {
                for (let j = 0; j < nums.length; j += 6) {
                    commands.push([
                        cmd,
                        nums[j],
                        nums[j + 1],
                        nums[j + 2],
                        nums[j + 3],
                        nums[j + 4],
                        nums[j + 5]
                    ]);
                }
            } else if (cmd === "S" || cmd === "Q") {
                for (let j = 0; j < nums.length; j += 4) {
                    commands.push([cmd, nums[j], nums[j + 1], nums[j + 2], nums[j + 3]]);
                }
            } else if (cmd === "A") {
                for (let j = 0; j < nums.length; j += 7) {
                    commands.push([
                        cmd,
                        nums[j],
                        nums[j + 1],
                        nums[j + 2],
                        nums[j + 3],
                        nums[j + 4],
                        nums[j + 5],
                        nums[j + 6]
                    ]);
                }
            }
        }
        if (commands.length === 0) {
            commands.push(["M", 0, 0]);
        }
        return commands;
    }

    function pathBbox(arr) {
        let minX = Infinity,
            minY = Infinity,
            maxX = -Infinity,
            maxY = -Infinity;
        arr.forEach((cmd) => {
            for (let i = 1; i < cmd.length; i += 2) {
                if (i + 1 <= cmd.length) {
                    const x = cmd[i];
                    const y = cmd[i + 1];
                    if (typeof x === "number" && typeof y === "number") {
                        if (x < minX) minX = x;
                        if (x > maxX) maxX = x;
                        if (y < minY) minY = y;
                        if (y > maxY) maxY = y;
                    }
                }
            }
        });
        if (minX === Infinity) {
            return {
                x: 0,
                y: 0,
                width: 0,
                height: 0
            };
        }
        return {
            x: minX,
            y: minY,
            width: maxX - minX,
            height: maxY - minY
        };
    }

    function arrayToPath(arr) {
        return arr.map((cmd) => cmd.join(" ")).join(" ");
    }

    function simplify(val) {
        switch (val[0]) {
            case "z":
            case "Z":
                val[0] = "L";
                val[1] = this.start[0];
                val[2] = this.start[1];
                break;
            case "H":
                val[0] = "L";
                val[2] = this.pos[1];
                break;
            case "V":
                val[0] = "L";
                val[2] = val[1];
                val[1] = this.pos[0];
                break;
            case "T":
                val[0] = "Q";
                val[3] = val[1];
                val[4] = val[2];
                val[1] = this.reflection[1];
                val[2] = this.reflection[0];
                break;
            case "S":
                val[0] = "C";
                val[6] = val[4];
                val[5] = val[3];
                val[4] = val[2];
                val[3] = val[1];
                val[2] = this.reflection[1];
                val[1] = this.reflection[0];
                break;
        }
        return val;
    }

    function setPosAndReflection(val) {
        var len = val.length;
        this.pos = [val[len - 2], val[len - 1]];
        if ("SCQT".indexOf(val[0]) != -1) {
            this.reflection = [
                2 * this.pos[0] - val[len - 4],
                2 * this.pos[1] - val[len - 3]
            ];
        }
        return val;
    }

    function toBezier(val) {
        var _a;
        var retVal = [val];
        switch (val[0]) {
            case "M":
                this.pos = this.start = [val[1], val[2]];
                return retVal;
            case "L":
                val[5] = val[3] = val[1];
                val[6] = val[4] = val[2];
                val[1] = this.pos[0];
                val[2] = this.pos[1];
                break;
            case "Q":
                val[6] = val[4];
                val[5] = val[3];
                val[4] = val[4] * 1 / 3 + val[2] * 2 / 3;
                val[3] = val[3] * 1 / 3 + val[1] * 2 / 3;
                val[2] = this.pos[1] * 1 / 3 + val[2] * 2 / 3;
                val[1] = this.pos[0] * 1 / 3 + val[1] * 2 / 3;
                break;
            case "A":
                retVal = arcToBezier((_a = this.pos) != null ? _a : [], val);
                val = retVal[0];
                break;
        }
        val[0] = "C";
        this.pos = [val[5], val[6]];
        this.reflection = [2 * val[5] - val[3], 2 * val[6] - val[4]];
        return retVal;
    }

    function findNextM(arr, offset) {
        if (offset === false) return false;
        for (var i = offset, len = arr.length; i < len; ++i) {
            if (arr[i][0] == "M") return i;
        }
        return false;
    }

    function arcToBezier(pos, val) {
        var rx = Math.abs(val[1]),
            ry = Math.abs(val[2]),
            xAxisRotation = val[3] % 360,
            largeArcFlag = val[4],
            sweepFlag = val[5],
            x = val[6],
            y = val[7],
            A = new Point(pos[0], pos[1]),
            B = new Point(x, y),
            primedCoord, lambda, mat, k, c, cSquare, t, O, OA, OB, tetaStart, tetaEnd, deltaTeta, nbSectors, f, arcSegPoints, angle, sinAngle, cosAngle, pt, i, il, retVal = [],
            x1, y1, x2, y2;
        if (rx === 0 || ry === 0 || A.x === B.x && A.y === B.y) {
            return [
                ["C", A.x, A.y, B.x, B.y, B.x, B.y]
            ];
        }
        primedCoord = new Point((A.x - B.x) / 2, (A.y - B.y) / 2).transform(
            // Start with the identity matrix (no args → Matrix defaults a=d=1, others 0).
            // Passing all-zero args here would produce a degenerate zero matrix, since
            // `0 ?? 1` is `0`, not `1` — every subsequent transform then yields (0,0)
            // and the arc-to-bezier conversion crashes on a NaN cascade.
            /** @type {any} */
            new Matrix().rotate(xAxisRotation)
        );
        lambda = primedCoord.x * primedCoord.x / (rx * rx) + primedCoord.y * primedCoord.y / (ry * ry);
        if (lambda > 1) {
            lambda = Math.sqrt(lambda);
            rx = lambda * rx;
            ry = lambda * ry;
        }
        mat = /** @type {any} */
            new Matrix().rotate(xAxisRotation).scale(1 / rx, 1 / ry).rotate(-xAxisRotation);
        A = A.transform(mat);
        B = B.transform(mat);
        k = [B.x - A.x, B.y - A.y];
        cSquare = k[0] * k[0] + k[1] * k[1];
        c = Math.sqrt(cSquare);
        k[0] /= c;
        k[1] /= c;
        t = cSquare < 4 ? Math.sqrt(1 - cSquare / 4) : 0;
        if (largeArcFlag === sweepFlag) {
            t *= -1;
        }
        O = new Point((B.x + A.x) / 2 + t * -k[1], (B.y + A.y) / 2 + t * k[0]);
        OA = new Point(A.x - O.x, A.y - O.y);
        OB = new Point(B.x - O.x, B.y - O.y);
        tetaStart = Math.acos(OA.x / Math.sqrt(OA.x * OA.x + OA.y * OA.y));
        if (OA.y < 0) tetaStart *= -1;
        tetaEnd = Math.acos(OB.x / Math.sqrt(OB.x * OB.x + OB.y * OB.y));
        if (OB.y < 0) tetaEnd *= -1;
        if (sweepFlag && tetaStart > tetaEnd) {
            tetaEnd += 2 * Math.PI;
        }
        if (!sweepFlag && tetaStart < tetaEnd) {
            tetaEnd -= 2 * Math.PI;
        }
        nbSectors = Math.ceil(Math.abs(tetaStart - tetaEnd) * 2 / Math.PI);
        arcSegPoints = [];
        angle = tetaStart;
        deltaTeta = (tetaEnd - tetaStart) / nbSectors;
        f = 4 * Math.tan(deltaTeta / 4) / 3;
        for (i = 0; i <= nbSectors; i++) {
            cosAngle = Math.cos(angle);
            sinAngle = Math.sin(angle);
            pt = new Point(O.x + cosAngle, O.y + sinAngle);
            arcSegPoints[i] = [
                new Point(pt.x + f * sinAngle, pt.y - f * cosAngle),
                pt,
                new Point(pt.x - f * sinAngle, pt.y + f * cosAngle)
            ];
            angle += deltaTeta;
        }
        arcSegPoints[0][0] = arcSegPoints[0][1].clone();
        arcSegPoints[arcSegPoints.length - 1][2] = arcSegPoints[arcSegPoints.length - 1][1].clone();
        mat = /** @type {any} */
            new Matrix().rotate(xAxisRotation).scale(rx, ry).rotate(-xAxisRotation);
        for (i = 0, il = arcSegPoints.length; i < il; i++) {
            arcSegPoints[i][0] = arcSegPoints[i][0].transform(mat);
            arcSegPoints[i][1] = arcSegPoints[i][1].transform(mat);
            arcSegPoints[i][2] = arcSegPoints[i][2].transform(mat);
        }
        for (i = 1, il = arcSegPoints.length; i < il; i++) {
            pt = arcSegPoints[i - 1][2];
            x1 = pt.x;
            y1 = pt.y;
            pt = arcSegPoints[i][0];
            x2 = pt.x;
            y2 = pt.y;
            pt = arcSegPoints[i][1];
            x = pt.x;
            y = pt.y;
            retVal.push(["C", x1, y1, x2, y2, x, y]);
        }
        return retVal;
    }

    function handleBlock(startArr, startOffsetM, startOffsetNextM, destArr, destOffsetM, destOffsetNextM) {
        var startArrTemp = startArr.slice(startOffsetM, startOffsetNextM || void 0);
        var destArrTemp = destArr.slice(destOffsetM, destOffsetNextM || void 0);
        var i = 0,
            posStart = {
                pos: [0, 0],
                start: [0, 0]
            },
            posDest = {
                pos: [0, 0],
                start: [0, 0]
            };
        while (true) {
            startArrTemp[i] = simplify.call(posStart, startArrTemp[i]);
            destArrTemp[i] = simplify.call(posDest, destArrTemp[i]);
            if (startArrTemp[i][0] != destArrTemp[i][0] || startArrTemp[i][0] == "M" || startArrTemp[i][0] == "A" && (startArrTemp[i][4] != destArrTemp[i][4] || startArrTemp[i][5] != destArrTemp[i][5])) {
                Array.prototype.splice.apply(
                    startArrTemp,
                    /** @type {[number, number, ...any[]]} */
                    [i, 1].concat(
                        /** @type {any} */
                        toBezier.call(posStart, startArrTemp[i])
                    )
                );
                Array.prototype.splice.apply(
                    destArrTemp,
                    /** @type {[number, number, ...any[]]} */
                    [i, 1].concat(
                        /** @type {any} */
                        toBezier.call(posDest, destArrTemp[i])
                    )
                );
            } else {
                startArrTemp[i] = /** @type {any} */
                    setPosAndReflection.call(
                        posStart,
                        startArrTemp[i]
                    );
                destArrTemp[i] = /** @type {any} */
                    setPosAndReflection.call(
                        posDest,
                        destArrTemp[i]
                    );
            }
            if (++i == startArrTemp.length && i == destArrTemp.length) break;
            if (i == startArrTemp.length) {
                startArrTemp.push([
                    "C",
                    posStart.pos[0],
                    posStart.pos[1],
                    posStart.pos[0],
                    posStart.pos[1],
                    posStart.pos[0],
                    posStart.pos[1]
                ]);
            }
            if (i == destArrTemp.length) {
                destArrTemp.push([
                    "C",
                    posDest.pos[0],
                    posDest.pos[1],
                    posDest.pos[0],
                    posDest.pos[1],
                    posDest.pos[0],
                    posDest.pos[1]
                ]);
            }
        }
        return {
            start: startArrTemp,
            dest: destArrTemp
        };
    }

    function synchronizePaths(fromD, toD) {
        var startArr = parsePath(fromD);
        var destArr = parsePath(toD);
        var startOffsetM = 0;
        var destOffsetM = 0;
        var startOffsetNextM = false;
        var destOffsetNextM = false;
        var result;
        while (true) {
            if (startOffsetM === false && destOffsetM === false) break;
            startOffsetNextM = findNextM(
                startArr,
                startOffsetM === false ? false : startOffsetM + 1
            );
            destOffsetNextM = findNextM(
                destArr,
                destOffsetM === false ? false : destOffsetM + 1
            );
            if (startOffsetM === false) {
                const bbox = pathBbox(
                    /** @type {any} */
                    result.start
                );
                if (bbox.height == 0 || bbox.width == 0) {
                    startOffsetM = startArr.push(startArr[0]) - 1;
                } else {
                    startOffsetM = startArr.push([
                        "M",
                        bbox.x + bbox.width / 2,
                        bbox.y + bbox.height / 2
                    ]) - 1;
                }
            }
            if (destOffsetM === false) {
                const bbox = pathBbox(
                    /** @type {any} */
                    result.dest
                );
                if (bbox.height == 0 || bbox.width == 0) {
                    destOffsetM = destArr.push(destArr[0]) - 1;
                } else {
                    destOffsetM = destArr.push([
                        "M",
                        bbox.x + bbox.width / 2,
                        bbox.y + bbox.height / 2
                    ]) - 1;
                }
            }
            result = handleBlock(
                startArr,
                startOffsetM,
                startOffsetNextM,
                destArr,
                destOffsetM,
                destOffsetNextM
            );
            startArr = startArr.slice(0, startOffsetM).concat(
                result.start,
                startOffsetNextM === false ? [] : startArr.slice(startOffsetNextM)
            );
            destArr = destArr.slice(0, destOffsetM).concat(
                result.dest,
                destOffsetNextM === false ? [] : destArr.slice(destOffsetNextM)
            );
            startOffsetM = startOffsetNextM === false ? false : startOffsetM + result.start.length;
            destOffsetM = destOffsetNextM === false ? false : destOffsetM + result.dest.length;
        }
        return {
            start: startArr,
            dest: destArr
        };
    }

    function morphPaths(fromD, toD) {
        var synced = synchronizePaths(fromD, toD);
        var startArr = synced.start;
        var destArr = synced.dest;
        return function(pos) {
            var result = startArr.map(function(from, idx) {
                return destArr[idx].map(function(to, toIdx) {
                    if (toIdx === 0) return to;
                    return from[toIdx] + (destArr[idx][toIdx] - from[toIdx]) * pos;
                });
            });
            return arrayToPath(result);
        };
    }
    let _measureSvg = null;
    let _measurePath = null;

    function samplePathPoints(d, n) {
        const pts = new Array(n);
        if (!Environment.isBrowser()) {
            const arr = parsePath(d);
            const bbox = pathBbox(arr);
            const cx = bbox.x + bbox.width / 2;
            const cy = bbox.y + bbox.height / 2;
            for (let i = 0; i < n; i++) pts[i] = {
                x: cx,
                y: cy
            };
            return pts;
        }
        if (!_measureSvg) {
            _measureSvg = /** @type {SVGSVGElement} */
                document.createElementNS("http://www.w3.org/2000/svg", "svg");
            _measureSvg.setAttribute("width", "0");
            _measureSvg.setAttribute("height", "0");
            _measureSvg.setAttribute(
                "style",
                "position:absolute;width:0;height:0;visibility:hidden;pointer-events:none;"
            );
            _measurePath = /** @type {SVGPathElement} */
                document.createElementNS("http://www.w3.org/2000/svg", "path");
            _measureSvg.appendChild(_measurePath);
            document.body.appendChild(_measureSvg);
        }
        _measurePath.setAttribute("d", d || "M0 0");
        let len = 0;
        try {
            len = _measurePath.getTotalLength();
        } catch (e) {
            len = 0;
        }
        if (!len || !isFinite(len)) {
            const arr = parsePath(d);
            const bbox = pathBbox(arr);
            const cx = bbox.x + bbox.width / 2;
            const cy = bbox.y + bbox.height / 2;
            for (let i = 0; i < n; i++) pts[i] = {
                x: cx,
                y: cy
            };
            return pts;
        }
        for (let i = 0; i < n; i++) {
            try {
                const p = _measurePath.getPointAtLength(i / n * len);
                pts[i] = {
                    x: p.x,
                    y: p.y
                };
            } catch (e) {
                pts[i] = {
                    x: 0,
                    y: 0
                };
            }
        }
        return pts;
    }

    function morphPolygons(fromD, toD, n = 96) {
        const fromPts = samplePathPoints(fromD, n);
        const toPts = samplePathPoints(toD, n);
        let bestOffset = 0;
        let bestDist = Infinity;
        for (let off = 0; off < n; off++) {
            let dist = 0;
            for (let i = 0; i < n; i++) {
                const a = fromPts[(i + off) % n];
                const b = toPts[i];
                const dx = a.x - b.x;
                const dy = a.y - b.y;
                dist += dx * dx + dy * dy;
                if (dist >= bestDist) break;
            }
            if (dist < bestDist) {
                bestDist = dist;
                bestOffset = off;
            }
        }
        const aligned = new Array(n);
        for (let i = 0; i < n; i++) {
            aligned[i] = fromPts[(i + bestOffset) % n];
        }
        return function(pos) {
            let out = "";
            for (let i = 0; i < n; i++) {
                const a = aligned[i];
                const b = toPts[i];
                const x = a.x + (b.x - a.x) * pos;
                const y = a.y + (b.y - a.y) * pos;
                out += (i === 0 ? "M" : "L") + x.toFixed(3) + " " + y.toFixed(3) + " ";
            }
            return out + "Z";
        };
    }

    function easeInOut(t) {
        return -Math.cos(t * Math.PI) / 2 + 0.5;
    }

    function parseColor(str) {
        if (!str || typeof str !== "string") return null;
        if (str[0] === "#") {
            let hex = str.slice(1);
            if (hex.length === 3)
                hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
            const n = parseInt(hex, 16);
            return [n >> 16 & 255, n >> 8 & 255, n & 255, 1];
        }
        const m = str.match(
            /rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+))?\s*\)/
        );
        if (m) return [+m[1], +m[2], +m[3], m[4] !== void 0 ? +m[4] : 1];
        return null;
    }

    function interpolateColor(from, to, pos) {
        return `rgba(${Math.round(from[0] + (to[0] - from[0]) * pos)},${Math.round(from[1] + (to[1] - from[1]) * pos)},${Math.round(from[2] + (to[2] - from[2]) * pos)},${from[3] + (to[3] - from[3]) * pos})`;
    }
    class SVGAnimationRunner {
        /**
         * @param {any} element
         * @param {number} duration
         * @param {number} delay
         */
        constructor(element, duration, delay) {
            this.el = element;
            this.duration = duration != null ? duration : 300;
            this.delay = delay || 0;
            this._attrTarget = null;
            this._plotTarget = null;
            this._plotAlgorithm = "commands";
            this._afterCb = null;
            this._duringCb = null;
            this._next = null;
            this._root = null;
            this._scheduled = false;
        }
        /**
         * @param {Record<string, any>} to
         */
        attr(to) {
            this._attrTarget = to;
            this._schedule();
            return this;
        }
        /**
         * @param {string} d
         * @param {'commands' | 'polygons'} [algorithm] - morph engine to use for
         *   the d→d interpolation. 'commands' (default) is the legacy
         *   per-command lerp; 'polygons' resamples both paths into N evenly
         *   spaced points and tweens point-by-point (smoother for shapes with
         *   very different anchor-point counts).
         */
        plot(d, algorithm) {
            this._plotTarget = d;
            if (algorithm) this._plotAlgorithm = algorithm;
            this._schedule();
            return this;
        }
        /**
         * @param {Function} fn
         */
        after(fn) {
            this._afterCb = fn;
            this._schedule();
            return this;
        }
        /**
         * @param {Function} fn
         */
        during(fn) {
            this._duringCb = fn;
            this._schedule();
            return this;
        }
        /**
         * @param {number} duration
         * @param {number} delay
         */
        animate(duration, delay) {
            const next = new SVGAnimationRunner(this.el, duration, delay);
            this._next = next;
            next._root = this._root || this;
            return next;
        }
        _schedule() {
            const root = this._root || this;
            if (!root._scheduled) {
                root._scheduled = true;
                queueMicrotask(() => root._executeChain());
            }
        }
        _executeChain() {
            const chain = [];
            let r = this;
            while (r) {
                chain.push(r);
                r = r._next;
            }
            let cumulativeDelay = 0;
            chain.forEach((runner) => {
                cumulativeDelay += runner.delay;
                runner._execute(cumulativeDelay);
                cumulativeDelay += runner.duration;
            });
        }
        /**
         * @param {number} startDelay
         */
        _execute(startDelay) {
            const el = this.el;
            const duration = this.duration;
            if (duration <= 1) {
                const apply = () => {
                    if (this._attrTarget) el.attr(this._attrTarget);
                    if (this._plotTarget) el.plot(this._plotTarget);
                    if (this._afterCb) this._afterCb.call(el);
                };
                if (startDelay > 0) {
                    setTimeout(apply, startDelay);
                } else {
                    apply();
                }
                return;
            }
            const run = () => {
                const fromAttrs = (
                    /** @type {Record<string, any>} */
                    {}
                );
                const fromColors = (
                    /** @type {Record<string, any>} */
                    {}
                );
                const toColors = (
                    /** @type {Record<string, any>} */
                    {}
                );
                if (this._attrTarget) {
                    for (const key of Object.keys(this._attrTarget)) {
                        const fromVal = el.attr(key);
                        fromAttrs[key] = fromVal;
                        const fc = parseColor(fromVal);
                        const tc = parseColor(String(this._attrTarget[key]));
                        if (fc && tc) {
                            fromColors[key] = fc;
                            toColors[key] = tc;
                        }
                    }
                }
                let morphFn = null;
                if (this._plotTarget) {
                    const fromPath = el.attr("d") || "";
                    try {
                        morphFn = this._plotAlgorithm === "polygons" ? morphPolygons(fromPath, this._plotTarget) : morphPaths(fromPath, this._plotTarget);
                    } catch (e) {
                        morphFn = null;
                    }
                }
                const start = performance.now();
                const tick = (now) => {
                    const elapsed = now - start;
                    const rawPos = Math.min(elapsed / duration, 1);
                    const pos = easeInOut(rawPos);
                    if (this._attrTarget) {
                        if (rawPos >= 1) {
                            el.attr(this._attrTarget);
                        } else {
                            const current = (
                                /** @type {Record<string, any>} */
                                {}
                            );
                            for (const key of Object.keys(this._attrTarget)) {
                                if (fromColors[key] && toColors[key]) {
                                    current[key] = interpolateColor(
                                        fromColors[key],
                                        toColors[key],
                                        pos
                                    );
                                } else {
                                    const from = parseFloat(fromAttrs[key]);
                                    const to = parseFloat(this._attrTarget[key]);
                                    if (!isNaN(from) && !isNaN(to)) {
                                        current[key] = from + (to - from) * pos;
                                    }
                                }
                            }
                            el.attr(current);
                        }
                    }
                    if (morphFn && rawPos < 1) {
                        el.attr(
                            "d",
                            /** @type {any} */
                            morphFn(pos)
                        );
                    }
                    if (this._duringCb) this._duringCb(pos);
                    if (rawPos < 1) {
                        BrowserAPIs.requestAnimationFrame(tick);
                    } else {
                        if (this._plotTarget) {
                            el.attr("d", this._plotTarget);
                        }
                        if (this._afterCb) this._afterCb.call(el);
                    }
                };
                BrowserAPIs.requestAnimationFrame(tick);
            };
            if (startDelay > 0) {
                setTimeout(run, startDelay);
            } else {
                run();
            }
        }
    }

    function installAnimationMethods(ElementClass) {
        ElementClass.prototype.animate = function(duration, delay) {
            return new SVGAnimationRunner(this, duration, delay);
        };
    }

    function installDraggable(ElementClass) {
        ElementClass.prototype.draggable = function(opts) {
            if (opts === false) {
                if (this._dragCleanup) {
                    this._dragCleanup();
                    this._dragCleanup = null;
                }
                return this;
            }
            const el = this;
            const constraints = opts || {};
            const onPointerDown = (e) => {
                if (e.button && e.button !== 0) return;
                e.stopPropagation();
                const isTouch = e.type === "touchstart";
                const ev = isTouch ? e.touches[0] : e;
                const svgEl = el.node;
                const startAttrX = parseFloat(svgEl.getAttribute("x")) || 0;
                const startAttrY = parseFloat(svgEl.getAttribute("y")) || 0;
                const startClientX = ev.clientX;
                const startClientY = ev.clientY;
                const svgRoot = svgEl.ownerSVGElement;
                let ctm = null;
                if (svgRoot) {
                    ctm = svgRoot.getScreenCTM();
                }
                const onMove = (me) => {
                    const mev = me.type === "touchmove" ? me.touches[0] : me;
                    let dx = mev.clientX - startClientX;
                    let dy = mev.clientY - startClientY;
                    if (ctm) {
                        dx = dx / ctm.a;
                        dy = dy / ctm.d;
                    }
                    let newX = startAttrX + dx;
                    let newY = startAttrY + dy;
                    const w = parseFloat(svgEl.getAttribute("width")) || 0;
                    const h = parseFloat(svgEl.getAttribute("height")) || 0;
                    if (constraints.minX !== void 0 && newX < constraints.minX)
                        newX = constraints.minX;
                    if (constraints.minY !== void 0 && newY < constraints.minY)
                        newY = constraints.minY;
                    if (constraints.maxX !== void 0 && newX + w > constraints.maxX)
                        newX = constraints.maxX - w;
                    if (constraints.maxY !== void 0 && newY + h > constraints.maxY)
                        newY = constraints.maxY - h;
                    const box = {
                        x: newX,
                        y: newY,
                        w,
                        h,
                        x2: newX + w,
                        y2: newY + h
                    };
                    const event = new CustomEvent("dragmove", {
                        detail: {
                            handler: {
                                /**
                                 * @param {number} x
                                 * @param {number} y
                                 */
                                move: function(x, y) {
                                    svgEl.setAttribute("x", x);
                                    svgEl.setAttribute("y", y);
                                }
                            },
                            box
                        }
                    });
                    svgEl.dispatchEvent(event);
                };
                const onUp = () => {
                    if (Environment.isBrowser()) {
                        document.removeEventListener("mousemove", onMove);
                        document.removeEventListener("touchmove", onMove);
                        document.removeEventListener("mouseup", onUp);
                        document.removeEventListener("touchend", onUp);
                    }
                };
                if (Environment.isBrowser()) {
                    document.addEventListener("mousemove", onMove);
                    document.addEventListener("touchmove", onMove);
                    document.addEventListener("mouseup", onUp);
                    document.addEventListener("touchend", onUp);
                }
            };
            el.node.addEventListener("mousedown", onPointerDown);
            el.node.addEventListener("touchstart", onPointerDown);
            el._dragCleanup = () => {
                el.node.removeEventListener("mousedown", onPointerDown);
                el.node.removeEventListener("touchstart", onPointerDown);
            };
            return el;
        };
    }

    function installSelectable(ElementClass) {
        ElementClass.prototype.select = function(opts) {
            if (opts === false) {
                if (this._selectCleanup) {
                    this._selectCleanup();
                    this._selectCleanup = null;
                }
                return this;
            }
            const el = this;
            const {
                createHandle,
                updateHandle
            } = opts;
            const handleGroup = document.createElementNS(SVGNS, "g");
            handleGroup.setAttribute("class", "svg_select_points");
            const parent = el.node.parentNode;
            if (parent) {
                parent.appendChild(handleGroup);
            }
            const handles = {};
            const handleNames = ["t", "b", "l", "r", "lt", "rt", "lb", "rb"];
            handleNames.forEach((name2, index) => {
                const subGroup = new SVGContainer(document.createElementNS(SVGNS, "g"));
                handleGroup.appendChild(subGroup.node);
                const handle = createHandle(subGroup, [0, 0], index, [], name2);
                handles[name2] = {
                    group: subGroup,
                    handle
                };
            });
            const updatePositions = () => {
                const x = parseFloat(el.attr("x")) || 0;
                const y = parseFloat(el.attr("y")) || 0;
                const w = parseFloat(el.attr("width")) || 0;
                const h = parseFloat(el.attr("height")) || 0;
                const elTransform = el.node.getAttribute("transform");
                if (elTransform) {
                    handleGroup.setAttribute("transform", elTransform);
                } else {
                    handleGroup.removeAttribute("transform");
                }
                const positions = {
                    t: [x + w / 2, y],
                    b: [x + w / 2, y + h],
                    l: [x, y + h / 2],
                    r: [x + w, y + h / 2],
                    lt: [x, y],
                    rt: [x + w, y],
                    lb: [x, y + h],
                    rb: [x + w, y + h]
                };
                handleNames.forEach((name2) => {
                    if (handles[name2] && positions[name2]) {
                        updateHandle(handles[name2].group, positions[name2]);
                    }
                });
            };
            updatePositions();
            el._selectHandles = handleGroup;
            el._selectHandlesMap = handles;
            el._updateSelectPositions = updatePositions;
            el._selectCleanup = () => {
                if (handleGroup.parentNode) {
                    handleGroup.parentNode.removeChild(handleGroup);
                }
                el._selectHandles = null;
                el._selectHandlesMap = null;
                el._updateSelectPositions = null;
            };
            return el;
        };
        ElementClass.prototype.resize = function(enable) {
            if (enable === false) {
                if (this._resizeCleanup) {
                    this._resizeCleanup();
                    this._resizeCleanup = null;
                }
                return this;
            }
            const el = this;
            const handles = el._selectHandlesMap;
            if (!handles) return el;
            const cleanupFns = [];
            const makeHandleDraggable = (name2) => {
                const handleInfo = handles[name2];
                if (!handleInfo || !handleInfo.group || !handleInfo.group.node) return;
                const handleNode = handleInfo.group.node;
                const onPointerDown = (e) => {
                    if (e.button && e.button !== 0) return;
                    e.stopPropagation();
                    const isTouch = e.type === "touchstart";
                    const ev = isTouch ? e.touches[0] : e;
                    const startClientX = ev.clientX;
                    const svgRoot = el.node.ownerSVGElement;
                    let ctm = null;
                    if (svgRoot) {
                        ctm = svgRoot.getScreenCTM();
                    }
                    const startX = parseFloat(el.attr("x")) || 0;
                    const startW = parseFloat(el.attr("width")) || 0;
                    const onMove = (me) => {
                        const mev = me.type === "touchmove" ? me.touches[0] : me;
                        let dx = mev.clientX - startClientX;
                        if (ctm) dx = dx / /** @type {any} */
                            ctm.a;
                        let newX = startX;
                        let newW = startW;
                        if (name2 === "l") {
                            newX = startX + dx;
                            newW = startW - dx;
                        } else if (name2 === "r") {
                            newW = startW + dx;
                        }
                        if (newW < 0) {
                            newW = 0;
                        }
                        el.attr({
                            x: newX,
                            width: newW
                        });
                        if (el._updateSelectPositions) {
                            el._updateSelectPositions();
                        }
                        const event = new CustomEvent("resize", {
                            detail: {
                                el
                            }
                        });
                        el.node.dispatchEvent(event);
                    };
                    const onUp = () => {
                        if (Environment.isBrowser()) {
                            document.removeEventListener("mousemove", onMove);
                            document.removeEventListener("touchmove", onMove);
                            document.removeEventListener("mouseup", onUp);
                            document.removeEventListener("touchend", onUp);
                        }
                        const event = new CustomEvent("resize", {
                            detail: {
                                el
                            }
                        });
                        el.node.dispatchEvent(event);
                    };
                    if (Environment.isBrowser()) {
                        document.addEventListener("mousemove", onMove);
                        document.addEventListener("touchmove", onMove);
                        document.addEventListener("mouseup", onUp);
                        document.addEventListener("touchend", onUp);
                    }
                };
                handleNode.addEventListener("mousedown", onPointerDown);
                handleNode.addEventListener("touchstart", onPointerDown);
                cleanupFns.push(() => {
                    handleNode.removeEventListener("mousedown", onPointerDown);
                    handleNode.removeEventListener("touchstart", onPointerDown);
                });
            };
            makeHandleDraggable("l");
            makeHandleDraggable("r");
            el._resizeCleanup = () => {
                cleanupFns.forEach((fn) => fn());
            };
            return el;
        };
    }
    installFilterMethods(SVGElement);
    installAnimationMethods(SVGElement);
    installDraggable(SVGElement);
    installSelectable(SVGElement);

    function SVG() {
        const svgEl = BrowserAPIs.createElementNS(SVGNS, "svg");
        const svg = new SVGContainer(svgEl);
        svg.attr({
            xmlns: SVGNS
        });
        return svg;
    }
    SVG.xlink = "http://www.w3.org/1999/xlink";
    if (Environment.isBrowser() && typeof window.SVG === "undefined") {
        window.SVG = SVG;
    }
    if (Environment.isBrowser()) {
        if (typeof window.SVG === "undefined") {
            window.SVG = SVG;
        }
        if (typeof window.Apex === "undefined") {
            window.Apex = {};
        }
    } else {
        if (typeof global !== "undefined") {
            if (typeof /** @type {any} */ global.Apex === "undefined") {
                global.Apex = {};
            }
            if (typeof /** @type {any} */ global.SVG === "undefined") {
                global.SVG = SVG;
            }
        }
    }
    const _InitCtxVariables = class _InitCtxVariables {
        /**
         * Register one or more optional feature modules.
         *
         * @param {Record<string, new (w: object, ctx: object) => unknown>} featureMap
         *   Plain object mapping ctx property name → constructor.
         *
         * Example (called from src/features/legend.js):
         *   InitCtxVariables.registerFeatures({ legend: Legend })
         */
        static registerFeatures(featureMap) {
            for (const [key, Ctor] of Object.entries(featureMap)) {
                _InitCtxVariables._featureRegistry.set(key, Ctor);
            }
        }
        /**
         * @param {import('../../types/internal').ChartContext} ctx
         */
        constructor(ctx) {
            this.ctx = ctx;
            this.w = ctx.w;
        }
        initModules() {
            this.ctx.publicMethods = [
                "updateOptions",
                "updateSeries",
                "appendData",
                "appendSeries",
                "isSeriesHidden",
                "highlightSeries",
                "toggleSeries",
                "showSeries",
                "hideSeries",
                "setLocale",
                "resetSeries",
                "zoomX",
                "toggleDataPointSelection",
                "dataURI",
                "exportToCSV",
                "addXaxisAnnotation",
                "addYaxisAnnotation",
                "addPointAnnotation",
                "clearAnnotations",
                "removeAnnotation",
                "paper",
                "destroy"
            ];
            this.ctx.eventList = [
                "click",
                "mousedown",
                "mousemove",
                "mouseleave",
                "touchstart",
                "touchmove",
                "touchleave",
                "mouseup",
                "touchend",
                "keydown",
                "keyup"
            ];
            this.ctx.animations = new Animations(this.w, this.ctx);
            this.ctx.axes = new Axes(this.w, this.ctx);
            this.ctx.core = new Core(this.ctx.el, this.w, this.ctx);
            this.ctx.config = new Config({});
            this.ctx.data = new Data(this.w, {
                resetGlobals: () => this.ctx.core.resetGlobals(),
                isMultipleY: () => this.ctx.core.isMultipleY()
            });
            this.ctx.grid = new Grid(this.w, this.ctx);
            this.ctx.graphics = new Graphics(this.w, this.ctx);
            this.ctx.coreUtils = new CoreUtils(this.w);
            this.ctx.crosshairs = new Crosshairs(this.w);
            this.ctx.events = new Events(this.w, this.ctx);
            this.ctx.fill = new Fill(this.w);
            this.ctx.localization = new Localization(this.w);
            this.ctx.options = new Options();
            this.ctx.responsive = new Responsive(this.w);
            this.ctx.series = new Series(this.w, {
                // legend may not be registered — guard with ?.
                toggleDataSeries: (...a) => {
                    var _a;
                    return (_a = this.ctx.legend) == null ? void 0 : _a.legendHelpers.toggleDataSeries(...a);
                },
                revertDefaultAxisMinMax: () => this.ctx.updateHelpers.revertDefaultAxisMinMax(),
                updateSeries: (...a) => this.ctx.updateHelpers._updateSeries(...a)
            });
            this.ctx.theme = new Theme(this.w);
            this.ctx.formatters = new Formatters(this.w);
            this.ctx.titleSubtitle = new TitleSubtitle(this.w);
            this.ctx.dimensions = new Dimensions(this.w, this.ctx);
            this.ctx.updateHelpers = new UpdateHelpers(this.w, this.ctx);
            const tooltipInstance = new Tooltip(this.w, this.ctx);
            this.w.globals.tooltip = tooltipInstance;
            Object.defineProperty(this.ctx, "tooltip", {
                get() {
                    return this.w.globals.tooltip;
                },
                configurable: true
            });
            this._initOptionalModules();
        }
        /**
         * Instantiate optional feature modules from the registry.
         *
         * Modules that are not registered are set to null on ctx so that call sites
         * can safely use optional-chaining (ctx.tooltip?.drawTooltip(...)).
         *
         * Lazy-getter features (toolbar, zoomPanSelection, keyboardNavigation) are
         * installed as on-demand getters so they are only constructed if accessed,
         * and only if their constructor was registered.
         */
        _initOptionalModules() {
            const reg = _InitCtxVariables._featureRegistry;
            const w = this.w;
            const ctx = this.ctx;
            const ExportsCtor = reg.get("exports");
            ctx.exports = ExportsCtor ? new ExportsCtor(w, ctx) : null;
            const LegendCtor = reg.get("legend");
            ctx.legend = LegendCtor ? new LegendCtor(w, ctx) : null;
            const MorphCtor = reg.get("morphTypeChange");
            ctx.morphTypeChange = MorphCtor ? new MorphCtor(w, ctx) : null;
            const ToolbarCtor = reg.get("toolbar");
            Object.defineProperty(ctx, "toolbar", {
                get() {
                    var _a;
                    if (!this._toolbar && ToolbarCtor)
                        this._toolbar = new ToolbarCtor(w, this);
                    return (_a = this._toolbar) != null ? _a : null;
                },
                configurable: true
            });
            const ZoomPanCtor = reg.get("zoomPanSelection");
            Object.defineProperty(ctx, "zoomPanSelection", {
                get() {
                    var _a;
                    if (!this._zoomPanSelection && ZoomPanCtor)
                        this._zoomPanSelection = new ZoomPanCtor(w, this);
                    return (_a = this._zoomPanSelection) != null ? _a : null;
                },
                configurable: true
            });
            const KeyboardCtor = reg.get("keyboardNavigation");
            Object.defineProperty(ctx, "keyboardNavigation", {
                get() {
                    var _a;
                    if (!this._keyboardNavigation && KeyboardCtor)
                        this._keyboardNavigation = new KeyboardCtor(w, this);
                    return (_a = this._keyboardNavigation) != null ? _a : null;
                },
                configurable: true
            });
        }
    };
    /**
     * Registry of optional feature modules.
     *
     * Populated by ApexCharts.registerFeatures() (called from feature entry
     * files such as src/features/legend.js). Keys match the ctx property name
     * the module is stored under (e.g. 'legend', 'exports').
     *
     * Core modules that every chart needs are NOT in this registry — they are
     * always instantiated unconditionally in initModules().
     */
    __publicField(_InitCtxVariables, "_featureRegistry", /* @__PURE__ */ new Map());
    let InitCtxVariables = _InitCtxVariables;
    class Destroy {
        /**
         * @param {import('../../types/internal').ChartContext} ctx
         */
        constructor(ctx) {
            this.ctx = ctx;
            this.w = ctx.w;
        }
        /**
         * @param {{ isUpdating: boolean }} opts
         */
        clear({
            isUpdating
        }) {
            if (this.ctx._zoomPanSelection) {
                this.ctx._zoomPanSelection.destroy();
            }
            if (this.ctx._toolbar) {
                this.ctx._toolbar.destroy();
            }
            if (this.w.globals.resizeObserver && typeof this.w.globals.resizeObserver.disconnect === "function") {
                this.w.globals.resizeObserver.disconnect();
                this.w.globals.resizeObserver = null;
            }
            PerformanceCache.invalidateAll(this.w);
            if (isUpdating) {
                this.ctx._zoomPanSelection = null;
                this.ctx._toolbar = null;
                this.ctx._keyboardNavigation = null;
            } else {
                this.ctx.animations = null;
                this.ctx.axes = null;
                this.ctx.annotations = null;
                this.ctx.core = null;
                this.ctx.data = null;
                this.ctx.grid = null;
                this.ctx.series = null;
                this.ctx.responsive = null;
                this.ctx.theme = null;
                this.ctx.formatters = null;
                this.ctx.titleSubtitle = null;
                this.ctx.legend = null;
                this.ctx.dimensions = null;
                this.ctx.options = null;
                this.ctx.crosshairs = null;
                this.ctx._zoomPanSelection = null;
                this.ctx.updateHelpers = null;
                this.ctx._toolbar = null;
                this.ctx.localization = null;
                this.ctx._keyboardNavigation = null;
                this.ctx.w.globals.tooltip = null;
            }
            this.clearDomElements({
                isUpdating
            });
        }
        /**
         * @param {any} draw
         */
        killSVG(draw) {
            draw.each(
                /** @this {any} */
                function() {
                    this.removeClass("*");
                    this.off();
                },
                true
            );
            draw.clear();
        }
        /**
         * @param {{ isUpdating: boolean }} opts
         */
        clearDomElements({
            isUpdating
        }) {
            const domEls = (
                /** @type {any} */
                this.w.dom
            );
            if (Environment.isBrowser()) {
                const elSVG = domEls.Paper.node;
                if (elSVG.parentNode && elSVG.parentNode.parentNode && !isUpdating) {
                    elSVG.parentNode.parentNode.style.minHeight = "unset";
                }
                const baseEl = domEls.baseEl;
                if (baseEl) {
                    this.ctx.eventList.forEach((event) => {
                        baseEl.removeEventListener(event, this.ctx.events.documentEvent);
                    });
                }
                if (this.ctx.el !== null) {
                    while (this.ctx.el.firstChild) {
                        this.ctx.el.removeChild(this.ctx.el.firstChild);
                    }
                }
                this.killSVG(domEls.Paper);
                domEls.Paper.remove();
            }
            domEls.elWrap = null;
            domEls.elGraphical = null;
            domEls.elLegendWrap = null;
            domEls.elLegendForeign = null;
            domEls.baseEl = null;
            domEls.elGridRect = null;
            domEls.elGridRectMask = null;
            domEls.elGridRectBarMask = null;
            domEls.elGridRectMarkerMask = null;
            domEls.elForecastMask = null;
            domEls.elNonForecastMask = null;
            domEls.elDefs = null;
        }
    }
    const ros = /* @__PURE__ */ new WeakMap();

    function addResizeListener(el, fn) {
        if (Environment.isSSR()) return;
        let called = false;
        if (el.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
            const elRect = el.getBoundingClientRect();
            if (el.style.display === "none" || elRect.width === 0) {
                called = true;
            }
        }
        const ro = new ResizeObserver((r) => {
            if (called) {
                fn.call(el, r);
            }
            called = true;
        });
        if (el.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
            Array.from(el.children).forEach((c) => ro.observe(c));
        } else {
            ro.observe(el);
        }
        ros.set(fn, ro);
    }

    function removeResizeListener(el, fn) {
        if (Environment.isSSR()) return;
        const ro = ros.get(fn);
        if (ro) {
            ro.disconnect();
            ros.delete(fn);
        }
    }
    const apexCSS = '@keyframes opaque {\n  0% {\n    opacity: 0\n  }\n\n  to {\n    opacity: 1\n  }\n}\n\n@keyframes resizeanim {\n\n  0%,\n  to {\n    opacity: 0\n  }\n}\n\n.apexcharts-canvas {\n  position: relative;\n  direction: ltr !important;\n  user-select: none;\n  /* Focus indicator colour. Themes override below. */\n  --apexcharts-focus-color: #008FFB;\n}\n\n/* Dark theme & high-contrast: brighter focus colour for sufficient contrast. */\n.apexcharts-canvas .apexcharts-theme-dark,\n.apexcharts-theme-dark.apexcharts-canvas {\n  --apexcharts-focus-color: #FFD500;\n}\n.apexcharts-canvas.apexcharts-high-contrast,\n.apexcharts-high-contrast.apexcharts-canvas {\n  --apexcharts-focus-color: #FFFF00;\n}\n\n/* Visually-hidden aria-live status region (WCAG 4.1.3 Status Messages). */\n.apexcharts-sr-status {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  white-space: nowrap;\n  border: 0;\n}\n\n/* Respect OS-level reduced-motion preference (WCAG 2.3.3). */\n@media (prefers-reduced-motion: reduce) {\n  .apexcharts-canvas *,\n  .apexcharts-canvas *::before,\n  .apexcharts-canvas *::after {\n    animation-duration: 0.01ms !important;\n    animation-iteration-count: 1 !important;\n    transition-duration: 0.01ms !important;\n  }\n}\n\n.apexcharts-canvas ::-webkit-scrollbar {\n  -webkit-appearance: none;\n  width: 6px\n}\n\n.apexcharts-canvas ::-webkit-scrollbar-thumb {\n  border-radius: 4px;\n  background-color: rgba(0, 0, 0, .5);\n  box-shadow: 0 0 1px rgba(255, 255, 255, .5);\n  -webkit-box-shadow: 0 0 1px rgba(255, 255, 255, .5)\n}\n\n.apexcharts-inner {\n  position: relative\n}\n\n.apexcharts-text tspan {\n  font-family: inherit\n}\n\nrect.legend-mouseover-inactive,\n.legend-mouseover-inactive rect,\n.legend-mouseover-inactive path,\n.legend-mouseover-inactive circle,\n.legend-mouseover-inactive line,\n.legend-mouseover-inactive text.apexcharts-yaxis-title-text,\n.legend-mouseover-inactive text.apexcharts-yaxis-label {\n  transition: .15s ease all;\n  opacity: .2\n}\n\n.apexcharts-legend-text {\n  padding-left: 15px;\n  margin-left: -15px;\n}\n\n.apexcharts-legend-series[role="button"]:focus {\n  outline: 2px solid var(--apexcharts-focus-color, #008FFB);\n  outline-offset: 2px;\n}\n\n.apexcharts-legend-series[role="button"]:focus:not(:focus-visible) {\n  outline: none;\n}\n\n.apexcharts-legend-series[role="button"]:focus-visible {\n  outline: 2px solid var(--apexcharts-focus-color, #008FFB);\n  outline-offset: 2px;\n}\n\n.apexcharts-series-collapsed {\n  opacity: 0\n}\n\n.apexcharts-canvas svg:focus:not(:focus-visible) {\n  outline: none;\n}\n\n/* Keyboard navigation focus indicator on SVG data elements.\n   SVG elements don\'t support CSS outline, so we use stroke. */\n.apexcharts-bar-area.apexcharts-keyboard-focused,\n.apexcharts-candlestick-area.apexcharts-keyboard-focused,\n.apexcharts-boxPlot-area.apexcharts-keyboard-focused,\n.apexcharts-rangebar-area.apexcharts-keyboard-focused,\n.apexcharts-pie-area.apexcharts-keyboard-focused,\n.apexcharts-heatmap-rect.apexcharts-keyboard-focused,\n.apexcharts-treemap-rect.apexcharts-keyboard-focused {\n  stroke: var(--apexcharts-focus-color, #008FFB);\n  stroke-width: 2;\n  stroke-opacity: 1;\n}\n\n.apexcharts-tooltip {\n  --apx-tt-bg: #ffffff;\n  --apx-tt-border: rgba(15, 23, 42, 0.06);\n  /* Layered shadow: tight inner contact + soft outer drop. The two Y\n   * offsets are exposed as variables so they flip in sync with the\n   * arrow when the tooltip is below the data point — see the\n   * `[data-placement="bottom"]` rule further down. */\n  --apx-tt-shadow-y-mid: 8px;\n  --apx-tt-shadow-y-far: 16px;\n  --apx-tt-shadow: 0 0 0 1px rgba(15, 23, 42, 0.04), 0 var(--apx-tt-shadow-y-mid) 16px -6px rgba(15, 23, 42, 0.12), 0 var(--apx-tt-shadow-y-far) 36px -12px rgba(15, 23, 42, 0.18);\n  --apx-tt-arrow-bg: var(--apx-tt-bg);\n  /* Two stacked drop-shadows: the first is a tight contact halo for\n   * edge definition against light chart backgrounds; the second is a\n   * softer directional drop that lifts the arrow off the surface.\n   * `--apx-tt-arrow-drop-y` is the Y offset of the directional drop;\n   * a per-placement rule below flips it to negative when the tooltip\n   * is below the data point (arrow on top) so the shadow always\n   * casts outward instead of into the tooltip body. */\n  --apx-tt-arrow-drop-y: 2px;\n  --apx-tt-arrow-shadow: drop-shadow(0 0 0.5px rgba(15, 23, 42, 0.2)) drop-shadow(0 var(--apx-tt-arrow-drop-y) 4px rgba(15, 23, 42, 0.2));\n  --apx-tt-color: #0f172a;\n  --apx-tt-color-muted: rgba(15, 23, 42, 0.55);\n  border-radius: 8px;\n  background: var(--apx-tt-bg);\n  border: 1px solid var(--apx-tt-border);\n  box-shadow: var(--apx-tt-shadow);\n  color: var(--apx-tt-color);\n  cursor: default;\n  font-size: 13px;\n  left: 0;\n  top: 0;\n  opacity: 0;\n  pointer-events: none;\n  position: absolute;\n  display: flex;\n  flex-direction: column;\n  padding: 2px 0;\n  white-space: nowrap;\n  z-index: 12;\n  transition: opacity .12s ease\n}\n\n/* While the tooltip is visible, smoothly animate position changes\n * between data points. Kept short (160 ms) and ease-out so it stays\n * responsive — too long would feel laggy when sweeping across many\n * points fast. The position transition is only attached after the\n * first paint (Position.applyTooltipPosition flips `data-positioned`\n * once the tooltip has been placed) so the *first* show doesn\'t slide\n * the tooltip in from the previously-stale (0,0) coordinates. */\n.apexcharts-tooltip.apexcharts-active {\n  opacity: 1;\n  transition: opacity .12s ease\n}\n.apexcharts-tooltip.apexcharts-active[data-positioned="true"] {\n  transition: opacity .12s ease, left .16s ease-out, top .16s ease-out\n}\n\n.apexcharts-tooltip.apexcharts-theme-light {\n  /* defaults already set above; class kept for backward-compat selectors */\n}\n\n.apexcharts-tooltip.apexcharts-theme-dark {\n  --apx-tt-bg: #1c1c1f;\n  --apx-tt-border: rgba(255, 255, 255, 0.08);\n  --apx-tt-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4), 0 var(--apx-tt-shadow-y-mid) 16px -6px rgba(0, 0, 0, 0.45), 0 var(--apx-tt-shadow-y-far) 36px -12px rgba(0, 0, 0, 0.55);\n  --apx-tt-arrow-shadow: drop-shadow(0 0 0.5px rgba(0, 0, 0, 0.55)) drop-shadow(0 var(--apx-tt-arrow-drop-y) 4px rgba(0, 0, 0, 0.45));\n  --apx-tt-color: #f3f4f6;\n  --apx-tt-color-muted: rgba(243, 244, 246, 0.55);\n}\n\n.apexcharts-tooltip * {\n  font-family: inherit\n}\n\n.apexcharts-tooltip-title {\n  padding: 8px 12px 4px;\n  font-size: 12px;\n  font-weight: 600;\n  letter-spacing: 0.01em;\n  color: var(--apx-tt-color-muted);\n  background: transparent;\n  border-bottom: none;\n  margin-bottom: 0\n}\n\n.apexcharts-tooltip.apexcharts-theme-light .apexcharts-tooltip-title,\n.apexcharts-tooltip.apexcharts-theme-dark .apexcharts-tooltip-title {\n  background: transparent;\n  border-bottom: none\n}\n\n/* `fillSeriesColor`: each series-group already paints itself with the\n * series colour. Drop the glass body entirely (transparent bg, no\n * border, no backdrop-filter, no padding) and clip the coloured\n * series-group(s) to the tooltip\'s rounded corners so they fill the\n * shell edge-to-edge. Text inside the coloured group is forced to\n * white for contrast. */\n.apexcharts-tooltip.apexcharts-tooltip-fill-series {\n  background: transparent;\n  -webkit-backdrop-filter: none;\n  backdrop-filter: none;\n  border: none;\n  padding: 0;\n  overflow: hidden;\n  color: #fff\n}\n\n.apexcharts-tooltip.apexcharts-tooltip-fill-series .apexcharts-tooltip-title {\n  background: rgba(0, 0, 0, 0.22);\n  color: #fff;\n  opacity: 1;\n  padding: 6px 12px\n}\n\n.apexcharts-tooltip.apexcharts-tooltip-fill-series .apexcharts-tooltip-series-group {\n  color: #fff\n}\n\n/* Arrow connector — sits *entirely outside* the tooltip body. Shares\n * the body\'s solid fill so it reads as a single shape. `filter:\n * drop-shadow` traces the clipped triangle outline (a regular\n * `box-shadow` would be erased by the `clip-path`). */\n.apexcharts-tooltip-arrow {\n  position: absolute;\n  width: 7px;\n  height: 14px;\n  background: var(--apx-tt-arrow-bg);\n  /* The variable already contains the full `drop-shadow(...) ...` filter\n   * chain (stacked shadows) so it\'s applied raw. */\n  -webkit-filter: var(--apx-tt-arrow-shadow);\n  filter: var(--apx-tt-arrow-shadow);\n  pointer-events: none;\n  top: calc(var(--apx-tt-arrow-y, 50%) - 7px)\n}\n\n.apexcharts-tooltip[data-placement="right"] .apexcharts-tooltip-arrow {\n  left: -7px;\n  clip-path: polygon(0 50%, 100% 0, 100% 100%)\n}\n\n.apexcharts-tooltip[data-placement="left"] .apexcharts-tooltip-arrow {\n  right: -7px;\n  clip-path: polygon(100% 50%, 0 0, 0 100%)\n}\n\n/* Vertical arrow variants: tooltip is above/below the data point and the\n * arrow points down/up. The base rule above uses `--apx-tt-arrow-y` for\n * left/right placement; for top/bottom we re-orient the rectangle and\n * use `--apx-tt-arrow-x` (set by applyTooltipPosition). */\n.apexcharts-tooltip[data-placement="top"] .apexcharts-tooltip-arrow,\n.apexcharts-tooltip[data-placement="bottom"] .apexcharts-tooltip-arrow {\n  width: 14px;\n  height: 7px;\n  top: auto;\n  left: calc(var(--apx-tt-arrow-x, 50%) - 7px)\n}\n\n.apexcharts-tooltip[data-placement="top"] .apexcharts-tooltip-arrow {\n  bottom: -7px;\n  clip-path: polygon(50% 100%, 0 0, 100% 0)\n}\n\n.apexcharts-tooltip[data-placement="bottom"] .apexcharts-tooltip-arrow {\n  top: -7px;\n  clip-path: polygon(50% 0, 0 100%, 100% 100%)\n}\n\n/* When the tooltip is flipped below the data point (arrow on top\n * pointing up), the default downward-biased shadows leave the top\n * edge of both the body *and* the arrow undefined. Flipping every\n * Y offset to negative casts the entire elevation upward so the\n * shadow falls between the tooltip and the bar above. */\n.apexcharts-tooltip[data-placement="bottom"] {\n  --apx-tt-shadow-y-mid: -8px;\n  --apx-tt-shadow-y-far: -16px;\n  --apx-tt-arrow-drop-y: -2px\n}\n\n.apexcharts-tooltip-text-goals-value,\n.apexcharts-tooltip-text-y-value,\n.apexcharts-tooltip-text-z-value {\n  display: inline-block;\n  margin-left: 5px;\n  font-weight: 600\n}\n\n.apexcharts-tooltip-text-goals-label:empty,\n.apexcharts-tooltip-text-goals-value:empty,\n.apexcharts-tooltip-text-y-label:empty,\n.apexcharts-tooltip-text-y-value:empty,\n.apexcharts-tooltip-text-z-value:empty,\n.apexcharts-tooltip-title:empty {\n  display: none\n}\n\n.apexcharts-tooltip-text-goals-label,\n.apexcharts-tooltip-text-goals-value {\n  padding: 6px 0 5px\n}\n\n.apexcharts-tooltip-goals-group,\n.apexcharts-tooltip-text-goals-label,\n.apexcharts-tooltip-text-goals-value {\n  display: flex\n}\n\n.apexcharts-tooltip-text-goals-label:not(:empty),\n.apexcharts-tooltip-text-goals-value:not(:empty) {\n  margin-top: -6px\n}\n\n.apexcharts-tooltip-marker {\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  position: relative;\n  width: 12px;\n  height: 12px;\n  margin-right: 6px;\n  vertical-align: middle;\n  color: inherit;\n}\n\n.apexcharts-tooltip-marker svg {\n  width: 100%;\n  height: 100%;\n  display: block;\n}\n\n.apexcharts-tooltip-series-group {\n  padding: 4px 12px;\n  display: none;\n  gap: 8px;\n  text-align: left;\n  justify-content: left;\n  align-items: center\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active .apexcharts-tooltip-marker {\n  opacity: 1\n}\n\n.apexcharts-tooltip-series-group.apexcharts-active:last-child,\n.apexcharts-tooltip-series-group:last-child {\n  padding-bottom: 8px\n}\n\n.apexcharts-tooltip-y-group {\n  padding: 6px 0 5px\n}\n\n.apexcharts-custom-tooltip,\n.apexcharts-tooltip-box {\n  padding: 4px 8px\n}\n\n.apexcharts-tooltip-boxPlot {\n  display: flex;\n  flex-direction: column-reverse\n}\n\n.apexcharts-tooltip-box>div {\n  margin: 4px 0\n}\n\n.apexcharts-tooltip-box span.value {\n  font-weight: 700\n}\n\n.apexcharts-tooltip-rangebar {\n  padding: 5px 8px\n}\n\n.apexcharts-tooltip-rangebar .category {\n  font-weight: 600;\n  color: #777\n}\n\n.apexcharts-tooltip-rangebar .series-name {\n  font-weight: 700;\n  display: block;\n  margin-bottom: 5px\n}\n\n/* X/Y axis tooltips — small popovers that label the crosshair on the\n * axes. Restyled to match the modern data-tooltip palette: solid white\n * body with a subtle border + soft drop-shadow, smaller font, rounded\n * corners. The arrows still use the CSS border-triangle technique\n * (cheap, crisp at small sizes); their colours flow from CSS variables\n * so light/dark themes only need one override per axis. */\n.apexcharts-xaxistooltip,\n.apexcharts-yaxistooltip {\n  --apx-axt-bg: #ffffff;\n  --apx-axt-border: rgba(15, 23, 42, 0.08);\n  --apx-axt-color: #0f172a;\n  --apx-axt-shadow: 0 4px 12px -4px rgba(15, 23, 42, 0.18), 0 1px 3px -1px rgba(15, 23, 42, 0.12);\n  opacity: 0;\n  pointer-events: none;\n  color: var(--apx-axt-color);\n  font-size: 12px;\n  font-weight: 500;\n  text-align: center;\n  border-radius: 6px;\n  position: absolute;\n  z-index: 10;\n  background: var(--apx-axt-bg);\n  border: 1px solid var(--apx-axt-border);\n  box-shadow: var(--apx-axt-shadow)\n}\n\n.apexcharts-xaxistooltip.apexcharts-theme-dark,\n.apexcharts-yaxistooltip.apexcharts-theme-dark {\n  --apx-axt-bg: #1c1c1f;\n  --apx-axt-border: rgba(255, 255, 255, 0.1);\n  --apx-axt-color: #f3f4f6;\n  --apx-axt-shadow: 0 4px 12px -4px rgba(0, 0, 0, 0.55), 0 1px 3px -1px rgba(0, 0, 0, 0.45)\n}\n\n.apexcharts-xaxistooltip {\n  padding: 4px 8px;\n  transition: .15s ease all\n}\n\n.apexcharts-xaxistooltip:after,\n.apexcharts-xaxistooltip:before {\n  left: 50%;\n  border: solid transparent;\n  content: " ";\n  height: 0;\n  width: 0;\n  position: absolute;\n  pointer-events: none\n}\n\n/* :before paints the 1px border outline of the triangle (slightly larger\n * than :after); :after sits inside and paints the fill — leaves a 1px\n * ring of :before visible at the edges. */\n.apexcharts-xaxistooltip:after {\n  border-color: transparent;\n  border-width: 5px;\n  margin-left: -5px\n}\n\n.apexcharts-xaxistooltip:before {\n  border-color: transparent;\n  border-width: 6px;\n  margin-left: -6px\n}\n\n.apexcharts-xaxistooltip-bottom:after,\n.apexcharts-xaxistooltip-bottom:before {\n  bottom: 100%\n}\n\n.apexcharts-xaxistooltip-top:after,\n.apexcharts-xaxistooltip-top:before {\n  top: 100%\n}\n\n.apexcharts-xaxistooltip-bottom:after {\n  border-bottom-color: var(--apx-axt-bg)\n}\n\n.apexcharts-xaxistooltip-bottom:before {\n  border-bottom-color: var(--apx-axt-border)\n}\n\n.apexcharts-xaxistooltip-top:after {\n  border-top-color: var(--apx-axt-bg)\n}\n\n.apexcharts-xaxistooltip-top:before {\n  border-top-color: var(--apx-axt-border)\n}\n\n.apexcharts-xaxistooltip.apexcharts-active {\n  opacity: 1;\n  transition: .15s ease all\n}\n\n.apexcharts-yaxistooltip {\n  padding: 3px 8px\n}\n\n.apexcharts-yaxistooltip:after,\n.apexcharts-yaxistooltip:before {\n  top: 50%;\n  border: solid transparent;\n  content: " ";\n  height: 0;\n  width: 0;\n  position: absolute;\n  pointer-events: none\n}\n\n.apexcharts-yaxistooltip:after {\n  border-color: transparent;\n  border-width: 5px;\n  margin-top: -5px\n}\n\n.apexcharts-yaxistooltip:before {\n  border-color: transparent;\n  border-width: 6px;\n  margin-top: -6px\n}\n\n.apexcharts-yaxistooltip-left:after,\n.apexcharts-yaxistooltip-left:before {\n  left: 100%\n}\n\n.apexcharts-yaxistooltip-right:after,\n.apexcharts-yaxistooltip-right:before {\n  right: 100%\n}\n\n.apexcharts-yaxistooltip-left:after {\n  border-left-color: var(--apx-axt-bg)\n}\n\n.apexcharts-yaxistooltip-left:before {\n  border-left-color: var(--apx-axt-border)\n}\n\n.apexcharts-yaxistooltip-right:after {\n  border-right-color: var(--apx-axt-bg)\n}\n\n.apexcharts-yaxistooltip-right:before {\n  border-right-color: var(--apx-axt-border)\n}\n\n.apexcharts-yaxistooltip.apexcharts-active {\n  opacity: 1\n}\n\n.apexcharts-yaxistooltip-hidden {\n  display: none\n}\n\n.apexcharts-xcrosshairs,\n.apexcharts-ycrosshairs {\n  pointer-events: none;\n  opacity: 0;\n  transition: .15s ease all\n}\n\n.apexcharts-xcrosshairs.apexcharts-active,\n.apexcharts-ycrosshairs.apexcharts-active {\n  opacity: 1;\n  transition: .15s ease all\n}\n\n.apexcharts-ycrosshairs-hidden {\n  opacity: 0\n}\n\n.apexcharts-selection-rect {\n  cursor: move\n}\n\n.svg_select_shape {\n  stroke-width: 1;\n  stroke-dasharray: 10 10;\n  stroke: black;\n  stroke-opacity: 0.1;\n  pointer-events: none;\n  fill: none;\n}\n\n.svg_select_handle {\n  stroke-width: 3;\n  stroke: black;\n  fill: none;\n}\n\n.svg_select_handle_r {\n  cursor: e-resize;\n}\n\n.svg_select_handle_l {\n  cursor: w-resize;\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-zoom {\n  cursor: crosshair\n}\n\n.apexcharts-svg.apexcharts-zoomable.hovering-pan {\n  cursor: move\n}\n\n.apexcharts-menu-icon,\n.apexcharts-pan-icon,\n.apexcharts-reset-icon,\n.apexcharts-selection-icon,\n.apexcharts-toolbar-custom-icon,\n.apexcharts-zoom-icon,\n.apexcharts-zoomin-icon,\n.apexcharts-zoomout-icon {\n  cursor: pointer;\n  /* WCAG 2.5.8 Target Size (Minimum): 24×24 CSS px hit target. */\n  width: 26px;\n  height: 24px;\n  line-height: 24px;\n  color: #6e8192;\n  text-align: center;\n  /* Reset native <button> chrome — these are styled via SVG icons. */\n  padding: 0;\n  margin: 0;\n  background: transparent;\n  border: 0;\n  border-radius: 5px;\n  display: inline-flex;\n  align-items: center;\n  justify-content: center;\n  transition: background-color .12s ease, color .12s ease;\n}\n\n.apexcharts-menu-icon svg,\n.apexcharts-pan-icon svg,\n.apexcharts-reset-icon svg,\n.apexcharts-selection-icon svg,\n.apexcharts-zoom-icon svg,\n.apexcharts-zoomin-icon svg,\n.apexcharts-zoomout-icon svg {\n  width: 18px;\n  height: 18px;\n  fill: none;\n  stroke: currentColor;\n  stroke-width: 2;\n  stroke-linecap: round;\n  stroke-linejoin: round\n}\n\n.apexcharts-theme-dark .apexcharts-menu-icon,\n.apexcharts-theme-dark .apexcharts-pan-icon,\n.apexcharts-theme-dark .apexcharts-reset-icon,\n.apexcharts-theme-dark .apexcharts-selection-icon,\n.apexcharts-theme-dark .apexcharts-toolbar-custom-icon,\n.apexcharts-theme-dark .apexcharts-zoom-icon,\n.apexcharts-theme-dark .apexcharts-zoomin-icon,\n.apexcharts-theme-dark .apexcharts-zoomout-icon {\n  color: #d4d6dc\n}\n\n.apexcharts-canvas .apexcharts-pan-icon.apexcharts-selected,\n.apexcharts-canvas .apexcharts-reset-zoom-icon.apexcharts-selected,\n.apexcharts-canvas .apexcharts-selection-icon.apexcharts-selected,\n.apexcharts-canvas .apexcharts-zoom-icon.apexcharts-selected {\n  background: rgba(0, 143, 251, 0.12);\n  color: #008ffb\n}\n\n.apexcharts-theme-light .apexcharts-menu-icon:hover,\n.apexcharts-theme-light .apexcharts-pan-icon:not(.apexcharts-selected):hover,\n.apexcharts-theme-light .apexcharts-reset-icon:hover,\n.apexcharts-theme-light .apexcharts-selection-icon:not(.apexcharts-selected):hover,\n.apexcharts-theme-light .apexcharts-zoom-icon:not(.apexcharts-selected):hover,\n.apexcharts-theme-light .apexcharts-zoomin-icon:hover,\n.apexcharts-theme-light .apexcharts-zoomout-icon:hover {\n  background: rgba(15, 23, 42, 0.06);\n  color: #1f2937\n}\n\n.apexcharts-theme-dark .apexcharts-menu-icon:hover,\n.apexcharts-theme-dark .apexcharts-pan-icon:not(.apexcharts-selected):hover,\n.apexcharts-theme-dark .apexcharts-reset-icon:hover,\n.apexcharts-theme-dark .apexcharts-selection-icon:not(.apexcharts-selected):hover,\n.apexcharts-theme-dark .apexcharts-zoom-icon:not(.apexcharts-selected):hover,\n.apexcharts-theme-dark .apexcharts-zoomin-icon:hover,\n.apexcharts-theme-dark .apexcharts-zoomout-icon:hover {\n  background: rgba(255, 255, 255, 0.08);\n  color: #fff\n}\n\n.apexcharts-menu-icon,\n.apexcharts-selection-icon {\n  position: relative\n}\n\n.apexcharts-toolbar {\n  position: absolute;\n  z-index: 11;\n  display: inline-flex;\n  align-items: center;\n  gap: 1px;\n  padding: 3px;\n  border-radius: 8px;\n  background: rgba(255, 255, 255, 0.85);\n  backdrop-filter: blur(8px);\n  -webkit-backdrop-filter: blur(8px);\n}\n\n.apexcharts-theme-dark .apexcharts-toolbar {\n  background: rgba(28, 28, 31, 0.82);\n}\n\n.apexcharts-menu {\n  background: rgba(255, 255, 255, 0.95);\n  backdrop-filter: blur(8px);\n  -webkit-backdrop-filter: blur(8px);\n  position: absolute;\n  top: calc(100% + 4px);\n  border: 1px solid rgba(15, 23, 42, 0.08);\n  border-radius: 8px;\n  padding: 4px;\n  right: 0;\n  opacity: 0;\n  min-width: 120px;\n  transition: opacity .15s ease, transform .15s ease;\n  transform: translateY(-2px);\n  pointer-events: none;\n  box-shadow: 0 4px 16px -4px rgba(15, 23, 42, 0.12), 0 2px 4px -1px rgba(15, 23, 42, 0.06)\n}\n\n.apexcharts-menu.apexcharts-menu-open {\n  opacity: 1;\n  transform: translateY(0);\n  pointer-events: all\n}\n\n.apexcharts-menu-item {\n  padding: 6px 9px;\n  font-size: 12px;\n  border-radius: 5px;\n  cursor: pointer\n}\n\n.apexcharts-theme-light .apexcharts-menu-item:hover {\n  background: rgba(15, 23, 42, 0.06)\n}\n\n.apexcharts-theme-dark .apexcharts-menu {\n  background: rgba(28, 28, 31, 0.92);\n  border-color: rgba(255, 255, 255, 0.08);\n  color: #f3f4f6;\n  box-shadow: 0 4px 16px -4px rgba(0, 0, 0, 0.5), 0 2px 4px -1px rgba(0, 0, 0, 0.4)\n}\n\n.apexcharts-theme-dark .apexcharts-menu-item:hover {\n  background: rgba(255, 255, 255, 0.08)\n}\n\n@media screen and (min-width:768px) {\n  .apexcharts-canvas:hover .apexcharts-toolbar {\n    opacity: 1\n  }\n}\n\n/* Toolbar keyboard accessibility: show toolbar when any button inside it is focused */\n.apexcharts-toolbar:focus-within {\n  opacity: 1\n}\n\n/* Focus indicator for toolbar icon buttons */\n.apexcharts-menu-icon:focus-visible,\n.apexcharts-pan-icon:focus-visible,\n.apexcharts-reset-icon:focus-visible,\n.apexcharts-selection-icon:focus-visible,\n.apexcharts-toolbar-custom-icon:focus-visible,\n.apexcharts-zoom-icon:focus-visible,\n.apexcharts-zoomin-icon:focus-visible,\n.apexcharts-zoomout-icon:focus-visible {\n  outline: 2px solid var(--apexcharts-focus-color, #008FFB);\n  outline-offset: 1px;\n  border-radius: 5px\n}\n\n/* Focus indicator for hamburger menu items */\n.apexcharts-menu-item:focus-visible {\n  outline: 2px solid var(--apexcharts-focus-color, #008FFB);\n  outline-offset: -2px;\n  background: #eee\n}\n\n.apexcharts-canvas .apexcharts-element-hidden,\n.apexcharts-datalabel.apexcharts-element-hidden,\n.apexcharts-hide .apexcharts-series-points {\n  opacity: 0;\n}\n\n.apexcharts-hidden-element-shown {\n  opacity: 1;\n  transition: 0.25s ease all;\n}\n\n.apexcharts-datalabel,\n.apexcharts-datalabel-label,\n.apexcharts-datalabel-value,\n.apexcharts-datalabels,\n.apexcharts-pie-label {\n  cursor: default;\n  pointer-events: none\n}\n\n.apexcharts-pie-label-delay {\n  opacity: 0;\n  animation-name: opaque;\n  animation-duration: .3s;\n  animation-fill-mode: forwards;\n  animation-timing-function: ease\n}\n\n.apexcharts-radialbar-label {\n  cursor: pointer;\n}\n\n.apexcharts-annotation-rect,\n.apexcharts-area-series .apexcharts-area,\n.apexcharts-gridline,\n.apexcharts-line,\n.apexcharts-point-annotation-label,\n.apexcharts-radar-series path:not(.apexcharts-marker),\n.apexcharts-radar-series polygon,\n.apexcharts-toolbar svg,\n.apexcharts-tooltip .apexcharts-marker,\n.apexcharts-xaxis-annotation-label,\n.apexcharts-yaxis-annotation-label,\n.apexcharts-zoom-rect,\n.no-pointer-events {\n  pointer-events: none\n}\n\n.apexcharts-tooltip-active .apexcharts-marker {\n  transition: .15s ease all\n}\n\n.apexcharts-radar-series .apexcharts-yaxis {\n  pointer-events: none;\n}\n\n.resize-triggers {\n  animation: 1ms resizeanim;\n  visibility: hidden;\n  opacity: 0;\n  height: 100%;\n  width: 100%;\n  overflow: hidden\n}\n\n.contract-trigger:before,\n.resize-triggers,\n.resize-triggers>div {\n  content: " ";\n  display: block;\n  position: absolute;\n  top: 0;\n  left: 0\n}\n\n.resize-triggers>div {\n  height: 100%;\n  width: 100%;\n  background: #eee;\n  overflow: auto\n}\n\n.contract-trigger:before {\n  overflow: hidden;\n  width: 200%;\n  height: 200%\n}\n\n.apexcharts-bar-goals-markers {\n  pointer-events: none\n}\n\n.apexcharts-bar-shadows {\n  pointer-events: none\n}\n\n.apexcharts-rangebar-goals-markers {\n  pointer-events: none\n}\n\n.apexcharts-disable-transitions * {\n  transition: none !important;\n}';
    class ApexCharts {
        /**
         * Creates a new ApexCharts instance.
         *
         * @param {HTMLElement} el - The DOM element to render the chart into.
         * @param {ApexOptions} opts - Chart configuration options.
         */
        constructor(el, opts) {
            // Module properties set dynamically by InitCtxVariables.initModules().
            // Declared as typed class fields so @ts-check resolves them throughout the
            // class body without errors. Each field typed as `any` since the modules are
            // plain objects whose specific shapes are not yet typed.
            /** @type {any} */
            __publicField(this, "core");
            /** @type {any} */
            __publicField(this, "responsive");
            /** @type {any} */
            __publicField(this, "axes");
            /** @type {any} */
            __publicField(this, "grid");
            /** @type {any} */
            __publicField(this, "graphics");
            /** @type {any} */
            __publicField(this, "coreUtils");
            /** @type {any} */
            __publicField(this, "crosshairs");
            /** @type {any} */
            __publicField(this, "events");
            /** @type {any} */
            __publicField(this, "fill");
            /** @type {any} */
            __publicField(this, "localization");
            /** @type {any} */
            __publicField(this, "options");
            /** @type {any} */
            __publicField(this, "series");
            /** @type {any} */
            __publicField(this, "theme");
            /** @type {any} */
            __publicField(this, "formatters");
            /** @type {any} */
            __publicField(this, "titleSubtitle");
            /** @type {any} */
            __publicField(this, "dimensions");
            /** @type {any} */
            __publicField(this, "updateHelpers");
            /** @type {any} */
            __publicField(this, "tooltip");
            /** @type {any} */
            __publicField(this, "data");
            /** @type {any} */
            __publicField(this, "animations");
            /** @type {any} */
            __publicField(this, "exports");
            /** @type {any} */
            __publicField(this, "legend");
            /** @type {any} */
            __publicField(this, "toolbar");
            /** @type {any} */
            __publicField(this, "zoomPanSelection");
            /** @type {any} */
            __publicField(this, "keyboardNavigation");
            /** @type {any} */
            __publicField(this, "annotations");
            /** @type {any} */
            __publicField(this, "morphTypeChange");
            /** @type {any} */
            __publicField(this, "timeScale");
            /** @type {any} */
            __publicField(this, "_keyboardNavigation");
            /** @type {any} */
            __publicField(this, "windowResizeHandler");
            /** @type {any} */
            __publicField(this, "parentResizeHandler");
            /** @type {string[]} */
            __publicField(this, "publicMethods", []);
            /** @type {string[]} */
            __publicField(this, "eventList", []);
            /** @type {any} */
            __publicField(this, "config");
            this.opts = opts;
            this.ctx = this;
            this.w = new Base(opts).init();
            this.el = el;
            this.w.globals.cuid = Utils$1.randomId();
            this.w.globals.chartID = this.w.config.chart.id ? Utils$1.escapeString(this.w.config.chart.id) : this.w.globals.cuid;
            applyAnimationPolicy(this.w);
            const initCtx = new InitCtxVariables(this);
            initCtx.initModules();
            this.lastUpdateOptions = null;
            this.create = this.create.bind(this);
            if (Environment.isBrowser()) {
                this.windowResizeHandler = this._windowResizeHandler.bind(this);
                this.parentResizeHandler = this._parentResizeCallback.bind(this);
            }
        }
        /**
         * Renders the chart. Must be called once after construction.
         *
         * @returns {Promise<ApexCharts>} Resolves with the chart instance after mount.
         */
        render() {
            var _a, _b;
            if (!((_b = (_a = this.w) == null ? void 0 : _a.config) == null ? void 0 : _b.chart)) {
                return Promise.reject(
                    new Error(
                        "ApexCharts: chart configuration is missing or invalid. Ensure the options object includes a `chart` property."
                    )
                );
            }
            return new Promise((resolve, reject) => {
                var _a2;
                if (Utils$1.elementExists(this.el)) {
                    if (typeof Apex._chartInstances === "undefined") {
                        Apex._chartInstances = [];
                    }
                    if (this.w.config.chart.id) {
                        Apex._chartInstances.push({
                            id: this.w.globals.chartID,
                            group: this.w.config.chart.group,
                            chart: this
                        });
                    }
                    this.setLocale(this.w.config.chart.defaultLocale);
                    const beforeMount = this.w.config.chart.events.beforeMount;
                    if (typeof beforeMount === "function") {
                        beforeMount(this, this.w);
                    }
                    this.events.fireEvent("beforeMount", [this, this.w]);
                    if (Environment.isBrowser()) {
                        window.addEventListener("resize", this.windowResizeHandler);
                        addResizeListener(
                            /** @type {HTMLElement} */
                            this.el.parentNode,
                            this.parentResizeHandler
                        );
                        const rootNode = (
                            /** @type {any} */
                            this.el.getRootNode && this.el.getRootNode()
                        );
                        const inShadowRoot = Utils$1.is("ShadowRoot", rootNode);
                        const doc = this.el.ownerDocument;
                        let css = inShadowRoot ? rootNode.getElementById("apexcharts-css") : doc.getElementById("apexcharts-css");
                        if (!css) {
                            css = BrowserAPIs.createElementNS(
                                "http://www.w3.org/1999/xhtml",
                                "style"
                            );
                            css.id = "apexcharts-css";
                            css.textContent = apexCSS;
                            const nonce = ((_a2 = this.opts.chart) == null ? void 0 : _a2.nonce) || this.w.config.chart.nonce;
                            if (nonce) {
                                css.setAttribute("nonce", nonce);
                            }
                            if (inShadowRoot) {
                                rootNode.prepend(css);
                            } else if (this.w.config.chart.injectStyleSheet !== false) {
                                doc.head.appendChild(css);
                            }
                        }
                    }
                    const graphData = this.create(this.w.config.series, {});
                    if (!graphData) return resolve(this);
                    this.mount(graphData).then(() => {
                        if (typeof this.w.config.chart.events.mounted === "function") {
                            this.w.config.chart.events.mounted(this, this.w);
                        }
                        this.events.fireEvent("mounted", [this, this.w]);
                        resolve(graphData);
                    }).catch((e) => {
                        var _a3, _b2;
                        const enriched = e instanceof Error ? e : new Error(String(e));
                        const err = (
                            /** @type {any} */
                            enriched
                        );
                        err.chartId = (_b2 = (_a3 = this.w) == null ? void 0 : _a3.globals) == null ? void 0 : _b2.chartID;
                        err.el = this.el;
                        reject(enriched);
                    });
                } else {
                    reject(new Error("Element not found"));
                }
            });
        }
        /**
         * @param {any[]} ser
         * @param {object} opts
         */
        create(ser, opts) {
            var _a, _b, _c;
            const w = this.w;
            if (!this.core) {
                const initCtx = new InitCtxVariables(this);
                initCtx.initModules();
            }
            const gl = this.w.globals;
            gl.noData = false;
            gl.animationEnded = false;
            if (!Utils$1.elementExists(this.el)) {
                gl.animationEnded = true;
                return null;
            }
            this.responsive.checkResponsiveConfig(opts);
            if (w.config.xaxis.convertedCatToNumeric) {
                const defaults = new Defaults(w.config);
                defaults.convertCatToNumericXaxis(w.config, this.ctx);
            }
            this.core.setupElements();
            if (w.config.chart.type === "treemap") {
                w.config.grid.show = false;
                w.config.yaxis[0].show = false;
            }
            if (gl.svgWidth === 0) {
                gl.animationEnded = true;
                return null;
            }
            let series = ser;
            ser.forEach((s, realIndex) => {
                if (s.hidden) {
                    series = this.legend.legendHelpers.getSeriesAfterCollapsing({
                        realIndex
                    });
                }
            });
            const combo = CoreUtils.checkComboSeries(series, w.config.chart.type);
            gl.comboCharts = combo.comboCharts;
            gl.comboBarCount = combo.comboBarCount;
            const allSeriesAreEmpty = series.every((s) => s.data && s.data.length === 0);
            if (series.length === 0 || allSeriesAreEmpty && gl.collapsedSeries.length < 1) {
                this.series.handleNoData();
            }
            if (Environment.isBrowser()) {
                this.events.setupEventHandlers();
            }
            const parsedState = this.data.parseData(series);
            this._writeParsedSeriesData(parsedState.seriesData);
            this._writeParsedRangeData(parsedState.rangeData);
            this._writeParsedCandleData(parsedState.candleData);
            this._writeParsedLabelData(parsedState.labelData);
            this._writeParsedAxisFlags(parsedState.axisFlags);
            this.theme.init();
            const markers = new Markers(this.w, this);
            markers.setGlobalMarkerSize();
            this.formatters.setLabelFormatters();
            this.titleSubtitle.draw();
            if (!gl.noData || gl.collapsedSeries.length === w.seriesData.series.length || w.config.legend.showForSingleSeries) {
                (_a = this.legend) == null ? void 0 : _a.init();
            }
            this.series.hasAllSeriesEqualX();
            if (gl.axisCharts) {
                this.core.coreCalculations();
                if (w.config.xaxis.type !== "category") {
                    this.formatters.setLabelFormatters();
                }
                if (this.ctx.toolbar) {
                    this.ctx.toolbar.minX = w.globals.minX;
                    this.ctx.toolbar.maxX = w.globals.maxX;
                }
            }
            this.formatters.heatmapLabelFormatters();
            const coreUtils = new CoreUtils(this.w);
            coreUtils.getLargestMarkerSize();
            const layoutState = this.dimensions.plotCoords();
            this._writeLayoutCoords(layoutState.layout);
            const xyRatios = this.core.xySettings();
            this.grid.createGridMask();
            const elGraph = this.core.plotChartType(series, xyRatios);
            const dataLabels = new DataLabels(this.w, this);
            dataLabels.bringForward();
            if (w.config.dataLabels.background.enabled) {
                dataLabels.dataLabelsBackground();
            }
            this.core.shiftGraphPosition();
            (_c = (_b = this.legend) == null ? void 0 : _b.heatmapGradientLegend) == null ? void 0 : _c.repositionToPlot();
            if (w.globals.dataPoints > 50) {
                w.dom.elWrap.classList.add("apexcharts-disable-transitions");
            }
            const dim = {
                plot: {
                    left: w.layout.translateX,
                    top: w.layout.translateY,
                    width: w.layout.gridWidth,
                    height: w.layout.gridHeight
                }
            };
            return {
                elGraph,
                xyRatios,
                dimensions: dim
            };
        }
        /**
         * @param {any} graphData
         */
        mount(graphData = null) {
            const me = this;
            const w = me.w;
            return new Promise((resolve, reject) => {
                var _a, _b, _c, _d, _e, _f, _g, _h, _i;
                if (me.el === null) {
                    return reject(
                        new Error("Not enough data to display or target element not found")
                    );
                } else if (graphData === null || w.globals.allSeriesCollapsed) {
                    me.series.handleNoData();
                }
                me.grid = new Grid(me.w, me);
                const elgrid = me.grid.drawGrid();
                const AnnotationsCtor = InitCtxVariables._featureRegistry.get("annotations");
                me.annotations = AnnotationsCtor ? new AnnotationsCtor(me.w, {
                    theme: me.theme,
                    timeScale: me.timeScale
                }) : null;
                (_a = me.annotations) == null ? void 0 : _a.drawImageAnnos();
                (_b = me.annotations) == null ? void 0 : _b.drawTextAnnos();
                if (w.config.grid.position === "back") {
                    if (elgrid) {
                        w.dom.elGraphical.add(elgrid.el);
                    }
                    if ((_c = elgrid == null ? void 0 : elgrid.elGridBorders) == null ? void 0 : _c.node) {
                        w.dom.elGraphical.add(elgrid.elGridBorders);
                    }
                }
                if (Array.isArray(graphData.elGraph)) {
                    for (let g = 0; g < graphData.elGraph.length; g++) {
                        w.dom.elGraphical.add(graphData.elGraph[g]);
                    }
                } else {
                    w.dom.elGraphical.add(graphData.elGraph);
                }
                if (w.config.grid.position === "front") {
                    if (elgrid) {
                        w.dom.elGraphical.add(elgrid.el);
                    }
                    if ((_d = elgrid == null ? void 0 : elgrid.elGridBorders) == null ? void 0 : _d.node) {
                        w.dom.elGraphical.add(elgrid.elGridBorders);
                    }
                }
                if (w.config.xaxis.crosshairs.position === "front") {
                    me.crosshairs.drawXCrosshairs();
                }
                if (w.config.yaxis[0].crosshairs.position === "front") {
                    me.crosshairs.drawYCrosshairs();
                }
                if (w.config.chart.type !== "treemap") {
                    me.axes.drawAxis(w.config.chart.type, elgrid);
                }
                const xAxis = new XAxis(this.w, this.ctx, elgrid);
                const yaxis = new YAxis(
                    this.w, {
                        theme: this.theme,
                        timeScale: this.timeScale
                    },
                    elgrid
                );
                if (elgrid !== null) {
                    xAxis.xAxisLabelCorrections();
                    yaxis.setYAxisTextAlignments();
                    w.config.yaxis.map((yaxe, index) => {
                        if (w.globals.ignoreYAxisIndexes.indexOf(index) === -1) {
                            yaxis.yAxisTitleRotate(index, yaxe.opposite);
                        }
                    });
                }
                (_e = me.annotations) == null ? void 0 : _e.drawAxesAnnotations();
                if (!w.globals.noData) {
                    if (Environment.isBrowser() && w.config.tooltip.enabled && !w.globals.noData) {
                        (_f = me.w.globals.tooltip) == null ? void 0 : _f.drawTooltip(graphData.xyRatios);
                    }
                    if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.keyboard.enabled && w.config.chart.accessibility.keyboard.navigation.enabled) {
                        (_g = me.keyboardNavigation) == null ? void 0 : _g.init();
                    }
                    if (Environment.isBrowser() && w.globals.axisCharts && (w.axisFlags.isXNumeric || /** @type {Record<string,any>} */
                            w.config.xaxis.convertedCatToNumeric || w.axisFlags.isRangeBar)) {
                        if (w.config.chart.zoom.enabled || w.config.chart.selection && w.config.chart.selection.enabled || // @ts-ignore — chart.pan is an internal toolbar config property
                            w.config.chart.pan && w.config.chart.pan.enabled) {
                            (_h = me.zoomPanSelection) == null ? void 0 : _h.init({
                                xyRatios: graphData.xyRatios
                            });
                        }
                    } else {
                        const tools = w.config.chart.toolbar.tools;
                        const toolsArr = [
                            "zoom",
                            "zoomin",
                            "zoomout",
                            "selection",
                            "pan",
                            "reset"
                        ];
                        toolsArr.forEach((t) => {
                            tools[t] = false;
                        });
                    }
                    if (w.config.chart.toolbar.show && !w.globals.allSeriesCollapsed) {
                        (_i = me.toolbar) == null ? void 0 : _i.createToolbar();
                    }
                }
                if (w.globals.memory.methodsToExec.length > 0) {
                    w.globals.memory.methodsToExec.forEach((fn) => {
                        fn.method(fn.params, false, fn.context);
                    });
                }
                if (!w.globals.axisCharts && !w.globals.noData) {
                    me.core.resizeNonAxisCharts();
                }
                resolve(me);
            });
        }
        /**
         * Destroys the chart instance, removes all DOM elements and event listeners.
         * After calling this, the instance should not be used again.
         */
        destroy() {
            if (Environment.isBrowser()) {
                window.removeEventListener("resize", this.windowResizeHandler);
                removeResizeListener(
                    /** @type {Element} */
                    this.el.parentNode,
                    this.parentResizeHandler
                );
            }
            const chartID = this.w.config.chart.id;
            if (chartID) {
                Apex._chartInstances.forEach(
                    (c, i) => {
                        if (c.id === Utils$1.escapeString(chartID)) {
                            Apex._chartInstances.splice(i, 1);
                        }
                    }
                );
            }
            if (this._keyboardNavigation) {
                this._keyboardNavigation.destroy();
            }
            new Destroy(this.ctx).clear({
                isUpdating: false
            });
        }
        /**
         * Merges new options into the existing config and re-renders the chart.
         *
         * @param {ApexOptions} options - Partial config object merged with the existing config.
         * @param {boolean} [redraw=false] - When true, redraws the chart from scratch instead of animating from previous paths.
         * @param {boolean} [animate=true] - Whether to animate the update.
         * @param {boolean} [updateSyncedCharts=true] - Whether to propagate the update to charts in the same group.
         * @param {boolean} [overwriteInitialConfig=true] - When true, replaces the stored initial config used by resetSeries().
         * @returns {Promise<ApexCharts>} Resolves with the chart instance after re-render.
         */
        updateOptions(options2, redraw = false, animate = true, updateSyncedCharts = true, overwriteInitialConfig = true) {
            const w = this.w;
            w.interact.selection = void 0;
            if (this.lastUpdateOptions) {
                if (Utils$1.shallowEqual(this.lastUpdateOptions, options2)) {
                    return Promise.resolve(this);
                }
                if (options2.series && this.lastUpdateOptions.series) {
                    if (JSON.stringify(this.lastUpdateOptions.series) === JSON.stringify(options2.series)) {
                        const optionsWithoutSeries = __spreadValues({}, options2);
                        const lastWithoutSeries = __spreadValues({}, this.lastUpdateOptions);
                        delete optionsWithoutSeries.series;
                        delete lastWithoutSeries.series;
                        if (Utils$1.shallowEqual(optionsWithoutSeries, lastWithoutSeries)) {
                            return Promise.resolve(this);
                        }
                    }
                }
            }
            if (options2.series) {
                this.data.resetParsingFlags();
                this.series.resetSeries(false, true, false);
                if (options2.series.length && options2.series[0].data) {
                    options2.series = options2.series.map(
                        (s, i) => {
                            return this.updateHelpers._extendSeries(s, i);
                        }
                    );
                }
                this.updateHelpers.revertDefaultAxisMinMax();
            }
            if (options2.xaxis) {
                options2 = this.updateHelpers.forceXAxisUpdate(options2);
            }
            if (options2.yaxis) {
                options2 = this.updateHelpers.forceYAxisUpdate(options2);
            }
            if (w.globals.collapsedSeriesIndices.length > 0) {
                this.series.clearPreviousPaths();
            }
            if (options2.theme) {
                options2 = this.theme.updateThemeOptions(options2);
            }
            return this.updateHelpers._updateOptions(
                options2,
                redraw,
                animate,
                updateSyncedCharts,
                overwriteInitialConfig
            );
        }
        /**
         * Replaces the chart's series data and re-renders.
         *
         * @param {ApexAxisChartSeries | ApexNonAxisChartSeries} [newSeries=[]] - The replacement series array.
         * @param {boolean} [animate=true] - Whether to animate the update.
         * @param {boolean} [overwriteInitialSeries=true] - When true, replaces the stored initial series used by resetSeries().
         * @returns {Promise<ApexCharts>} Resolves with the chart instance after re-render.
         */
        updateSeries(newSeries = [], animate = true, overwriteInitialSeries = true) {
            this.data.resetParsingFlags();
            this.series.resetSeries(false);
            this.updateHelpers.revertDefaultAxisMinMax();
            return this.updateHelpers._updateSeries(
                newSeries,
                animate,
                overwriteInitialSeries
            );
        }
        /**
         * Appends a new series to the existing series array and re-renders.
         *
         * @param {ApexAxisChartSeries[0] | ApexNonAxisChartSeries} newSerie - The series object to append.
         * @param {boolean} [animate=true] - Whether to animate the update.
         * @param {boolean} [overwriteInitialSeries=true] - When true, replaces the stored initial series used by resetSeries().
         * @returns {Promise<ApexCharts>} Resolves with the chart instance after re-render.
         */
        appendSeries(newSerie, animate = true, overwriteInitialSeries = true) {
            this.data.resetParsingFlags();
            const newSeries = this.w.config.series.slice();
            newSeries.push(
                /** @type {any} */
                newSerie
            );
            this.series.resetSeries(false);
            this.updateHelpers.revertDefaultAxisMinMax();
            return this.updateHelpers._updateSeries(
                newSeries,
                animate,
                overwriteInitialSeries
            );
        }
        /**
         * Appends data points to existing series without replacing them.
         * Each element of `newData` corresponds to the series at the same index.
         *
         * @param {Array<{ data: any[] }>} newData - Data to append, in the same shape as series[].data.
         * @param {boolean} [overwriteInitialSeries=true] - When true, updates the stored initial series used by resetSeries().
         * @returns {Promise<ApexCharts>} Resolves with the chart instance after re-render.
         */
        appendData(newData, overwriteInitialSeries = true) {
            const me = this;
            me.data.resetParsingFlags();
            me.w.globals.dataChanged = true;
            me.series.getPreviousPaths();
            const newSeries = me.w.config.series.slice();
            for (let i = 0; i < newSeries.length; i++) {
                if (newData[i] !== null && typeof newData[i] !== "undefined") {
                    const srcSerie = (
                        /** @type {any} */
                        newData[i]
                    );
                    const dstSerie = (
                        /** @type {any} */
                        newSeries[i]
                    );
                    for (let j = 0; j < srcSerie.data.length; j++) {
                        dstSerie.data.push(srcSerie.data[j]);
                    }
                }
            }
            me.w.config.series = newSeries;
            if (overwriteInitialSeries) {
                me.w.globals.initialSeries = Utils$1.clone(me.w.config.series);
            }
            return this.update();
        }
        /**
         * @param {object} [options]
         */
        update(options2) {
            return new Promise((resolve, reject) => {
                if (this.lastUpdateOptions && JSON.stringify(this.lastUpdateOptions) === JSON.stringify(options2)) {
                    return resolve(this);
                }
                this.lastUpdateOptions = Utils$1.clone(options2);
                new Destroy(this.ctx).clear({
                    isUpdating: true
                });
                const graphData = this.create(this.w.config.series, options2 != null ? options2 : {});
                if (!graphData) return resolve(this);
                this.mount(graphData).then(() => {
                    var _a;
                    (_a = this.morphTypeChange) == null ? void 0 : _a.applyChromeFade();
                    if (typeof this.w.config.chart.events.updated === "function") {
                        this.w.config.chart.events.updated(this, this.w);
                    }
                    this.events.fireEvent("updated", [this, this.w]);
                    this.w.globals.isDirty = true;
                    resolve(this);
                }).catch((e) => {
                    reject(e);
                });
            });
        }
        /**
         * Fast update path for data-only series changes.
         *
         * Skips rebuilding grid, axes, dimensions, legend, annotations, tooltip DOM,
         * and toolbar. Only recalculates scales and replots the series paths.
         * Called automatically by _updateSeries() when the fast path is eligible.
         *
         * @param {boolean} animate - Whether to animate the update.
         * @returns {Promise<ApexCharts>} Resolves with the chart instance.
         */
        fastUpdate(animate) {
            return new Promise((resolve, reject) => {
                var _a;
                try {
                    const w = this.w;
                    const gl = w.globals;
                    gl.shouldAnimate = animate;
                    gl.dataChanged = true;
                    gl.animationEnded = false;
                    PerformanceCache.invalidateSelectors(w);
                    const gl2 = w.globals;
                    gl2.maxY = -Number.MAX_VALUE;
                    gl2.minY = Number.MIN_VALUE;
                    gl2.minYArr = [];
                    gl2.maxYArr = [];
                    gl2.maxX = -Number.MAX_VALUE;
                    gl2.minX = Number.MAX_VALUE;
                    gl2.initialMaxX = -Number.MAX_VALUE;
                    gl2.initialMinX = Number.MAX_VALUE;
                    gl2.yAxisScale = [];
                    gl2.xAxisScale = null;
                    gl2.xAxisTicksPositions = [];
                    gl2.xRange = 0;
                    gl2.yRange = [];
                    gl2.zRange = 0;
                    gl2.xTickAmount = 0;
                    gl2.multiAxisTickAmount = 0;
                    gl2.pointsArray = [];
                    gl2.dataLabelsRects = [];
                    gl2.lastDrawnDataLabelsIndexes = [];
                    gl2.textRectsCache = /* @__PURE__ */ new Map();
                    gl2.domCache = /* @__PURE__ */ new Map();
                    gl2.cachedSelectors = {};
                    gl2.disableZoomIn = false;
                    gl2.disableZoomOut = false;
                    if (gl.axisCharts) {
                        this.core.coreCalculations();
                        if (w.config.xaxis.type !== "category") {
                            this.formatters.setLabelFormatters();
                        }
                    }
                    const xyRatios = this.core.xySettings();
                    const innerEl = w.dom.elGraphical.node;
                    const toRemove = innerEl.querySelectorAll(
                        ".apexcharts-series, .apexcharts-datalabels, .apexcharts-datalabels-background"
                    );
                    toRemove.forEach(
                        (el) => {
                            var _a2;
                            return (_a2 = el.parentNode) == null ? void 0 : _a2.removeChild(el);
                        }
                    );
                    const elGraph = this.core.plotChartType(w.config.series, xyRatios);
                    const gridEl = innerEl.querySelector(".apexcharts-grid");
                    const graphs = Array.isArray(elGraph) ? elGraph : [elGraph];
                    if (gridEl && w.config.grid.position === "front") {
                        graphs.forEach((g) => {
                            const node = g && g.node ? g.node : g;
                            if (node) innerEl.insertBefore(node, gridEl);
                        });
                    } else {
                        graphs.forEach((g) => {
                            w.dom.elGraphical.add(g);
                        });
                    }
                    const dataLabels = new DataLabels(w, this);
                    dataLabels.bringForward();
                    if (w.config.dataLabels.background.enabled) {
                        dataLabels.dataLabelsBackground();
                    }
                    if (Environment.isBrowser() && w.config.tooltip.enabled && !gl.noData) {
                        (_a = w.globals.tooltip) == null ? void 0 : _a.drawTooltip(xyRatios);
                    }
                    if (typeof w.config.chart.events.updated === "function") {
                        w.config.chart.events.updated(this, w);
                    }
                    this.events.fireEvent("updated", [this, w]);
                    gl.isDirty = true;
                    resolve(this);
                } catch (e) {
                    reject(e);
                }
            });
        }
        /**
         * Returns all charts in the same `chart.group` (including this instance),
         * used to synchronise zoom/pan across grouped charts.
         *
         * @returns {ApexCharts[]}
         */
        getSyncedCharts() {
            const chartGroups = this.getGroupedCharts();
            let allCharts = (
                /** @type {ApexCharts[]} */
                [this]
            );
            if (chartGroups.length) {
                allCharts = [];
                chartGroups.forEach((ch) => {
                    allCharts.push(ch);
                });
            }
            return allCharts;
        }
        /**
         * Returns all charts in the same `chart.group`, excluding this instance.
         * Used internally to apply hover/zoom effects to sibling charts.
         *
         * @returns {ApexCharts[]}
         */
        getGroupedCharts() {
            return Apex._chartInstances.filter((ch) => {
                if (ch.group) {
                    return true;
                }
            }).map(
                (ch) => this.w.config.chart.group === ch.group ? ch.chart : this
            );
        }
        /**
         * Retrieves a rendered chart instance by its `chart.id` config value.
         *
         * @param {string} id - The chart ID set via `chart.id` in options.
         * @returns {ApexCharts | undefined}
         */
        static getChartByID(id) {
            const chartId = Utils$1.escapeString(id);
            if (!Apex._chartInstances) return void 0;
            const c = Apex._chartInstances.filter(
                (ch) => ch.id === chartId
            )[0];
            return c && c.chart;
        }
        /**
         * Scans the document for elements with a `data-apexcharts` attribute and
         * `data-options` JSON, then renders a chart in each one automatically.
         * Useful for non-framework HTML pages.
         */
        static initOnLoad() {
            var _a;
            const els = document.querySelectorAll("[data-apexcharts]");
            for (let i = 0; i < els.length; i++) {
                const el = (
                    /** @type {HTMLElement} */
                    els[i]
                );
                const options2 = JSON.parse((_a = els[i].getAttribute("data-options")) != null ? _a : "");
                const apexChart = new ApexCharts(el, options2);
                apexChart.render();
            }
        }
        /**
         * This static method allows users to call chart methods without necessarily from the
         * instance of the chart in case user has assigned chartID to the targeted chart.
         * The chartID is used for mapping the instance stored in Apex._chartInstances global variable
         *
         * This is helpful in cases when you don't have reference of the chart instance
         * easily and need to call the method from anywhere.
         * For eg, in React/Vue applications when you have many parent/child components,
         * and need easy reference to other charts for performing dynamic operations
         *
         * @param {string} chartID - The unique identifier which will be used to call methods
         * on that chart instance
         * @param {string} fn - The method name to call
         * @param {...any} opts - The parameters which are accepted in the original method will be passed here in the same order.
         */
        static exec(chartID, fn, ...opts) {
            const chart = this.getChartByID(chartID);
            if (!chart) return;
            chart.w.globals.isExecCalled = true;
            let ret = null;
            if (chart.publicMethods.indexOf(fn) !== -1) {
                ret = /** @type {any} */
                    chart[fn](...opts);
            }
            return ret;
        }
        /**
         * Deep-merges `source` into `target` and returns the result.
         * Thin wrapper around the internal `Utils.extend` utility.
         *
         * @param {object} target
         * @param {object} source
         * @returns {object}
         */
        static merge(target, source) {
            return Utils$1.extend(target, source);
        }
        static getThemePalettes() {
            return getThemePalettes();
        }
        /**
         * Register additional chart types. Used by sub-entry points so that only
         * the types they include are bundled.
         *
         * @param {Record<string, new (...args: any[]) => any>} typeMap  e.g. { line: Line, area: Line }
         */
        static use(typeMap) {
            register(typeMap);
        }
        /**
         * Register optional feature modules (Exports, Legend, Toolbar,
         * ZoomPanSelection, KeyboardNavigation, Annotations).
         *
         * Call this before rendering any chart. Feature entry files (e.g.
         * `apexcharts/features/legend`) call this automatically when imported.
         * Note: Tooltip is part of core and does not need to be registered.
         *
         * @param {Record<string, new (...args: any[]) => any>} featureMap  e.g. { legend: Legend, exports: Exports }
         */
        static registerFeatures(featureMap) {
            InitCtxVariables.registerFeatures(featureMap);
        }
        /**
         * Toggles (show/hide) the series identified by name.
         * Mirrors a click on the corresponding legend item.
         *
         * @param {string} seriesName
         * @returns {object | undefined} The collapsed series object, if now hidden.
         */
        toggleSeries(seriesName) {
            return this.series.toggleSeries(seriesName);
        }
        /**
         * Highlights or un-highlights a series when the user hovers a legend item.
         * Called internally by the legend; not typically called by consumers.
         *
         * @param {MouseEvent} e
         * @param {HTMLElement} targetElement - The legend marker element being hovered.
         */
        highlightSeriesOnLegendHover(e, targetElement) {
            return this.series.toggleSeriesOnHover(e, targetElement);
        }
        /**
         * Makes a previously hidden series visible and re-renders.
         *
         * @param {string} seriesName
         */
        showSeries(seriesName) {
            this.series.showSeries(seriesName);
        }
        /**
         * Hides a visible series and re-renders.
         *
         * @param {string} seriesName
         */
        hideSeries(seriesName) {
            this.series.hideSeries(seriesName);
        }
        /**
         * Highlights (dims all other series) the series identified by name.
         *
         * @param {string} seriesName
         */
        highlightSeries(seriesName) {
            this.series.highlightSeries(seriesName);
        }
        /**
         * Returns whether the series identified by name is currently hidden.
         *
         * @param {string} seriesName
         * @returns {boolean}
         */
        isSeriesHidden(seriesName) {
            return this.series.isSeriesHidden(seriesName);
        }
        /**
         * Resets the chart to the initial series and optionally the initial zoom level.
         *
         * @param {boolean} [shouldUpdateChart=true] - When true, triggers a re-render.
         * @param {boolean} [shouldResetZoom=true] - When true, restores the initial zoom level.
         */
        resetSeries(shouldUpdateChart = true, shouldResetZoom = true) {
            this.series.resetSeries(shouldUpdateChart, shouldResetZoom);
        }
        /**
         * Subscribes to a chart event by name.
         * Supported event names mirror the `chart.events` option keys
         * (e.g. `'mounted'`, `'updated'`, `'dataPointMouseEnter'`).
         *
         * @param {string} name - Event name.
         * @param {Function} handler - Callback invoked when the event fires.
         */
        addEventListener(name2, handler) {
            this.events.addEventListener(name2, handler);
        }
        /**
         * Removes a previously registered event listener.
         *
         * @param {string} name - Event name.
         * @param {Function} handler - The exact function reference passed to addEventListener.
         */
        removeEventListener(name2, handler) {
            this.events.removeEventListener(name2, handler);
        }
        /**
         * Adds an x-axis annotation dynamically after render.
         *
         * @param {XAxisAnnotations} opts - Annotation configuration.
         * @param {boolean} [pushToMemory=true] - When true, the annotation persists across re-renders.
         * @param {ApexCharts} [context] - Override the target chart instance (used by exec()).
         */
        addXaxisAnnotation(opts, pushToMemory = true, context = void 0) {
            var _a;
            let me = (
                /** @type {ApexCharts} */
                /** @type {unknown} */
                this
            );
            if (context) {
                me = context;
            }
            (_a = me.annotations) == null ? void 0 : _a.addXaxisAnnotationExternal(opts, pushToMemory, me);
        }
        /**
         * Adds a y-axis annotation dynamically after render.
         *
         * @param {YAxisAnnotations} opts - Annotation configuration.
         * @param {boolean} [pushToMemory=true] - When true, the annotation persists across re-renders.
         * @param {ApexCharts} [context] - Override the target chart instance (used by exec()).
         */
        addYaxisAnnotation(opts, pushToMemory = true, context = void 0) {
            var _a;
            let me = (
                /** @type {ApexCharts} */
                /** @type {unknown} */
                this
            );
            if (context) {
                me = context;
            }
            (_a = me.annotations) == null ? void 0 : _a.addYaxisAnnotationExternal(opts, pushToMemory, me);
        }
        /**
         * Adds a point annotation dynamically after render.
         *
         * @param {PointAnnotations} opts - Annotation configuration.
         * @param {boolean} [pushToMemory=true] - When true, the annotation persists across re-renders.
         * @param {ApexCharts} [context] - Override the target chart instance (used by exec()).
         */
        addPointAnnotation(opts, pushToMemory = true, context = void 0) {
            var _a;
            let me = (
                /** @type {ApexCharts} */
                /** @type {unknown} */
                this
            );
            if (context) {
                me = context;
            }
            (_a = me.annotations) == null ? void 0 : _a.addPointAnnotationExternal(opts, pushToMemory, me);
        }
        /**
         * Removes all annotations from the chart.
         *
         * @param {ApexCharts} [context] - Override the target chart instance (used by exec()).
         */
        clearAnnotations(context = void 0) {
            var _a;
            let me = (
                /** @type {ApexCharts} */
                /** @type {unknown} */
                this
            );
            if (context) {
                me = context;
            }
            (_a = me.annotations) == null ? void 0 : _a.clearAnnotations(me);
        }
        /**
         * Removes a specific annotation by its `id`.
         *
         * @param {string} id - The annotation id as set in the annotation config.
         * @param {ApexCharts} [context] - Override the target chart instance (used by exec()).
         */
        removeAnnotation(id, context = void 0) {
            var _a;
            let me = (
                /** @type {ApexCharts} */
                /** @type {unknown} */
                this
            );
            if (context) {
                me = context;
            }
            (_a = me.annotations) == null ? void 0 : _a.removeAnnotation(me, id);
        }
        /**
         * Returns the inner SVG group element that contains all chart graphics.
         *
         * @returns {Element | null}
         */
        getChartArea() {
            const el = this.w.dom.baseEl.querySelector(".apexcharts-inner");
            return el;
        }
        /**
         * Returns the sum of all data points whose x value falls within [minX, maxX].
         *
         * @param {number} minX
         * @param {number} maxX
         * @returns {number[]} One total per series.
         */
        getSeriesTotalXRange(minX, maxX) {
            return this.coreUtils.getSeriesTotalsXRange(minX, maxX);
        }
        /**
         * Returns the highest y value in the specified series.
         *
         * @param {number} [seriesIndex=0]
         * @returns {number}
         */
        getHighestValueInSeries(seriesIndex = 0) {
            const range = new Range(this.w);
            return range.getMinYMaxY(seriesIndex).highestY;
        }
        /**
         * Returns the lowest y value in the specified series.
         *
         * @param {number} [seriesIndex=0]
         * @returns {number}
         */
        getLowestValueInSeries(seriesIndex = 0) {
            const range = new Range(this.w);
            return range.getMinYMaxY(seriesIndex).lowestY;
        }
        /**
         * Returns the sum of each series (the totals used for percentage calculations).
         *
         * @returns {number[]}
         */
        getSeriesTotal() {
            return this.w.globals.seriesTotals;
        }
        /**
         * Returns a curated snapshot of chart state for use in formatters, events,
         * and external integrations. Prefer this over accessing `chart.w` directly.
         *
         * The shape of this object is stable and versioned. `chart.w` is internal
         * and will be restricted in a future major version.
         */
        getState() {
            const w = this.w;
            const gl = w.globals;
            return {
                // Series data — computed/parsed form used for rendering
                series: w.seriesData.series,
                seriesNames: w.seriesData.seriesNames,
                colors: gl.colors,
                labels: w.labelData.labels,
                seriesTotals: gl.seriesTotals,
                seriesPercent: gl.seriesPercent,
                seriesXvalues: gl.seriesXvalues,
                seriesYvalues: gl.seriesYvalues,
                // Axis bounds — updated after each render
                minX: gl.minX,
                maxX: gl.maxX,
                minY: gl.minY,
                maxY: gl.maxY,
                minYArr: gl.minYArr,
                maxYArr: gl.maxYArr,
                minXDiff: gl.minXDiff,
                dataPoints: gl.dataPoints,
                // Axis scale objects — computed tick/scale results
                xAxisScale: gl.xAxisScale,
                yAxisScale: gl.yAxisScale,
                xTickAmount: gl.xTickAmount,
                // Axis type flags
                isXNumeric: w.axisFlags.isXNumeric,
                // Multi-axis series mapping
                seriesYAxisMap: gl.seriesYAxisMap,
                seriesYAxisReverseMap: gl.seriesYAxisReverseMap,
                // Chart dimensions — updated after each render/resize
                svgWidth: gl.svgWidth,
                svgHeight: gl.svgHeight,
                gridWidth: w.layout.gridWidth,
                gridHeight: w.layout.gridHeight,
                // Interactive state
                selectedDataPoints: w.interact.selectedDataPoints,
                collapsedSeriesIndices: gl.collapsedSeriesIndices,
                zoomed: w.interact.zoomed,
                // Chart-type-specific series data (null when not applicable)
                seriesX: w.seriesData.seriesX,
                seriesZ: w.seriesData.seriesZ,
                seriesCandleO: w.candleData.seriesCandleO,
                seriesCandleH: w.candleData.seriesCandleH,
                seriesCandleM: w.candleData.seriesCandleM,
                seriesCandleL: w.candleData.seriesCandleL,
                seriesCandleC: w.candleData.seriesCandleC,
                seriesRangeStart: w.rangeData.seriesRangeStart,
                seriesRangeEnd: w.rangeData.seriesRangeEnd,
                seriesGoals: w.seriesData.seriesGoals
            };
        }
        /**
         * Programmatically selects or deselects a data point.
         * Equivalent to a user click on the data point.
         *
         * @param {number} seriesIndex - Zero-based series index.
         * @param {number} [dataPointIndex] - Zero-based data point index within the series.
         * @returns {number[][] | null} Updated selectedDataPoints array, or null.
         */
        toggleDataPointSelection(seriesIndex, dataPointIndex) {
            return this.updateHelpers.toggleDataPointSelection(
                seriesIndex,
                dataPointIndex
            );
        }
        /**
         * Programmatically zooms the x-axis to the given range.
         * Requires zoom to be enabled (`chart.zoom.enabled: true`).
         *
         * @param {number} min - The minimum x value (timestamp or numeric).
         * @param {number} max - The maximum x value (timestamp or numeric).
         */
        zoomX(min, max) {
            var _a;
            (_a = this.ctx.toolbar) == null ? void 0 : _a.zoomUpdateOptions(min, max);
        }
        /**
         * Switches the active locale, updating all locale-dependent labels (toolbar tooltips, month names, etc.).
         *
         * @param {string} localeName - Must match a locale name defined in `chart.locales`.
         */
        setLocale(localeName) {
            this.localization.setCurrentLocaleValues(localeName);
        }
        /**
         * Exports the chart to a PNG or SVG data URI.
         * Requires the Exports feature: `import 'apexcharts/features/exports'`.
         *
         * @param {{ scale?: number, width?: number }} [options]
         * @returns {Promise<{ imgURI: string } | { blob: Blob }>}
         */
        dataURI(options2) {
            if (!this.ctx.exports)
                throw new Error(
                    "apexcharts: Exports feature is not registered. Import apexcharts/features/exports."
                );
            return this.ctx.exports.dataURI(options2);
        }
        /**
         * Returns the chart's SVG markup as a string, optionally scaled.
         * Requires the Exports feature: `import 'apexcharts/features/exports'`.
         *
         * @param {number} [scale=1]
         * @returns {Promise<string>}
         */
        getSvgString(scale) {
            if (!this.ctx.exports)
                throw new Error(
                    "apexcharts: Exports feature is not registered. Import apexcharts/features/exports."
                );
            return this.ctx.exports.getSvgString(scale);
        }
        /**
         * Triggers a CSV download of the chart's data.
         * Requires the Exports feature: `import 'apexcharts/features/exports'`.
         *
         * @param {{ series?: any, fileName?: string, columnDelimiter?: string, lineDelimiter?: string }} [options]
         */
        exportToCSV(options2 = {}) {
            if (!this.ctx.exports)
                throw new Error(
                    "apexcharts: Exports feature is not registered. Import apexcharts/features/exports."
                );
            return this.ctx.exports.exportToCSV(options2);
        }
        paper() {
            return this.w.dom.Paper;
        }
        // ─── Slice write-back stubs ─────────────────────────────────────────────────
        /**
         * @param {Partial<import('./types/internal').SeriesData>} slice
         */
        _writeParsedSeriesData(slice) {
            Object.assign(this.w.seriesData, slice);
        }
        /**
         * @param {Partial<import('./types/internal').RangeData>} slice
         */
        _writeParsedRangeData(slice) {
            Object.assign(this.w.rangeData, slice);
        }
        /**
         * @param {Partial<import('./types/internal').CandleData>} slice
         */
        _writeParsedCandleData(slice) {
            Object.assign(this.w.candleData, slice);
        }
        /**
         * @param {Partial<import('./types/internal').LabelData>} slice
         */
        _writeParsedLabelData(slice) {
            Object.assign(this.w.labelData, slice);
        }
        /**
         * @param {Partial<import('./types/internal').AxisFlags>} slice
         */
        _writeParsedAxisFlags(slice) {
            Object.assign(this.w.axisFlags, slice);
        }
        /**
         * @param {Partial<import('./types/internal').LayoutCoords>} slice
         */
        _writeLayoutCoords(slice) {
            Object.assign(this.w.layout, slice);
        }
        _parentResizeCallback() {
            if (this.w.globals.animationEnded && this.w.config.chart.redrawOnParentResize) {
                this._windowResize();
            }
        }
        /**
         * Handle window resize and re-draw the whole chart.
         */
        _windowResize() {
            this.w.globals.resizeTimer = window.setTimeout(() => {
                this.w.globals.resized = true;
                this.w.globals.dataChanged = false;
                this.ctx.update();
            }, 150);
        }
        _windowResizeHandler() {
            var _a;
            clearTimeout((_a = this.w.globals.resizeTimer) != null ? _a : void 0);
            let {
                redrawOnWindowResize: redraw
            } = this.w.config.chart;
            if (typeof redraw === "function") {
                redraw = /** @type {any} */
                    redraw();
            }
            redraw && this._windowResize();
        }
    }
    const apexchartsLegendCSS = ".apexcharts-flip-y {\n  transform: scaleY(-1) translateY(-100%);\n  transform-origin: top;\n  transform-box: fill-box;\n}\n.apexcharts-flip-x {\n  transform: scaleX(-1);\n  transform-origin: center;\n  transform-box: fill-box;\n}\n.apexcharts-legend {\n  display: flex;\n  overflow: auto;\n  padding: 0 10px;\n}\n.apexcharts-legend.apexcharts-legend-group-horizontal {\n  flex-direction: column;\n}\n.apexcharts-legend-group {\n  display: flex;\n}\n.apexcharts-legend-group-vertical {\n  flex-direction: column-reverse;\n}\n.apexcharts-legend.apx-legend-position-bottom, .apexcharts-legend.apx-legend-position-top {\n  flex-wrap: wrap\n}\n.apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\n  flex-direction: column;\n  bottom: 0;\n}\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-left, .apexcharts-legend.apx-legend-position-top.apexcharts-align-left, .apexcharts-legend.apx-legend-position-right, .apexcharts-legend.apx-legend-position-left {\n  justify-content: flex-start;\n  align-items: flex-start;\n}\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-center, .apexcharts-legend.apx-legend-position-top.apexcharts-align-center {\n  justify-content: center;\n  align-items: center;\n}\n.apexcharts-legend.apx-legend-position-bottom.apexcharts-align-right, .apexcharts-legend.apx-legend-position-top.apexcharts-align-right {\n  justify-content: flex-end;\n  align-items: flex-end;\n}\n.apexcharts-legend-series {\n  cursor: pointer;\n  line-height: normal;\n  display: flex;\n  align-items: center;\n}\n.apexcharts-legend-text {\n  position: relative;\n  font-size: 14px;\n}\n.apexcharts-legend-text *, .apexcharts-legend-marker * {\n  pointer-events: none;\n}\n.apexcharts-legend-marker {\n  position: relative;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  cursor: pointer;\n  margin-right: 1px;\n}\n\n.apexcharts-legend-series.apexcharts-no-click {\n  cursor: auto;\n}\n.apexcharts-legend .apexcharts-hidden-zero-series, .apexcharts-legend .apexcharts-hidden-null-series {\n  display: none !important;\n}\n.apexcharts-inactive-legend {\n  opacity: 0.45;\n} ";
    class Exports {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
        }
        /**
         * @param {string} svgString
         */
        svgStringToNode(svgString) {
            const parser = new DOMParser();
            const svgDoc = parser.parseFromString(svgString, "image/svg+xml");
            return svgDoc.documentElement;
        }
        /**
         * @param {any} svg
         * @param {number} scale
         */
        scaleSvgNode(svg, scale) {
            const svgWidth = parseFloat(svg.getAttributeNS(null, "width"));
            const svgHeight = parseFloat(svg.getAttributeNS(null, "height"));
            svg.setAttributeNS(null, "width", svgWidth * scale);
            svg.setAttributeNS(null, "height", svgHeight * scale);
            svg.setAttributeNS(null, "viewBox", "0 0 " + svgWidth + " " + svgHeight);
        }
        /**
         * @param {number} [_scale]
         */
        getSvgString(_scale) {
            return new Promise((resolve) => {
                const w = this.w;
                let scale = _scale || w.config.chart.toolbar.export.scale || w.config.chart.toolbar.export.width / w.globals.svgWidth;
                if (!scale) {
                    scale = 1;
                }
                const width = w.globals.svgWidth * scale;
                const height = w.globals.svgHeight * scale;
                const clonedNode = (
                    /** @type {HTMLElement} */
                    w.dom.elWrap.cloneNode(true)
                );
                clonedNode.style.width = width + "px";
                clonedNode.style.height = height + "px";
                const serializedNode = new XMLSerializer().serializeToString(clonedNode);
                const shouldIncludeLegendStyles = w.config.legend.show && w.dom.elLegendWrap && w.dom.elLegendWrap.children.length > 0;
                let exportStyles = `
        .apexcharts-tooltip, .apexcharts-toolbar, .apexcharts-xaxistooltip, .apexcharts-yaxistooltip, .apexcharts-xcrosshairs, .apexcharts-ycrosshairs, .apexcharts-zoom-rect, .apexcharts-selection-rect {
          display: none;
        }
      `;
                if (shouldIncludeLegendStyles) {
                    exportStyles += apexchartsLegendCSS;
                }
                let svgString = `
        <svg xmlns="http://www.w3.org/2000/svg"
          version="1.1"
          xmlns:xlink="http://www.w3.org/1999/xlink"
          class="apexcharts-svg"
          xmlns:data="ApexChartsNS"
          transform="translate(0, 0)"
          width="${w.globals.svgWidth}px" height="${w.globals.svgHeight}px">
          <foreignObject width="100%" height="100%">
            <div xmlns="http://www.w3.org/1999/xhtml" style="width:${width}px; height:${height}px;">
            <style type="text/css">
              ${exportStyles}
            </style>
              ${serializedNode}
            </div>
          </foreignObject>
        </svg>
      `;
                const svgNode = this.svgStringToNode(svgString);
                if (scale !== 1) {
                    this.scaleSvgNode(svgNode, scale);
                }
                this.convertImagesToBase64(svgNode).then(() => {
                    svgString = new XMLSerializer().serializeToString(svgNode);
                    resolve(svgString.replace(/&nbsp;/g, "&#160;"));
                });
            });
        }
        /**
         * @param {any} svgNode
         */
        convertImagesToBase64(svgNode) {
            const images = svgNode.getElementsByTagName("image");
            const promises = Array.from(images).map((img) => {
                const href = img.getAttributeNS("http://www.w3.org/1999/xlink", "href");
                if (href && !href.startsWith("data:")) {
                    return this.getBase64FromUrl(href).then((base64) => {
                        img.setAttributeNS("http://www.w3.org/1999/xlink", "href", base64);
                    }).catch((error) => {
                        console.error("Error converting image to base64:", error);
                    });
                }
                return Promise.resolve();
            });
            return Promise.all(promises);
        }
        /**
         * @param {string} url
         */
        getBase64FromUrl(url) {
            if (Environment.isSSR()) return Promise.resolve(url);
            return new Promise((resolve, reject) => {
                const img = new Image();
                img.crossOrigin = "Anonymous";
                img.onload = () => {
                    const canvas = document.createElement("canvas");
                    canvas.width = img.width;
                    canvas.height = img.height;
                    const ctx = canvas.getContext("2d");
                    if (ctx) ctx.drawImage(img, 0, 0);
                    resolve(canvas.toDataURL());
                };
                img.onerror = reject;
                img.src = url;
            });
        }
        svgUrl() {
            return new Promise((resolve) => {
                this.getSvgString().then((svgData) => {
                    const svgBlob = new Blob([svgData], {
                        type: "image/svg+xml;charset=utf-8"
                    });
                    resolve(URL.createObjectURL(svgBlob));
                });
            });
        }
        /**
         * @param {Record<string, any> | undefined} options
         */
        dataURI(options2) {
            if (Environment.isSSR()) return Promise.resolve({
                imgURI: ""
            });
            return new Promise((resolve) => {
                const w = this.w;
                const scale = options2 ? options2.scale || options2.width / w.globals.svgWidth : 1;
                const canvas = document.createElement("canvas");
                canvas.width = w.globals.svgWidth * scale;
                canvas.height = parseInt(w.dom.elWrap.style.height, 10) * scale;
                const canvasBg = w.config.chart.background === "transparent" || !w.config.chart.background ? "#fff" : w.config.chart.background;
                const ctx = canvas.getContext("2d");
                if (!ctx) return;
                ctx.fillStyle = canvasBg;
                ctx.fillRect(0, 0, canvas.width * scale, canvas.height * scale);
                this.getSvgString(scale).then((svgData) => {
                    const svgUrl = "data:image/svg+xml," + encodeURIComponent(svgData);
                    const img = new Image();
                    img.crossOrigin = "anonymous";
                    img.onload = () => {
                        ctx.drawImage(img, 0, 0);
                        const edgeCanvas = canvas;
                        if (edgeCanvas.msToBlob) {
                            const blob = edgeCanvas.msToBlob();
                            resolve({
                                blob
                            });
                        } else {
                            const imgURI = canvas.toDataURL("image/png");
                            resolve({
                                imgURI
                            });
                        }
                    };
                    img.src = svgUrl;
                });
            });
        }
        exportToSVG() {
            this.svgUrl().then((url) => {
                this.triggerDownload(
                    url,
                    this.w.config.chart.toolbar.export.svg.filename,
                    ".svg"
                );
            });
        }
        exportToPng() {
            const scale = this.w.config.chart.toolbar.export.scale;
            const width = this.w.config.chart.toolbar.export.width;
            const option = scale ? {
                scale
            } : width ? {
                width
            } : void 0;
            this.dataURI(option).then(({
                imgURI,
                blob
            }) => {
                if (blob) {
                    navigator.msSaveOrOpenBlob(blob, this.w.globals.chartID + ".png");
                } else {
                    this.triggerDownload(
                        imgURI,
                        this.w.config.chart.toolbar.export.png.filename,
                        ".png"
                    );
                }
            });
        }
        /** @param {{ series?: any, fileName?: any, columnDelimiter?: string, lineDelimiter?: string }} opts */
        exportToCSV({
            series,
            fileName,
            columnDelimiter = ",",
            lineDelimiter = "\n"
        }) {
            const w = this.w;
            if (!series) series = w.config.series;
            let columns = [];
            const rows = [];
            let result = "";
            const universalBOM = "\uFEFF";
            const gSeries = w.seriesData.series.map((s, i) => {
                return w.globals.collapsedSeriesIndices.indexOf(i) === -1 ? s : [];
            });
            const getFormattedCategory = (cat) => {
                if (typeof w.config.chart.toolbar.export.csv.categoryFormatter === "function") {
                    return w.config.chart.toolbar.export.csv.categoryFormatter(cat);
                }
                if (w.config.xaxis.type === "datetime" && String(cat).length >= 10) {
                    return new Date(cat).toDateString();
                }
                return Utils$1.isNumber(cat) ? cat : cat.split(columnDelimiter).join("");
            };
            const getFormattedValue = (value) => {
                return typeof w.config.chart.toolbar.export.csv.valueFormatter === "function" ? w.config.chart.toolbar.export.csv.valueFormatter(value) : value;
            };
            const seriesMaxDataLength = Math.max(
                ...series.map((s) => {
                    return s.data ? s.data.length : 0;
                })
            );
            const dataFormat = new Data(this.w);
            const axesUtils = new AxesUtils(this.w, {
                theme: this.ctx.theme,
                timeScale: this.ctx.timeScale
            });
            const getCat = (i) => {
                let cat = "";
                if (!w.globals.axisCharts) {
                    cat = w.config.labels[i];
                } else {
                    if (w.config.xaxis.type === "category" || w.config.xaxis.convertedCatToNumeric) {
                        if (w.globals.isBarHorizontal) {
                            const lbFormatter = w.formatters.yLabelFormatters[0];
                            const sr = new Series(this.ctx.w);
                            const activeSeries = sr.getActiveConfigSeriesIndex();
                            cat = lbFormatter(w.labelData.labels[i], {
                                seriesIndex: activeSeries,
                                dataPointIndex: i,
                                w
                            });
                        } else {
                            cat = axesUtils.getLabel(
                                w.labelData.labels,
                                w.labelData.timescaleLabels,
                                0,
                                i
                            ).text;
                        }
                    }
                    if (w.config.xaxis.type === "datetime") {
                        if (w.config.xaxis.categories.length) {
                            cat = w.config.xaxis.categories[i];
                        } else if (w.config.labels.length) {
                            cat = w.config.labels[i];
                        }
                    }
                }
                if (cat === null) return "nullvalue";
                if (Array.isArray(cat)) {
                    cat = cat.join(" ");
                }
                return Utils$1.isNumber(cat) ? cat : cat.split(columnDelimiter).join("");
            };
            const getEmptyDataForCsvColumn = () => {
                return [...Array(seriesMaxDataLength)].map(() => "");
            };
            const handleAxisRowsColumns = (s, sI) => {
                var _a;
                if (columns.length && sI === 0) {
                    rows.push(columns.join(columnDelimiter));
                }
                if (s.data) {
                    s.data = s.data.length && s.data || getEmptyDataForCsvColumn();
                    for (let i = 0; i < s.data.length; i++) {
                        columns = [];
                        let cat = getCat(i);
                        if (cat === "nullvalue") continue;
                        if (!cat) {
                            if (dataFormat.isFormatXY()) {
                                cat = series[sI].data[i].x;
                            } else if (dataFormat.isFormat2DArray()) {
                                cat = series[sI].data[i] ? series[sI].data[i][0] : "";
                            }
                        }
                        if (sI === 0) {
                            columns.push(getFormattedCategory(cat));
                            for (let ci = 0; ci < w.seriesData.series.length; ci++) {
                                const value = dataFormat.isFormatXY() ? (_a = series[ci].data[i]) == null ? void 0 : _a.y : gSeries[ci][i];
                                columns.push(getFormattedValue(value));
                            }
                        }
                        if (w.config.chart.type === "candlestick" || s.type && s.type === "candlestick") {
                            columns.pop();
                            columns.push(w.candleData.seriesCandleO[sI][i]);
                            columns.push(w.candleData.seriesCandleH[sI][i]);
                            columns.push(w.candleData.seriesCandleL[sI][i]);
                            columns.push(w.candleData.seriesCandleC[sI][i]);
                        }
                        if (w.config.chart.type === "boxPlot" || s.type && s.type === "boxPlot") {
                            columns.pop();
                            columns.push(w.candleData.seriesCandleO[sI][i]);
                            columns.push(w.candleData.seriesCandleH[sI][i]);
                            columns.push(w.candleData.seriesCandleM[sI][i]);
                            columns.push(w.candleData.seriesCandleL[sI][i]);
                            columns.push(w.candleData.seriesCandleC[sI][i]);
                        }
                        if (w.config.chart.type === "rangeBar") {
                            columns.pop();
                            columns.push(w.rangeData.seriesRangeStart[sI][i]);
                            columns.push(w.rangeData.seriesRangeEnd[sI][i]);
                        }
                        if (columns.length) {
                            rows.push(columns.join(columnDelimiter));
                        }
                    }
                }
            };
            const handleUnequalXValues = () => {
                const categories = /* @__PURE__ */ new Set();
                const data = {};
                series.forEach((s, sI) => {
                    s == null ? void 0 : s.data.forEach((dataItem) => {
                        let cat, value;
                        if (dataFormat.isFormatXY()) {
                            cat = dataItem.x;
                            value = dataItem.y;
                        } else if (dataFormat.isFormat2DArray()) {
                            cat = dataItem[0];
                            value = dataItem[1];
                        } else {
                            return;
                        }
                        if (! /** @type {Record<string,any>} */
                            data[cat]) {
                            data[cat] = Array(
                                series.length
                            ).fill("");
                        }
                        data[cat][sI] = getFormattedValue(value);
                        categories.add(cat);
                    });
                });
                if (columns.length) {
                    rows.push(columns.join(columnDelimiter));
                }
                Array.from(categories).sort().forEach((cat) => {
                    rows.push([
                        getFormattedCategory(cat),
                        /** @type {Record<string,any>} */
                        data[cat].join(columnDelimiter)
                    ]);
                });
            };
            columns.push(w.config.chart.toolbar.export.csv.headerCategory);
            if (w.config.chart.type === "boxPlot") {
                columns.push("minimum");
                columns.push("q1");
                columns.push("median");
                columns.push("q3");
                columns.push("maximum");
            } else if (w.config.chart.type === "candlestick") {
                columns.push("open");
                columns.push("high");
                columns.push("low");
                columns.push("close");
            } else if (w.config.chart.type === "rangeBar") {
                columns.push("minimum");
                columns.push("maximum");
            } else {
                series.map((s, sI) => {
                    const sname = (s.name ? s.name : `series-${sI}`) + "";
                    if (w.globals.axisCharts) {
                        columns.push(
                            sname.split(columnDelimiter).join("") ? sname.split(columnDelimiter).join("") : `series-${sI}`
                        );
                    }
                });
            }
            if (!w.globals.axisCharts) {
                columns.push(w.config.chart.toolbar.export.csv.headerValue);
                rows.push(columns.join(columnDelimiter));
            }
            if (!w.globals.allSeriesHasEqualX && w.globals.axisCharts && !w.config.xaxis.categories.length && !w.config.labels.length) {
                handleUnequalXValues();
            } else {
                series.map((s, sI) => {
                    if (w.globals.axisCharts) {
                        handleAxisRowsColumns(s, sI);
                    } else {
                        columns = [];
                        columns.push(getFormattedCategory(w.labelData.labels[sI]));
                        columns.push(getFormattedValue(gSeries[sI]));
                        rows.push(columns.join(columnDelimiter));
                    }
                });
            }
            result += rows.join(lineDelimiter);
            this.triggerDownload(
                "data:text/csv; charset=utf-8," + encodeURIComponent(universalBOM + result),
                fileName ? fileName : w.config.chart.toolbar.export.csv.filename,
                ".csv"
            );
        }
        /**
         * @param {string} href
         * @param {string} filename
         * @param {string} ext
         */
        triggerDownload(href, filename, ext) {
            if (Environment.isSSR()) return;
            const downloadLink = document.createElement("a");
            downloadLink.href = href;
            downloadLink.download = (filename ? filename : this.w.globals.chartID) + ext;
            document.body.appendChild(downloadLink);
            downloadLink.click();
            document.body.removeChild(downloadLink);
        }
    }
    ApexCharts.registerFeatures({
        exports: Exports
    });
    let Helpers$3 = class Helpers {
        /**
         * @param {import('./Legend').default} lgCtx
         */
        constructor(lgCtx) {
            this.w = lgCtx.w;
            this.lgCtx = lgCtx;
        }
        getLegendStyles() {
            if (Environment.isSSR()) return null;
            const stylesheet = document.createElement("style");
            stylesheet.setAttribute("type", "text/css");
            const nonce = this.w.config.chart.nonce;
            if (nonce) {
                stylesheet.setAttribute("nonce", nonce);
            }
            const rule = document.createTextNode(apexchartsLegendCSS);
            stylesheet.appendChild(rule);
            return stylesheet;
        }
        getLegendDimensions() {
            const w = this.w;
            const currLegendsWrap = w.dom.baseEl.querySelector(".apexcharts-legend");
            if (!currLegendsWrap) {
                return {
                    clwh: 0,
                    clww: 0
                };
            }
            const {
                width: currLegendsWrapWidth,
                height: currLegendsWrapHeight
            } = currLegendsWrap.getBoundingClientRect();
            return {
                clwh: currLegendsWrapHeight,
                clww: currLegendsWrapWidth
            };
        }
        appendToForeignObject() {
            var _a;
            const legendStyles = this.getLegendStyles();
            if (this.w.config.chart.injectStyleSheet !== false && legendStyles) {
                (_a = this.w.dom.elLegendForeign) == null ? void 0 : _a.appendChild(legendStyles);
            }
        }
        /**
         * @param {number} seriesCnt
         * @param {boolean} isHidden
         */
        toggleDataSeries(seriesCnt, isHidden) {
            var _a, _b;
            const w = this.w;
            if (w.globals.axisCharts || w.config.chart.type === "radialBar") {
                w.globals.resized = true;
                let seriesEl = null;
                let realIndex = null;
                w.globals.risingSeries = [];
                if (w.globals.axisCharts) {
                    seriesEl = w.dom.baseEl.querySelector(
                        `.apexcharts-series[data\\:realIndex='${seriesCnt}']`
                    );
                    if (!seriesEl) return;
                    realIndex = parseInt((_a = seriesEl.getAttribute("data:realIndex")) != null ? _a : "", 10);
                } else {
                    seriesEl = w.dom.baseEl.querySelector(
                        `.apexcharts-series[rel='${seriesCnt + 1}']`
                    );
                    if (!seriesEl) return;
                    realIndex = parseInt((_b = seriesEl.getAttribute("rel")) != null ? _b : "", 10) - 1;
                }
                if (isHidden) {
                    const seriesToMakeVisible = [{
                            cs: w.globals.collapsedSeries,
                            csi: w.globals.collapsedSeriesIndices
                        },
                        {
                            cs: w.globals.ancillaryCollapsedSeries,
                            csi: w.globals.ancillaryCollapsedSeriesIndices
                        }
                    ];
                    seriesToMakeVisible.forEach((r) => {
                        const cs = (
                            /** @type {any} */
                            r.cs
                        );
                        const csi = (
                            /** @type {any} */
                            r.csi
                        );
                        this.riseCollapsedSeries(
                            cs,
                            csi,
                            /** @type {number} */
                            realIndex
                        );
                    });
                } else {
                    this.hideSeries({
                        seriesEl,
                        realIndex
                    });
                }
                if (w.config.chart.accessibility.enabled) {
                    const legendItem = w.dom.baseEl.querySelector(
                        `.apexcharts-legend-series[rel="${seriesCnt + 1}"]`
                    );
                    if (legendItem) {
                        const isCollapsed = w.globals.collapsedSeriesIndices.includes(realIndex) || w.globals.ancillaryCollapsedSeriesIndices.includes(realIndex);
                        legendItem.setAttribute(
                            "aria-pressed",
                            isCollapsed ? "true" : "false"
                        );
                        const legendTextEl = legendItem.querySelector(
                            ".apexcharts-legend-text"
                        );
                        const seriesName = legendTextEl ? legendTextEl.textContent : w.seriesData.seriesNames[seriesCnt];
                        const statusText = isCollapsed ? "hidden" : "visible";
                        legendItem.setAttribute(
                            "aria-label",
                            `${seriesName}, ${statusText}. Press Enter or Space to toggle.`
                        );
                    }
                }
            } else {
                const seriesEl = w.dom.Paper.findOne(
                    ` .apexcharts-series[rel='${seriesCnt + 1}'] path`
                );
                const type = w.config.chart.type;
                if (type === "pie" || type === "polarArea" || type === "donut") {
                    const dataLabels = w.config.plotOptions.pie.donut.labels;
                    const graphics = new Graphics(this.w);
                    graphics.pathMouseDown(seriesEl, null);
                    this.lgCtx.printDataLabelsInner(seriesEl.node, dataLabels);
                }
                if (w.config.chart.accessibility.enabled) {
                    const legendItem = w.dom.baseEl.querySelector(
                        `.apexcharts-legend-series[rel="${seriesCnt + 1}"]`
                    );
                    if (legendItem) {
                        const isCollapsed = w.globals.collapsedSeriesIndices.includes(seriesCnt);
                        legendItem.setAttribute(
                            "aria-pressed",
                            isCollapsed ? "true" : "false"
                        );
                        const legendTextEl = legendItem.querySelector(
                            ".apexcharts-legend-text"
                        );
                        const seriesName = legendTextEl ? legendTextEl.textContent : w.seriesData.seriesNames[seriesCnt];
                        const statusText = isCollapsed ? "hidden" : "visible";
                        legendItem.setAttribute(
                            "aria-label",
                            `${seriesName}, ${statusText}. Press Enter or Space to toggle.`
                        );
                    }
                }
            }
        }
        /** @param {{realIndex: any}} opts */
        getSeriesAfterCollapsing({
            realIndex
        }) {
            var _a;
            const w = this.w;
            const gl = w.globals;
            const series = Utils$1.clone(w.config.series);
            if (gl.axisCharts) {
                const yaxis = w.config.yaxis[gl.seriesYAxisReverseMap[realIndex]];
                const collapseData = {
                    index: realIndex,
                    data: series[realIndex].data.slice(),
                    type: series[realIndex].type || w.config.chart.type
                };
                if (yaxis && yaxis.show && yaxis.showAlways) {
                    if (gl.ancillaryCollapsedSeriesIndices.indexOf(realIndex) < 0) {
                        gl.ancillaryCollapsedSeries.push(collapseData);
                        gl.ancillaryCollapsedSeriesIndices.push(realIndex);
                    }
                } else {
                    if (gl.collapsedSeriesIndices.indexOf(realIndex) < 0) {
                        gl.collapsedSeries.push(collapseData);
                        gl.collapsedSeriesIndices.push(realIndex);
                        const removeIndexOfRising = gl.risingSeries.indexOf(realIndex);
                        gl.risingSeries.splice(removeIndexOfRising, 1);
                    }
                }
            } else {
                gl.collapsedSeries.push({
                    index: realIndex,
                    data: series[realIndex],
                    type: (
                        /** @type {any} */
                        (_a = w.config.series[realIndex].type) != null ? _a : "line"
                    )
                });
                gl.collapsedSeriesIndices.push(realIndex);
            }
            gl.allSeriesCollapsed = gl.collapsedSeries.length + gl.ancillaryCollapsedSeries.length === w.config.series.length;
            return this._getSeriesBasedOnCollapsedState(series);
        }
        /** @param {{seriesEl: any, realIndex: any}} opts */
        hideSeries({
            seriesEl,
            realIndex
        }) {
            const w = this.w;
            const series = this.getSeriesAfterCollapsing({
                realIndex
            });
            const seriesChildren = seriesEl.childNodes;
            for (let sc = 0; sc < seriesChildren.length; sc++) {
                if (seriesChildren[sc].classList.contains("apexcharts-series-markers-wrap")) {
                    if (seriesChildren[sc].classList.contains("apexcharts-hide")) {
                        seriesChildren[sc].classList.remove("apexcharts-hide");
                    } else {
                        seriesChildren[sc].classList.add("apexcharts-hide");
                    }
                }
            }
            this.lgCtx.updateSeries(
                series,
                w.config.chart.animations.dynamicAnimation.enabled
            );
        }
        /**
         * @param {any[]} collapsedSeries
         * @param {number[]} seriesIndices
         * @param {number} realIndex
         */
        riseCollapsedSeries(collapsedSeries, seriesIndices, realIndex) {
            const w = this.w;
            let series = Utils$1.clone(w.config.series);
            if (collapsedSeries.length > 0) {
                for (let c = 0; c < collapsedSeries.length; c++) {
                    if (collapsedSeries[c].index === realIndex) {
                        if (w.globals.axisCharts) {
                            series[realIndex].data = collapsedSeries[c].data.slice();
                        } else {
                            series[realIndex] = collapsedSeries[c].data;
                        }
                        if (typeof series[realIndex] !== "number") {
                            series[realIndex].hidden = false;
                        }
                        collapsedSeries.splice(c, 1);
                        seriesIndices.splice(c, 1);
                        w.globals.risingSeries.push(realIndex);
                        c--;
                    }
                }
                series = this._getSeriesBasedOnCollapsedState(series);
                this.lgCtx.updateSeries(
                    series,
                    w.config.chart.animations.dynamicAnimation.enabled
                );
            }
        }
        /**
         * @param {any[]} series
         */
        _getSeriesBasedOnCollapsedState(series) {
            const w = this.w;
            let collapsed = 0;
            if (w.globals.axisCharts) {
                series.forEach((s, sI) => {
                    if (!(w.globals.collapsedSeriesIndices.indexOf(sI) < 0 && w.globals.ancillaryCollapsedSeriesIndices.indexOf(sI) < 0)) {
                        series[sI].data = [];
                        collapsed++;
                    }
                });
            } else {
                series.forEach((s, sI) => {
                    if (!(w.globals.collapsedSeriesIndices.indexOf(sI) < 0)) {
                        series[sI] = 0;
                        collapsed++;
                    }
                });
            }
            w.globals.allSeriesCollapsed = collapsed === series.length;
            return series;
        }
    };
    const SVG_NS = "http://www.w3.org/2000/svg";
    class HeatmapGradientLegend {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {import('../../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this.svgEl = null;
            this.arrowEl = null;
            this.hoverValueEl = null;
            this._min = 0;
            this._max = 0;
            this._geom = null;
            this._bandHitEls = [];
            this._activeBandIndex = -1;
            this._onCellEnter = this._onCellEnter.bind(this);
            this._onCellLeave = this._onCellLeave.bind(this);
            this._onBandEnter = this._onBandEnter.bind(this);
            this._onBandLeave = this._onBandLeave.bind(this);
        }
        /** Default value formatter for min/max labels and the hover tooltip. */
        _getFormatter() {
            const cfg = this.w.config.plotOptions.heatmap.colorScale.gradientLegend;
            if (typeof cfg.formatter === "function") return cfg.formatter;
            return (v) => {
                if (!Number.isFinite(v)) return String(v);
                const abs = Math.abs(v);
                if (abs >= 1e3) return v.toFixed(0);
                if (abs >= 10) return v.toFixed(1);
                return v.toFixed(2);
            };
        }
        /**
         * True when the user has opted into the gradient legend variant.
         * @param {any} w
         */
        static isEnabled(w) {
            var _a, _b, _c, _d;
            const cfg = (_d = (_c = (_b = (_a = w == null ? void 0 : w.config) == null ? void 0 : _a.plotOptions) == null ? void 0 : _b.heatmap) == null ? void 0 : _c.colorScale) == null ? void 0 : _d.gradientLegend;
            return !!(cfg && cfg.enabled);
        }
        /**
         * Build the gradient legend DOM into `elLegendWrap`.
         * Caller is responsible for clearing the wrap first.
         */
        draw() {
            var _a, _b, _c, _d, _e, _f, _g, _h;
            const w = this.w;
            const elLegendWrap = (
                /** @type {HTMLElement} */
                w.dom.elLegendWrap
            );
            if (!elLegendWrap) return;
            const cfg = w.config.plotOptions.heatmap.colorScale.gradientLegend;
            const position = w.config.legend.position;
            const isVertical = position === "left" || position === "right";
            const arrowSize = (_b = (_a = cfg.arrow) == null ? void 0 : _a.size) != null ? _b : 8;
            const arrowGutter = arrowSize + 4;
            const labelPadAlongStrip = cfg.showLabels ? 28 : 4;
            const labelPadAcrossStrip = cfg.showLabels ? 20 : 4;
            const minLabelWidth = cfg.showLabels ? 44 : 0;
            const stripLength = this._resolveStripLength(isVertical ? cfg.height : cfg.width, isVertical);
            const stripThickness = cfg.thickness;
            const svgWidth = isVertical ? Math.max(stripThickness + arrowGutter + 4, minLabelWidth) : stripLength + labelPadAlongStrip * 2;
            const svgHeight = isVertical ? stripLength + labelPadAcrossStrip * 2 : stripThickness + arrowGutter + 4;
            const verticalGroupWidth = stripThickness + arrowGutter;
            const verticalGroupLeftPad = (svgWidth - verticalGroupWidth) / 2;
            const stripX = isVertical ? position === "left" ? verticalGroupLeftPad : verticalGroupLeftPad + arrowGutter : labelPadAlongStrip;
            const stripY = isVertical ? labelPadAcrossStrip : position === "top" ? arrowGutter : 4;
            const svg = BrowserAPIs.createElementNS(SVG_NS, "svg");
            svg.setAttribute("class", "apexcharts-heatmap-gradient-legend");
            svg.setAttribute("width", String(svgWidth));
            svg.setAttribute("height", String(svgHeight));
            svg.setAttribute("overflow", "visible");
            const defs = BrowserAPIs.createElementNS(SVG_NS, "defs");
            const gradId = `apexcharts-heatmap-gradient-${w.globals.cuid}`;
            const linearGrad = BrowserAPIs.createElementNS(SVG_NS, "linearGradient");
            linearGrad.setAttribute("id", gradId);
            if (isVertical) {
                linearGrad.setAttribute("x1", "0");
                linearGrad.setAttribute("y1", "1");
                linearGrad.setAttribute("x2", "0");
                linearGrad.setAttribute("y2", "0");
            } else {
                linearGrad.setAttribute("x1", "0");
                linearGrad.setAttribute("y1", "0");
                linearGrad.setAttribute("x2", "1");
                linearGrad.setAttribute("y2", "0");
            }
            const {
                min,
                max,
                stops,
                bands
            } = this._computeStops();
            this._min = min;
            this._max = max;
            stops.forEach((s) => {
                const stopEl = BrowserAPIs.createElementNS(SVG_NS, "stop");
                stopEl.setAttribute("offset", `${(s.percent * 100).toFixed(2)}%`);
                stopEl.setAttribute("stop-color", s.color);
                linearGrad.appendChild(stopEl);
            });
            defs.appendChild(linearGrad);
            svg.appendChild(defs);
            const rect = BrowserAPIs.createElementNS(SVG_NS, "rect");
            rect.setAttribute("x", String(stripX));
            rect.setAttribute("y", String(stripY));
            rect.setAttribute("width", String(isVertical ? stripThickness : stripLength));
            rect.setAttribute("height", String(isVertical ? stripLength : stripThickness));
            rect.setAttribute("rx", "2");
            rect.setAttribute("fill", `url(#${gradId})`);
            svg.appendChild(rect);
            if (cfg.showLabels) {
                const labelColor = ((_c = cfg.labelStyle) == null ? void 0 : _c.colors) || (Array.isArray(w.config.legend.labels.colors) ? w.config.legend.labels.colors[0] : w.config.legend.labels.colors) || w.config.chart.foreColor;
                const labelFontSize = ((_d = cfg.labelStyle) == null ? void 0 : _d.fontSize) || "11px";
                const labelFontFamily = ((_e = cfg.labelStyle) == null ? void 0 : _e.fontFamily) || w.config.chart.fontFamily;
                const fmt = this._getFormatter();
                const makeLabel = (text, x, y, anchor) => {
                    const t = BrowserAPIs.createElementNS(SVG_NS, "text");
                    t.setAttribute("x", String(x));
                    t.setAttribute("y", String(y));
                    t.setAttribute("text-anchor", anchor);
                    t.setAttribute("dominant-baseline", "middle");
                    t.setAttribute("fill", labelColor);
                    t.setAttribute("font-size", labelFontSize);
                    if (labelFontFamily) t.setAttribute("font-family", labelFontFamily);
                    t.textContent = String(text);
                    return t;
                };
                if (isVertical) {
                    const midX = stripX + stripThickness / 2;
                    svg.appendChild(makeLabel(fmt(min), midX, stripY + stripLength + 10, "middle"));
                    svg.appendChild(makeLabel(fmt(max), midX, stripY - 10, "middle"));
                } else {
                    const midY = stripY + stripThickness / 2;
                    svg.appendChild(makeLabel(fmt(min), stripX - 6, midY, "end"));
                    svg.appendChild(makeLabel(fmt(max), stripX + stripLength + 6, midY, "start"));
                }
            }
            const arrowColor = ((_f = cfg.arrow) == null ? void 0 : _f.color) || w.config.chart.foreColor;
            const arrow = this._buildArrow(arrowSize, arrowColor, position);
            svg.appendChild(arrow);
            this.arrowEl = arrow;
            this._bandHitEls = [];
            if (w.config.legend.onItemHover.highlightDataSeries && bands.length > 0) {
                bands.forEach((b) => {
                    const hit = BrowserAPIs.createElementNS(SVG_NS, "rect");
                    if (isVertical) {
                        const yTop = stripY + stripLength - b.p2 * stripLength;
                        const yBot = stripY + stripLength - b.p1 * stripLength;
                        hit.setAttribute("x", String(stripX));
                        hit.setAttribute("y", String(yTop));
                        hit.setAttribute("width", String(stripThickness));
                        hit.setAttribute("height", String(Math.max(0, yBot - yTop)));
                    } else {
                        hit.setAttribute("x", String(stripX + b.p1 * stripLength));
                        hit.setAttribute("y", String(stripY));
                        hit.setAttribute(
                            "width",
                            String(Math.max(0, (b.p2 - b.p1) * stripLength))
                        );
                        hit.setAttribute("height", String(stripThickness));
                    }
                    hit.setAttribute("fill", "transparent");
                    hit.setAttribute("class", "apexcharts-heatmap-gradient-band");
                    hit.setAttribute("data:range-index", String(b.index));
                    hit.style.cursor = "pointer";
                    svg.appendChild(hit);
                    this._bandHitEls.push(hit);
                });
            }
            this._geom = {
                isVertical,
                position,
                stripX,
                stripY,
                stripLength,
                stripThickness,
                arrowSize,
                svgWidth,
                svgHeight
            };
            if (cfg.showHoverValue) {
                const tt = BrowserAPIs.createElement("div");
                tt.classList.add("apexcharts-heatmap-gradient-legend-value");
                tt.style.position = "absolute";
                tt.style.fontSize = ((_g = cfg.labelStyle) == null ? void 0 : _g.fontSize) || "11px";
                tt.style.fontFamily = ((_h = cfg.labelStyle) == null ? void 0 : _h.fontFamily) || w.config.chart.fontFamily || "";
                tt.style.color = w.config.chart.foreColor;
                tt.style.background = "rgba(0,0,0,0.65)";
                tt.style.color = "#fff";
                tt.style.padding = "2px 6px";
                tt.style.borderRadius = "3px";
                tt.style.pointerEvents = "none";
                tt.style.whiteSpace = "nowrap";
                tt.style.opacity = "0";
                tt.style.transition = "opacity 120ms ease";
                this.hoverValueEl = tt;
            }
            elLegendWrap.classList.add("apexcharts-heatmap-gradient-legend-wrap");
            elLegendWrap.classList.add(
                "apx-legend-position-" + position
            );
            elLegendWrap.appendChild(svg);
            if (this.hoverValueEl) elLegendWrap.appendChild(this.hoverValueEl);
            this.svgEl = svg;
            this._applyWrapAlignment(elLegendWrap, position, isVertical, svgWidth, svgHeight);
            this._attachHoverListeners();
            this._attachBandHoverListeners();
        }
        /**
         * Resolve a configured length (number = px, string ending in '%' =
         * percentage of the chart's SVG width/height) to a pixel length.
         * @param {number|string} value
         * @param {boolean} isVertical
         * @returns {number}
         */
        _resolveStripLength(value, isVertical) {
            const w = this.w;
            const basis = isVertical ? w.globals.svgHeight || w.config.chart.height || 300 : w.globals.svgWidth || w.config.chart.width || 600;
            if (typeof value === "string") {
                const trimmed = value.trim();
                if (trimmed.endsWith("%")) {
                    const pct = parseFloat(trimmed) || 0;
                    return Math.max(20, basis * pct / 100);
                }
                const n = parseFloat(trimmed);
                return Number.isFinite(n) ? n : 200;
            }
            if (typeof value === "number" && Number.isFinite(value)) return value;
            return 200;
        }
        /**
         * Position the legend wrap and align the gradient strip within it. The
         * wrap spans the chart's long axis (full width for top/bottom; full
         * height for left/right) and uses flexbox to honor the `align` config.
         * Bypasses the standard `setLegendWrapXY` which sizes the wrap to its
         * content.
         * @param {HTMLElement} elLegendWrap
         * @param {'top'|'right'|'bottom'|'left'} position
         * @param {boolean} isVertical
         * @param {number} svgWidth
         * @param {number} svgHeight
         */
        _applyWrapAlignment(elLegendWrap, position, isVertical, svgWidth, svgHeight) {
            const w = this.w;
            const cfg = w.config.plotOptions.heatmap.colorScale.gradientLegend;
            const align = cfg.align || "center";
            const edgePad = 12;
            const chartWidth = w.globals.svgWidth || w.config.chart.width || 600;
            const chartHeight = w.globals.svgHeight || w.config.chart.height || 300;
            const userOffsetX = w.config.legend.offsetX || 0;
            const userOffsetY = w.config.legend.offsetY || 0;
            elLegendWrap.style.position = "absolute";
            elLegendWrap.style.display = "block";
            elLegendWrap.style.overflow = "visible";
            elLegendWrap.style.padding = "0";
            elLegendWrap.style.width = svgWidth + "px";
            elLegendWrap.style.height = svgHeight + "px";
            elLegendWrap.style.right = "auto";
            elLegendWrap.style.bottom = "auto";
            if (isVertical) {
                const availableHeight = chartHeight - svgHeight - edgePad * 2;
                let y;
                if (align === "start") y = edgePad;
                else if (align === "end") y = edgePad + Math.max(0, availableHeight);
                else y = edgePad + Math.max(0, availableHeight) / 2;
                elLegendWrap.style.top = y + userOffsetY + "px";
                if (position === "left") {
                    elLegendWrap.style.left = edgePad + userOffsetX + "px";
                } else {
                    elLegendWrap.style.left = chartWidth - svgWidth - edgePad + userOffsetX + "px";
                }
            } else {
                const availableWidth = chartWidth - svgWidth - edgePad * 2;
                let x;
                if (align === "start") x = edgePad;
                else if (align === "end") x = edgePad + Math.max(0, availableWidth);
                else x = edgePad + Math.max(0, availableWidth) / 2;
                elLegendWrap.style.left = x + userOffsetX + "px";
                if (position === "top") {
                    elLegendWrap.style.top = edgePad + userOffsetY + "px";
                } else {
                    elLegendWrap.style.top = chartHeight - svgHeight - edgePad + userOffsetY + "px";
                }
            }
        }
        /**
         * Re-position the strip once the final layout is known.
         *
         * `_applyWrapAlignment` (called during `draw()`, before `plotCoords()`) can
         * only pin to the chart's outer edge. This runs after layout — when
         * `translateX/Y`, `gridWidth/Height` and `xAxisHeight` are populated — and:
         *   - centers the strip within its reserved band on the perpendicular axis
         *     (between the title and the plot for `top`; the x-axis and the chart
         *     bottom for `bottom`; the chart edge and the plot for `left`/`right`),
         *     so the slack is split evenly instead of dumped on one side, and
         *   - aligns it along the plot's own extent (so `align: 'center'` centers
         *     over the heatmap, not the whole canvas).
         * Honors `legend.offsetX/offsetY` for user nudging. Safe to call repeatedly.
         */
        repositionToPlot() {
            var _a, _b;
            if (!Environment.isBrowser()) return;
            const w = this.w;
            const g = w.globals;
            const wrap = (
                /** @type {HTMLElement} */
                w.dom.elLegendWrap
            );
            if (!wrap || !this._geom) return;
            if (!Number.isFinite(g.gridWidth) || !Number.isFinite(g.gridHeight)) return;
            const {
                isVertical,
                position,
                svgWidth,
                svgHeight,
                stripX,
                stripY,
                stripThickness
            } = this._geom;
            const align = w.config.plotOptions.heatmap.colorScale.gradientLegend.align || "center";
            const ox = w.config.legend.offsetX || 0;
            const oy = w.config.legend.offsetY || 0;
            const dimHelpers = (_b = (_a = this.ctx) == null ? void 0 : _a.dimensions) == null ? void 0 : _b.dimHelpers;
            const titleArea = dimHelpers ? dimHelpers.getTitleSubtitleCoords("title").height + dimHelpers.getTitleSubtitleCoords("subtitle").height : 0;
            const xAxisArea = w.layout.xAxisHeight || 0;
            const alongOffset = (extent, size) => {
                const avail = Math.max(0, extent - size);
                if (align === "start") return 0;
                if (align === "end") return avail;
                return avail / 2;
            };
            if (isVertical) {
                wrap.style.top = g.translateY + alongOffset(g.gridHeight, svgHeight) + oy + "px";
                const bandStart = position === "left" ? 0 : g.translateX + g.gridWidth;
                const bandEnd = position === "left" ? g.translateX : g.svgWidth;
                const stripCenter = (bandStart + bandEnd) / 2;
                wrap.style.left = stripCenter - stripX - stripThickness / 2 + ox + "px";
            } else {
                wrap.style.left = g.translateX + alongOffset(g.gridWidth, svgWidth) + ox + "px";
                const bandStart = position === "top" ? titleArea : g.translateY + g.gridHeight + xAxisArea;
                const bandEnd = position === "top" ? g.translateY : g.svgHeight;
                const stripCenter = (bandStart + bandEnd) / 2;
                wrap.style.top = stripCenter - stripY - stripThickness / 2 + oy + "px";
            }
            BrowserAPIs.requestAnimationFrame(() => this._enforceMinPlotGap());
        }
        /**
         * Guarantee a minimum gap between the strip's chart-facing edge and the plot.
         * Measured in viewport space (immune to the wrap↔SVG coordinate offset) and
         * applied as a *relative* shift to the wrap's current position, so it only
         * nudges a strip that ended up too close — placements with ample room are
         * left exactly where centering put them. Runs post-paint (see caller).
         */
        _enforceMinPlotGap() {
            const w = this.w;
            const wrap = (
                /** @type {HTMLElement} */
                w.dom.elLegendWrap
            );
            const strip = this.svgEl && this.svgEl.querySelector("rect");
            const grid = w.dom.baseEl.querySelector(".apexcharts-grid");
            if (!wrap || !strip || !grid || !this._geom) return;
            const s = strip.getBoundingClientRect();
            const gr = grid.getBoundingClientRect();
            if (!s.width || !s.height || !gr.width || !gr.height) return;
            const MIN_GAP = 16;
            const {
                isVertical,
                position
            } = this._geom;
            if (isVertical) {
                const gap = position === "left" ? gr.left - s.right : s.left - gr.right;
                if (gap < MIN_GAP) {
                    const curLeft = parseFloat(wrap.style.left) || 0;
                    const shift = MIN_GAP - gap;
                    wrap.style.left = curLeft + (position === "left" ? -shift : shift) + "px";
                }
            } else {
                const gap = position === "top" ? gr.top - s.bottom : s.top - gr.bottom;
                if (gap < MIN_GAP) {
                    const curTop = parseFloat(wrap.style.top) || 0;
                    const shift = MIN_GAP - gap;
                    wrap.style.top = curTop + (position === "top" ? -shift : shift) + "px";
                }
            }
        }
        /**
         * Tear down listeners (called before re-render).
         */
        destroy() {
            var _a, _b, _c, _d, _e, _f, _g;
            for (let i = 0; i < this._bandHitEls.length; i++) {
                const el = this._bandHitEls[i];
                (_a = el.removeEventListener) == null ? void 0 : _a.call(el, "mousemove", this._onBandEnter);
                (_b = el.removeEventListener) == null ? void 0 : _b.call(el, "mouseout", this._onBandLeave);
            }
            this._bandHitEls = [];
            this._activeBandIndex = -1;
            if (!((_c = this.ctx) == null ? void 0 : _c.events)) return;
            try {
                (_e = (_d = this.ctx.events).removeEventListener) == null ? void 0 : _e.call(
                    _d,
                    "dataPointMouseEnter",
                    this._onCellEnter
                );
                (_g = (_f = this.ctx.events).removeEventListener) == null ? void 0 : _g.call(
                    _f,
                    "dataPointMouseLeave",
                    this._onCellLeave
                );
            } catch (_) {}
        }
        /** Wire mousemove/mouseout on each per-band hit-region (ranges mode). */
        _attachBandHoverListeners() {
            if (!Environment.isBrowser()) return;
            for (let i = 0; i < this._bandHitEls.length; i++) {
                const el = this._bandHitEls[i];
                el.addEventListener("mousemove", this._onBandEnter);
                el.addEventListener("mouseout", this._onBandLeave);
            }
        }
        /**
         * Hovering a gradient band highlights its cells and dims the rest. Guarded
         * so the repeated mousemove stream only re-applies on an actual band change.
         * @param {Event} e
         */
        _onBandEnter(e) {
            var _a, _b, _c, _d;
            const w = this.w;
            const target = (
                /** @type {Element} */
                e.currentTarget
            );
            const idx = parseInt((_a = target.getAttribute("data:range-index")) != null ? _a : "-1", 10);
            if (idx < 0 || idx === this._activeBandIndex) return;
            this._activeBandIndex = idx;
            (_d = (_c = (_b = this.ctx) == null ? void 0 : _b.events) == null ? void 0 : _c.fireEvent) == null ? void 0 : _d.call(_c, "legendHover", [this.ctx, idx, w]);
            new Series(w).highlightRangeInSeries(idx, "highlight");
        }
        /** Leaving a band clears the highlight. */
        _onBandLeave() {
            if (this._activeBandIndex < 0) return;
            const idx = this._activeBandIndex;
            this._activeBandIndex = -1;
            new Series(this.w).highlightRangeInSeries(idx, "reset");
        }
        _attachHoverListeners() {
            var _a, _b;
            if (!Environment.isBrowser()) return;
            if (!((_b = (_a = this.ctx) == null ? void 0 : _a.events) == null ? void 0 : _b.addEventListener)) return;
            this.ctx.events.addEventListener(
                "dataPointMouseEnter",
                this._onCellEnter
            );
            this.ctx.events.addEventListener(
                "dataPointMouseLeave",
                this._onCellLeave
            );
        }
        /**
         * dataPointMouseEnter fires as `(e, ctx, { seriesIndex, dataPointIndex, w })`.
         * Graphics._fireEvent forwards listener args in the same shape.
         * @param {...any} args
         */
        _onCellEnter(...args) {
            var _a, _b;
            const w = this.w;
            if (!this.arrowEl) return;
            const opts = args[args.length - 1];
            if (!opts || typeof opts !== "object") return;
            const i = opts.seriesIndex;
            const j = opts.dataPointIndex;
            if (typeof i !== "number" || typeof j !== "number") return;
            if (w.config.chart.type !== "heatmap") return;
            const row = (_b = (_a = w.seriesData) == null ? void 0 : _a.series) == null ? void 0 : _b[i];
            const val = row == null ? void 0 : row[j];
            if (val == null || Number.isNaN(val)) return;
            this._positionArrow(val);
        }
        _onCellLeave() {
            if (!this.arrowEl) return;
            this.arrowEl.setAttribute("opacity", "0");
            if (this.hoverValueEl) {
                this.hoverValueEl.style.opacity = "0";
            }
        }
        /**
         * Move the arrow to the position corresponding to `val` along the strip.
         * @param {number} val
         */
        _positionArrow(val) {
            if (!this.arrowEl || !this._geom) return;
            const {
                isVertical,
                position,
                stripX,
                stripY,
                stripLength,
                stripThickness,
                arrowSize
            } = this._geom;
            const min = this._min;
            const max = this._max;
            const span = max - min;
            let pct;
            if (span === 0) {
                pct = 0.5;
            } else {
                pct = (val - min) / span;
            }
            if (pct < 0) pct = 0;
            if (pct > 1) pct = 1;
            if (isVertical) {
                const yCenter = stripY + stripLength - pct * stripLength;
                let tipX, baseX;
                if (position === "left") {
                    tipX = stripX + stripThickness;
                    baseX = tipX + arrowSize;
                } else {
                    tipX = stripX;
                    baseX = tipX - arrowSize;
                }
                const points = [
                    `${tipX},${yCenter}`,
                    `${baseX},${yCenter - arrowSize / 2}`,
                    `${baseX},${yCenter + arrowSize / 2}`
                ].join(" ");
                this.arrowEl.setAttribute("points", points);
            } else {
                const xCenter = stripX + pct * stripLength;
                let tipY, baseY;
                if (position === "top") {
                    tipY = stripY + stripThickness;
                    baseY = tipY + arrowSize;
                } else {
                    tipY = stripY;
                    baseY = tipY - arrowSize;
                }
                const points = [
                    `${xCenter},${tipY}`,
                    `${xCenter - arrowSize / 2},${baseY}`,
                    `${xCenter + arrowSize / 2},${baseY}`
                ].join(" ");
                this.arrowEl.setAttribute("points", points);
            }
            this.arrowEl.setAttribute("opacity", "1");
            if (this.hoverValueEl) {
                const fmt = this._getFormatter();
                this.hoverValueEl.textContent = fmt(val);
                if (isVertical) {
                    const yCenter = stripY + stripLength - pct * stripLength;
                    if (position === "left") {
                        this.hoverValueEl.style.left = `${stripX + stripThickness + arrowSize + 8}px`;
                    } else {
                        this.hoverValueEl.style.left = `${stripX - arrowSize - 8}px`;
                        this.hoverValueEl.style.transform = "translateX(-100%)";
                    }
                    this.hoverValueEl.style.top = `${yCenter - 9}px`;
                } else {
                    const xCenter = stripX + pct * stripLength;
                    this.hoverValueEl.style.left = `${xCenter}px`;
                    this.hoverValueEl.style.transform = "translateX(-50%)";
                    if (position === "top") {
                        this.hoverValueEl.style.top = `${stripY + stripThickness + arrowSize + 8}px`;
                    } else {
                        this.hoverValueEl.style.top = `${stripY - arrowSize - 18}px`;
                    }
                }
                this.hoverValueEl.style.opacity = "1";
            }
        }
        /**
         * @param {number} size
         * @param {string} color
         * @param {'top'|'right'|'bottom'|'left'} _position
         */
        _buildArrow(size, color, _position) {
            const polygon = BrowserAPIs.createElementNS(SVG_NS, "polygon");
            polygon.setAttribute("fill", color);
            polygon.setAttribute("opacity", "0");
            polygon.setAttribute("class", "apexcharts-heatmap-gradient-arrow");
            polygon.setAttribute("points", "0,0 0,0 0,0");
            polygon.setAttribute("pointer-events", "none");
            return polygon;
        }
        /**
         * Build gradient stops + return effective min/max.
         * - If `colorScale.ranges` is set, stops are placed at each range boundary
         *   so the gradient reflects the user's discrete palette.
         * - Otherwise, samples N stops from the same shadeColor function the cells
         *   use, so the strip visually matches the heatmap.
         * @returns {{ min: number, max: number, stops: Array<{percent:number,color:string}>, bands: Array<{index:number,p1:number,p2:number}> }}
         */
        _computeStops() {
            var _a, _b;
            const w = this.w;
            const cs = w.config.plotOptions.heatmap.colorScale;
            const cfg = cs.gradientLegend;
            let dataMin = Infinity;
            let dataMax = -Infinity;
            const rows = ((_a = w.seriesData) == null ? void 0 : _a.series) || [];
            for (let i = 0; i < rows.length; i++) {
                const row = rows[i];
                if (!row) continue;
                for (let j = 0; j < row.length; j++) {
                    const v = row[j];
                    if (v == null || Number.isNaN(v)) continue;
                    if (v < dataMin) dataMin = v;
                    if (v > dataMax) dataMax = v;
                }
            }
            if (!Number.isFinite(dataMin)) dataMin = 0;
            if (!Number.isFinite(dataMax)) dataMax = 0;
            let min = dataMin;
            let max = dataMax;
            if (typeof cs.min !== "undefined") {
                min = cs.min < dataMin ? cs.min : dataMin;
            }
            if (typeof cs.max !== "undefined") {
                max = cs.max > dataMax ? cs.max : dataMax;
            }
            const stops = [];
            const bands = [];
            if (cs.ranges && cs.ranges.length > 0) {
                const ranges = cs.ranges.map((r, originalIndex) => __spreadProps(__spreadValues({}, r), {
                    _originalIndex: originalIndex
                })).sort((a, b) => a.from - b.from);
                const lo = ranges[0].from;
                const hi = ranges[ranges.length - 1].to;
                min = lo;
                max = hi;
                const span = hi - lo || 1;
                ranges.forEach((r) => {
                    const p1 = (r.from - lo) / span;
                    const p2 = (r.to - lo) / span;
                    stops.push({
                        percent: (p1 + p2) / 2,
                        color: r.color
                    });
                    bands.push({
                        index: r._originalIndex,
                        p1,
                        p2
                    });
                });
            } else {
                const baseColor = w.globals.colors[0] || "#008FFB";
                const utils = new Utils$1();
                const shadeIntensity = (_b = w.config.plotOptions.heatmap.shadeIntensity) != null ? _b : 0.5;
                const hasNegs = (
                    /** @type {any} */
                    w.globals.hasNegs
                );
                const n = Math.max(2, cfg.stops || 16);
                for (let s = 0; s < n; s++) {
                    const t = s / (n - 1);
                    const v = min + t * (max - min);
                    const total = Math.abs(max) + Math.abs(min);
                    const percent_v = total === 0 ? 0 : 100 * v / total;
                    let colorShadePercent;
                    if (hasNegs) {
                        if (w.config.plotOptions.heatmap.reverseNegativeShade) {
                            colorShadePercent = percent_v < 0 ? percent_v / 100 * (shadeIntensity * 1.25) : (1 - percent_v / 100) * (shadeIntensity * 1.25);
                        } else {
                            colorShadePercent = percent_v <= 0 ? 1 - (1 + percent_v / 100) * shadeIntensity : (1 - percent_v / 100) * shadeIntensity;
                        }
                    } else {
                        colorShadePercent = 1 - percent_v / 100;
                    }
                    if (colorShadePercent > 1) colorShadePercent = 1;
                    if (colorShadePercent < -1) colorShadePercent = -1;
                    const shaded = w.config.plotOptions.heatmap.enableShades ? utils.shadeColor(
                        w.config.theme.mode === "dark" ? colorShadePercent * -1 : colorShadePercent,
                        baseColor
                    ) : baseColor;
                    stops.push({
                        percent: t,
                        color: shaded
                    });
                }
            }
            return {
                min,
                max,
                stops,
                bands
            };
        }
    }
    class Legend {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {import('../../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this.printDataLabelsInner = (...a) => {
                var _a;
                return (_a = ctx.pie) == null ? void 0 : _a.printDataLabelsInner(...a);
            };
            this.updateSeries = (...a) => ctx.updateHelpers._updateSeries(...a);
            this.onLegendClick = this.onLegendClick.bind(this);
            this.onLegendHovered = this.onLegendHovered.bind(this);
            this.isBarsDistributed = this.w.config.chart.type === "bar" && this.w.config.plotOptions.bar.distributed && this.w.config.series.length === 1;
            this.legendHelpers = new Helpers$3(this);
        }
        init() {
            const w = this.w;
            const gl = w.globals;
            const cnf = w.config;
            const showLegendAlways = cnf.legend.showForSingleSeries && this.w.seriesData.series.length === 1 || this.isBarsDistributed || // Heatmap legends are colorScale-driven (discrete ranges or the
                // gradient strip), not series-driven, so they must render even for a
                // single-row heatmap.
                cnf.chart.type === "heatmap" || this.w.seriesData.series.length > 1;
            this.legendHelpers.appendToForeignObject();
            if ((showLegendAlways || !gl.axisCharts) && cnf.legend.show) {
                const elLegendWrap = (
                    /** @type {HTMLElement} */
                    w.dom.elLegendWrap
                );
                while (elLegendWrap.firstChild) {
                    elLegendWrap.removeChild(elLegendWrap.firstChild);
                }
                if (this.heatmapGradientLegend) {
                    this.heatmapGradientLegend.destroy();
                    this.heatmapGradientLegend = null;
                }
                if (cnf.chart.type === "heatmap" && HeatmapGradientLegend.isEnabled(w)) {
                    this.heatmapGradientLegend = new HeatmapGradientLegend(w, this.ctx);
                    this.heatmapGradientLegend.draw();
                } else {
                    this.drawLegends();
                    if (cnf.legend.position === "bottom" || cnf.legend.position === "top") {
                        this.legendAlignHorizontal();
                    } else if (cnf.legend.position === "right" || cnf.legend.position === "left") {
                        this.legendAlignVertical();
                    }
                }
            }
        }
        createLegendMarker({
            i,
            fillcolor
        }) {
            const w = this.w;
            const elMarker = BrowserAPIs.createElement("span");
            elMarker.classList.add("apexcharts-legend-marker");
            const mShape = w.config.legend.markers.shape || w.config.markers.shape;
            let shape = mShape;
            if (Array.isArray(mShape)) {
                shape = mShape[i];
            }
            const mSize = Array.isArray(w.config.legend.markers.size) ? parseFloat(w.config.legend.markers.size[i]) : parseFloat(w.config.legend.markers.size);
            const mOffsetX = Array.isArray(w.config.legend.markers.offsetX) ? parseFloat(w.config.legend.markers.offsetX[i]) : parseFloat(w.config.legend.markers.offsetX);
            const mOffsetY = Array.isArray(w.config.legend.markers.offsetY) ? parseFloat(w.config.legend.markers.offsetY[i]) : parseFloat(w.config.legend.markers.offsetY);
            const mBorderWidth = Array.isArray(w.config.legend.markers.strokeWidth) ? parseFloat(w.config.legend.markers.strokeWidth[i]) : parseFloat(w.config.legend.markers.strokeWidth);
            const mStyle = elMarker.style;
            mStyle.height = (mSize + mBorderWidth) * 2 + "px";
            mStyle.width = (mSize + mBorderWidth) * 2 + "px";
            mStyle.left = mOffsetX + "px";
            mStyle.top = mOffsetY + "px";
            if (w.config.legend.markers.customHTML) {
                mStyle.background = "transparent";
                mStyle.color = fillcolor[i];
                if (Array.isArray(w.config.legend.markers.customHTML)) {
                    if (w.config.legend.markers.customHTML[i]) {
                        elMarker.innerHTML = w.config.legend.markers.customHTML[i]();
                    }
                } else {
                    elMarker.innerHTML = w.config.legend.markers.customHTML();
                }
            } else {
                const markers = new Markers(this.ctx.w, this.ctx);
                const markerConfig = markers.getMarkerConfig({
                    cssClass: `apexcharts-legend-marker apexcharts-marker apexcharts-marker-${shape}`,
                    seriesIndex: i,
                    strokeWidth: mBorderWidth,
                    size: mSize
                });
                const SVGLib = Environment.isBrowser() ? (
                    /** @type {any} */
                    window.SVG
                ) : (
                    /** @type {any} */
                    global.SVG
                );
                const SVGMarker = SVGLib().addTo(elMarker).size("100%", "100%");
                const marker = new Graphics(this.w).drawMarker(0, 0, __spreadProps(__spreadValues({}, markerConfig), {
                    pointFillColor: Array.isArray(fillcolor) ? fillcolor[i] : markerConfig.pointFillColor,
                    shape
                }));
                const shapesEls = w.dom.Paper.find(
                    ".apexcharts-legend-marker.apexcharts-marker"
                );
                shapesEls.forEach((shapeEl) => {
                    if (shapeEl.node.classList.contains("apexcharts-marker-triangle")) {
                        shapeEl.node.style.transform = "translate(50%, 45%)";
                    } else {
                        shapeEl.node.style.transform = "translate(50%, 50%)";
                    }
                });
                SVGMarker.add(marker);
            }
            return elMarker;
        }
        drawLegends() {
            var _a;
            const me = this;
            const w = this.w;
            const elLegendWrap = (
                /** @type {HTMLElement} */
                w.dom.elLegendWrap
            );
            const fontFamily = w.config.legend.fontFamily;
            let legendNames = w.seriesData.seriesNames;
            let fillcolor = w.config.legend.markers.fillColors ? w.config.legend.markers.fillColors.slice() : w.globals.colors.slice();
            if (w.config.chart.type === "heatmap") {
                const ranges = w.config.plotOptions.heatmap.colorScale.ranges;
                legendNames = ranges.map((colorScale) => {
                    return colorScale.name ? colorScale.name : colorScale.from + " - " + colorScale.to;
                });
                fillcolor = ranges.map((color) => color.color);
            } else if (this.isBarsDistributed) {
                legendNames = w.labelData.labels.slice();
            }
            if (w.config.legend.customLegendItems.length) {
                legendNames = w.config.legend.customLegendItems;
            }
            const legendFormatter = w.formatters.legendFormatter;
            const isLegendInversed = w.config.legend.inverseOrder;
            const legendGroups = [];
            if (w.labelData.seriesGroups.length > 1 && w.config.legend.clusterGroupedSeries) {
                w.labelData.seriesGroups.forEach((_, gi) => {
                    legendGroups[gi] = BrowserAPIs.createElement("div");
                    legendGroups[gi].classList.add(
                        "apexcharts-legend-group",
                        `apexcharts-legend-group-${gi}`
                    );
                    if (w.config.legend.clusterGroupedSeriesOrientation === "horizontal") {
                        elLegendWrap.classList.add("apexcharts-legend-group-horizontal");
                    } else {
                        legendGroups[gi].classList.add("apexcharts-legend-group-vertical");
                    }
                });
            }
            for (let i = isLegendInversed ? legendNames.length - 1 : 0; isLegendInversed ? i >= 0 : i <= legendNames.length - 1; isLegendInversed ? i-- : i++) {
                const text = legendFormatter(legendNames[i], {
                    seriesIndex: i,
                    w
                });
                let collapsedSeries = false;
                let ancillaryCollapsedSeries = false;
                if (w.globals.collapsedSeries.length > 0) {
                    for (let c = 0; c < w.globals.collapsedSeries.length; c++) {
                        if (w.globals.collapsedSeries[c].index === i) {
                            collapsedSeries = true;
                        }
                    }
                }
                if (w.globals.ancillaryCollapsedSeriesIndices.length > 0) {
                    for (let c = 0; c < w.globals.ancillaryCollapsedSeriesIndices.length; c++) {
                        if (w.globals.ancillaryCollapsedSeriesIndices[c] === i) {
                            ancillaryCollapsedSeries = true;
                        }
                    }
                }
                const elMarker = this.createLegendMarker({
                    i,
                    fillcolor
                });
                Graphics.setAttrs(elMarker, {
                    rel: i + 1,
                    "data:collapsed": collapsedSeries || ancillaryCollapsedSeries
                });
                if (collapsedSeries || ancillaryCollapsedSeries) {
                    elMarker.classList.add("apexcharts-inactive-legend");
                }
                const elLegend = BrowserAPIs.createElement("div");
                if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.keyboard.enabled) {
                    elLegend.setAttribute("role", "button");
                    elLegend.setAttribute("tabindex", "0");
                    const seriesName = Array.isArray(text) ? text.join(" ") : text;
                    const isCollapsed = collapsedSeries || ancillaryCollapsedSeries;
                    const statusText = isCollapsed ? "hidden" : "visible";
                    elLegend.setAttribute(
                        "aria-label",
                        `${seriesName}, ${statusText}. Press Enter or Space to toggle.`
                    );
                    elLegend.setAttribute("aria-pressed", isCollapsed ? "true" : "false");
                }
                const elLegendText = BrowserAPIs.createElement("span");
                elLegendText.classList.add("apexcharts-legend-text");
                elLegendText.innerHTML = Array.isArray(text) ? text.join(" ") : text;
                let textColor = w.config.legend.labels.useSeriesColors ? w.globals.colors[i] : Array.isArray(w.config.legend.labels.colors) ? (_a = w.config.legend.labels.colors) == null ? void 0 : _a[i] : w.config.legend.labels.colors;
                if (!textColor) {
                    textColor = w.config.chart.foreColor;
                }
                elLegendText.style.color = textColor;
                elLegendText.style.fontSize = w.config.legend.fontSize;
                elLegendText.style.fontWeight = w.config.legend.fontWeight;
                elLegendText.style.fontFamily = fontFamily || w.config.chart.fontFamily;
                Graphics.setAttrs(elLegendText, {
                    rel: i + 1,
                    i,
                    "data:default-text": encodeURIComponent(text),
                    "data:collapsed": collapsedSeries || ancillaryCollapsedSeries
                });
                elLegend.appendChild(elMarker);
                elLegend.appendChild(elLegendText);
                const coreUtils = new CoreUtils(this.w);
                if (!w.config.legend.showForZeroSeries) {
                    const total = coreUtils.getSeriesTotalByIndex(i);
                    if (total === 0 && coreUtils.seriesHaveSameValues(i) && !coreUtils.isSeriesNull(i) && w.globals.collapsedSeriesIndices.indexOf(i) === -1 && w.globals.ancillaryCollapsedSeriesIndices.indexOf(i) === -1) {
                        elLegend.classList.add("apexcharts-hidden-zero-series");
                    }
                }
                if (!w.config.legend.showForNullSeries) {
                    if (coreUtils.isSeriesNull(i) && w.globals.collapsedSeriesIndices.indexOf(i) === -1 && w.globals.ancillaryCollapsedSeriesIndices.indexOf(i) === -1) {
                        elLegend.classList.add("apexcharts-hidden-null-series");
                    }
                }
                if (legendGroups.length) {
                    w.labelData.seriesGroups.forEach((group, gi) => {
                        var _a2, _b;
                        if (group.includes(
                                /** @type {Record<string,any>} */
                                (_b = (_a2 = w.config.series[i]) == null ? void 0 : _a2.name) != null ? _b : ""
                            )) {
                            elLegendWrap.appendChild(legendGroups[gi]);
                            legendGroups[gi].appendChild(elLegend);
                        }
                    });
                } else {
                    elLegendWrap.appendChild(elLegend);
                }
                elLegendWrap.classList.add(
                    `apexcharts-align-${w.config.legend.horizontalAlign}`
                );
                elLegendWrap.classList.add(
                    "apx-legend-position-" + w.config.legend.position
                );
                elLegend.classList.add("apexcharts-legend-series");
                elLegend.style.margin = `${w.config.legend.itemMargin.vertical}px ${w.config.legend.itemMargin.horizontal}px`;
                elLegendWrap.style.width = w.config.legend.width ? w.config.legend.width + "px" : "";
                elLegendWrap.style.height = w.config.legend.height ? w.config.legend.height + "px" : "";
                Graphics.setAttrs(elLegend, {
                    rel: i + 1,
                    seriesName: Utils$1.escapeString(legendNames[i]),
                    "data:collapsed": collapsedSeries || ancillaryCollapsedSeries
                });
                if (collapsedSeries || ancillaryCollapsedSeries) {
                    elLegend.classList.add("apexcharts-inactive-legend");
                }
                if (!w.config.legend.onItemClick.toggleDataSeries) {
                    elLegend.classList.add("apexcharts-no-click");
                }
            }
            w.dom.elWrap.addEventListener("click", me.onLegendClick, true);
            if (w.config.legend.onItemHover.highlightDataSeries && w.config.legend.customLegendItems.length === 0) {
                w.dom.elWrap.addEventListener("mousemove", me.onLegendHovered, true);
                w.dom.elWrap.addEventListener("mouseout", me.onLegendHovered, true);
            }
            if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.keyboard.enabled) {
                w.dom.elWrap.addEventListener(
                    "keydown",
                    me.onLegendKeyDown.bind(me),
                    true
                );
            }
        }
        /**
         * @param {number} offsetX
         * @param {number} offsetY
         */
        setLegendWrapXY(offsetX, offsetY) {
            const w = this.w;
            const elLegendWrap = (
                /** @type {HTMLElement} */
                w.dom.elLegendWrap
            );
            const legendHeight = elLegendWrap.clientHeight;
            let x = 0;
            let y = 0;
            if (w.config.legend.position === "bottom") {
                y = w.globals.svgHeight - Math.min(legendHeight, w.globals.svgHeight / 2) - 5;
            } else if (w.config.legend.position === "top") {
                const dim = new Dimensions(this.w, this.ctx);
                const titleH = dim.dimHelpers.getTitleSubtitleCoords("title").height;
                const subtitleH = dim.dimHelpers.getTitleSubtitleCoords("subtitle").height;
                y = (titleH > 0 ? titleH - 10 : 0) + (subtitleH > 0 ? subtitleH - 10 : 0);
            }
            elLegendWrap.style.position = "absolute";
            x = x + offsetX + w.config.legend.offsetX;
            y = y + offsetY + w.config.legend.offsetY;
            elLegendWrap.style.left = x + "px";
            elLegendWrap.style.top = y + "px";
            if (w.config.legend.position === "right") {
                elLegendWrap.style.left = "auto";
                elLegendWrap.style.right = 25 + w.config.legend.offsetX + "px";
            }
            const fixedHeigthWidth = (
                /** @type {const} */
                ["width", "height"]
            );
            fixedHeigthWidth.forEach((hw) => {
                if (elLegendWrap && elLegendWrap.style[hw]) {
                    elLegendWrap.style[hw] = parseInt(String(w.config.legend[hw]), 10) + "px";
                }
            });
        }
        legendAlignHorizontal() {
            const w = this.w;
            const elLegendWrap = (
                /** @type {HTMLElement} */
                w.dom.elLegendWrap
            );
            elLegendWrap.style.right = "0";
            const dimensions = new Dimensions(this.w, this.ctx);
            const titleRect = dimensions.dimHelpers.getTitleSubtitleCoords("title");
            const subtitleRect = dimensions.dimHelpers.getTitleSubtitleCoords("subtitle");
            const offsetX = 20;
            let offsetY = 0;
            if (w.config.legend.position === "top") {
                offsetY = titleRect.height + subtitleRect.height + w.config.title.margin + w.config.subtitle.margin - 10;
            }
            this.setLegendWrapXY(offsetX, offsetY);
        }
        legendAlignVertical() {
            const w = this.w;
            const lRect = this.legendHelpers.getLegendDimensions();
            const offsetY = 20;
            let offsetX = 0;
            if (w.config.legend.position === "left") {
                offsetX = 20;
            }
            if (w.config.legend.position === "right") {
                offsetX = w.globals.svgWidth - lRect.clww - 10;
            }
            this.setLegendWrapXY(offsetX, offsetY);
        }
        /**
         * @param {MouseEvent} e
         */
        onLegendHovered(e) {
            var _a;
            const w = this.w;
            const target = (
                /** @type {Element} */
                e.target
            );
            const hoverOverLegend = target.classList.contains("apexcharts-legend-series") || target.classList.contains("apexcharts-legend-text") || target.classList.contains("apexcharts-legend-marker");
            if (w.config.chart.type !== "heatmap" && !this.isBarsDistributed) {
                if (!target.classList.contains("apexcharts-inactive-legend") && hoverOverLegend) {
                    const series = new Series(this.ctx.w);
                    series.toggleSeriesOnHover(e, target);
                }
            } else {
                if (hoverOverLegend) {
                    const seriesCnt = parseInt((_a = target.getAttribute("rel")) != null ? _a : "0", 10) - 1;
                    this.ctx.events.fireEvent("legendHover", [this.ctx, seriesCnt, this.w]);
                    const series = new Series(this.ctx.w);
                    if (e.type === "mousemove") {
                        series.highlightRangeInSeries(seriesCnt, "highlight");
                    } else if (e.type === "mouseout") {
                        series.highlightRangeInSeries(seriesCnt, "reset");
                    }
                }
            }
        }
        /**
         * @param {KeyboardEvent} e
         */
        onLegendKeyDown(e) {
            const me = this;
            const w = this.w;
            const target = (
                /** @type {Element} */
                e.target
            );
            const isLegendItem = target.classList.contains("apexcharts-legend-series") || target.classList.contains("apexcharts-legend-text") || target.classList.contains("apexcharts-legend-marker");
            if (!isLegendItem) return;
            if (e.key === "Enter" || e.key === " ") {
                e.preventDefault();
                const rel = target.getAttribute("rel");
                me.onLegendClick(e);
                if (rel !== null && w.config.legend.onItemClick.toggleDataSeries) {
                    requestAnimationFrame(() => {
                        const restored = w.dom.baseEl.querySelector(
                            `.apexcharts-legend-series[rel="${rel}"]`
                        );
                        if (restored) restored.focus();
                    });
                }
            }
        }
        /**
         * @param {Event} e
         */
        onLegendClick(e) {
            var _a;
            const w = this.w;
            const target = (
                /** @type {Element} */
                e.target
            );
            if (w.config.legend.customLegendItems.length) return;
            if (target.classList.contains("apexcharts-legend-series") || target.classList.contains("apexcharts-legend-text") || target.classList.contains("apexcharts-legend-marker")) {
                const seriesCnt = parseInt((_a = target.getAttribute("rel")) != null ? _a : "0", 10) - 1;
                const isHidden = target.getAttribute("data:collapsed") === "true";
                const legendClick = this.w.config.chart.events.legendClick;
                if (typeof legendClick === "function") {
                    legendClick(this.ctx, seriesCnt, this.w);
                }
                this.ctx.events.fireEvent("legendClick", [this.ctx, seriesCnt, this.w]);
                const markerClick = this.w.config.legend.markers.onClick;
                if (typeof markerClick === "function" && target.classList.contains("apexcharts-legend-marker")) {
                    markerClick(this.ctx, seriesCnt, this.w);
                    this.ctx.events.fireEvent("legendMarkerClick", [
                        this.ctx,
                        seriesCnt,
                        this.w
                    ]);
                }
                const clickAllowed = w.config.chart.type !== "treemap" && w.config.chart.type !== "heatmap" && !this.isBarsDistributed;
                if (clickAllowed && w.config.legend.onItemClick.toggleDataSeries) {
                    this.legendHelpers.toggleDataSeries(seriesCnt, isHidden);
                }
            }
        }
    }
    ApexCharts.registerFeatures({
        legend: Legend
    });
    const icoPan = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n    <path d="M5 9 2 12l3 3"/>\n    <path d="M9 5l3-3 3 3"/>\n    <path d="M15 19l-3 3-3-3"/>\n    <path d="M19 9l3 3-3 3"/>\n    <path d="M2 12h20"/>\n    <path d="M12 2v20"/>\n</svg>\n';
    const icoZoom = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n    <circle cx="11" cy="11" r="7"/>\n    <path d="m21 21-4.3-4.3M8 11h6M11 8v6"/>\n</svg>\n';
    const icoReset = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n    <path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"/>\n    <path d="M3 3v5h5"/>\n</svg>\n';
    const icoZoomIn = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n    <path d="M12 5v14M5 12h14"/>\n</svg>\n';
    const icoZoomOut = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n    <path d="M5 12h14"/>\n</svg>\n';
    const icoSelect = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n    <path d="M5 3a2 2 0 0 0-2 2"/>\n    <path d="M19 3a2 2 0 0 1 2 2"/>\n    <path d="M21 19a2 2 0 0 1-2 2"/>\n    <path d="M5 21a2 2 0 0 1-2-2"/>\n    <path d="M9 3h1M14 3h1M9 21h1M14 21h1M3 9v1M3 14v1M21 9v1M21 14v1"/>\n</svg>\n';
    const icoMenu = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">\n    <path d="M4 6h16M4 12h16M4 18h16"/>\n</svg>\n';
    class Toolbar {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this.ev = this.w.config.chart.events;
            this.selectedClass = "apexcharts-selected";
            this.localeValues = this.w.globals.locale.toolbar;
            this.minX = w.globals.minX;
            this.maxX = w.globals.maxX;
            this.elZoom = null;
            this.elZoomIn = null;
            this.elZoomOut = null;
            this.elPan = null;
            this.elSelection = null;
            this.elZoomReset = null;
            this.elMenuIcon = null;
            this.elMenu = null;
            this.elMenuItems = [];
            this.t = null;
        }
        createToolbar() {
            const w = this.w;
            const createDiv = () => {
                return BrowserAPIs.createElementNS("http://www.w3.org/1999/xhtml", "div");
            };
            const createBtn = () => {
                const btn = (
                    /** @type {HTMLButtonElement} */
                    BrowserAPIs.createElementNS("http://www.w3.org/1999/xhtml", "button")
                );
                btn.setAttribute("type", "button");
                return btn;
            };
            const elToolbarWrap = createDiv();
            elToolbarWrap.setAttribute("class", "apexcharts-toolbar");
            elToolbarWrap.style.top = w.config.chart.toolbar.offsetY + "px";
            elToolbarWrap.style.right = -w.config.chart.toolbar.offsetX + 3 + "px";
            w.dom.elWrap.appendChild(elToolbarWrap);
            this.elZoom = createBtn();
            this.elZoomIn = createBtn();
            this.elZoomOut = createBtn();
            this.elPan = createBtn();
            this.elSelection = createBtn();
            this.elZoomReset = createBtn();
            this.elMenuIcon = createBtn();
            this.elMenu = createDiv();
            this.elCustomIcons = [];
            this.t = w.config.chart.toolbar.tools;
            if (Array.isArray(this.t.customIcons)) {
                for (let i = 0; i < this.t.customIcons.length; i++) {
                    this.elCustomIcons.push(createBtn());
                }
            }
            const toolbarControls = [];
            const appendZoomControl = (type, el, ico) => {
                const tool = type.toLowerCase();
                if (this.t[tool] && w.config.chart.zoom.enabled) {
                    toolbarControls.push({
                        el,
                        icon: typeof this.t[tool] === "string" ? this.t[tool] : ico,
                        title: (
                            /** @type {any} */
                            this.localeValues[type]
                        ),
                        class: `apexcharts-${tool}-icon`
                    });
                }
            };
            appendZoomControl("zoomIn", this.elZoomIn, icoZoomIn);
            appendZoomControl("zoomOut", this.elZoomOut, icoZoomOut);
            const zoomSelectionCtrls = (z) => {
                if (this.t[z] && w.config.chart[z].enabled) {
                    toolbarControls.push({
                        el: z === "zoom" ? this.elZoom : this.elSelection,
                        icon: typeof this.t[z] === "string" ? this.t[z] : z === "zoom" ? icoZoom : icoSelect,
                        title: (
                            /** @type {any} */
                            this.localeValues[z === "zoom" ? "selectionZoom" : "selection"]
                        ),
                        class: `apexcharts-${z}-icon`
                    });
                }
            };
            zoomSelectionCtrls("zoom");
            zoomSelectionCtrls("selection");
            if (this.t.pan && w.config.chart.zoom.enabled) {
                toolbarControls.push({
                    el: this.elPan,
                    icon: typeof this.t.pan === "string" ? this.t.pan : icoPan,
                    title: this.localeValues.pan,
                    class: "apexcharts-pan-icon"
                });
            }
            appendZoomControl("reset", this.elZoomReset, icoReset);
            if (this.t.download) {
                toolbarControls.push({
                    el: this.elMenuIcon,
                    icon: typeof this.t.download === "string" ? this.t.download : icoMenu,
                    title: this.localeValues.menu,
                    class: "apexcharts-menu-icon"
                });
            }
            for (let i = 0; i < this.elCustomIcons.length; i++) {
                toolbarControls.push({
                    el: this.elCustomIcons[i],
                    icon: this.t.customIcons[i].icon,
                    title: this.t.customIcons[i].title,
                    index: this.t.customIcons[i].index,
                    class: "apexcharts-toolbar-custom-icon " + this.t.customIcons[i].class
                });
            }
            toolbarControls.forEach((t, index) => {
                if (t.index) {
                    Utils$1.moveIndexInArray(toolbarControls, index, t.index);
                }
            });
            for (let i = 0; i < toolbarControls.length; i++) {
                Graphics.setAttrs(toolbarControls[i].el, {
                    class: toolbarControls[i].class,
                    title: toolbarControls[i].title,
                    "aria-label": toolbarControls[i].title
                });
                toolbarControls[i].el.innerHTML = toolbarControls[i].icon;
                elToolbarWrap.appendChild(toolbarControls[i].el);
            }
            if (this.elZoom.parentNode) {
                this.elZoom.setAttribute("aria-pressed", String(!!w.interact.zoomEnabled));
            }
            if (this.elSelection.parentNode) {
                this.elSelection.setAttribute(
                    "aria-pressed",
                    String(!!w.interact.selectionEnabled)
                );
            }
            if (this.elPan.parentNode) {
                this.elPan.setAttribute("aria-pressed", String(!!w.interact.panEnabled));
            }
            if (this.elMenuIcon.parentNode) {
                this.elMenuIcon.setAttribute("aria-haspopup", "true");
                this.elMenuIcon.setAttribute("aria-expanded", "false");
            }
            this._createHamburgerMenu(elToolbarWrap);
            if (w.interact.zoomEnabled) {
                this.elZoom.classList.add(this.selectedClass);
            } else if (w.interact.panEnabled) {
                this.elPan.classList.add(this.selectedClass);
            } else if (w.interact.selectionEnabled) {
                this.elSelection.classList.add(this.selectedClass);
            }
            this.addToolbarEventListeners();
        }
        /**
         * @param {Element} parent
         */
        _createHamburgerMenu(parent) {
            this.elMenuItems = [];
            parent.appendChild(
                /** @type {Node} */
                this.elMenu
            );
            Graphics.setAttrs(this.elMenu, {
                class: "apexcharts-menu",
                role: "menu"
            });
            const menuItems = [{
                    name: "exportSVG",
                    title: this.localeValues.exportToSVG
                },
                {
                    name: "exportPNG",
                    title: this.localeValues.exportToPNG
                },
                {
                    name: "exportCSV",
                    title: this.localeValues.exportToCSV
                }
            ];
            for (let i = 0; i < menuItems.length; i++) {
                this.elMenuItems.push(
                    BrowserAPIs.createElementNS("http://www.w3.org/1999/xhtml", "div")
                );
                this.elMenuItems[i].innerHTML = menuItems[i].title;
                Graphics.setAttrs(this.elMenuItems[i], {
                    class: `apexcharts-menu-item ${menuItems[i].name}`,
                    title: menuItems[i].title,
                    role: "menuitem",
                    tabindex: "-1"
                });
                this.elMenu.appendChild(this.elMenuItems[i]);
            }
        }
        addToolbarEventListeners() {
            var _a, _b, _c, _d, _e, _f, _g, _h;
            (_a = this.elZoomReset) == null ? void 0 : _a.addEventListener("click", this.handleZoomReset.bind(this));
            (_b = this.elSelection) == null ? void 0 : _b.addEventListener(
                "click",
                this.toggleZoomSelection.bind(this, "selection")
            );
            (_c = this.elZoom) == null ? void 0 : _c.addEventListener(
                "click",
                this.toggleZoomSelection.bind(this, "zoom")
            );
            (_d = this.elZoomIn) == null ? void 0 : _d.addEventListener("click", this.handleZoomIn.bind(this));
            (_e = this.elZoomOut) == null ? void 0 : _e.addEventListener("click", this.handleZoomOut.bind(this));
            (_f = this.elPan) == null ? void 0 : _f.addEventListener("click", this.togglePanning.bind(this));
            (_g = this.elMenuIcon) == null ? void 0 : _g.addEventListener("click", this.toggleMenu.bind(this));
            this.elMenuItems.forEach((m) => {
                if (m.classList.contains("exportSVG")) {
                    m.addEventListener("click", this.handleDownload.bind(this, "svg"));
                } else if (m.classList.contains("exportPNG")) {
                    m.addEventListener("click", this.handleDownload.bind(this, "png"));
                } else if (m.classList.contains("exportCSV")) {
                    m.addEventListener("click", this.handleDownload.bind(this, "csv"));
                }
            });
            for (let i = 0; i < this.t.customIcons.length; i++) {
                this.elCustomIcons[i].addEventListener(
                    "click",
                    this.t.customIcons[i].click.bind(this, this.ctx, this.ctx.w)
                );
            }
            const toolbarButtons = [
                this.elZoomReset,
                this.elSelection,
                this.elZoom,
                this.elZoomIn,
                this.elZoomOut,
                this.elPan,
                this.elMenuIcon,
                ...this.elCustomIcons
            ];
            toolbarButtons.forEach((btn) => {
                btn.addEventListener("keydown", (e) => {
                    if (e.key === "Enter" || e.key === " ") {
                        e.preventDefault();
                        const btnClass = btn.className;
                        btn.click();
                        requestAnimationFrame(() => {
                            const baseEl = this.w.dom.baseEl;
                            if (!baseEl) return;
                            const apexClass = btnClass.split(" ").find((c) => c.startsWith("apexcharts-"));
                            if (!apexClass) return;
                            const restored = baseEl.querySelector(`.${apexClass}`);
                            if (restored) restored.focus();
                        });
                    }
                });
            });
            (_h = this.elMenuIcon) == null ? void 0 : _h.addEventListener(
                "keydown",
                (e) => {
                    var _a2;
                    if (e.key === "ArrowDown" || e.key === "ArrowUp") {
                        e.preventDefault();
                        if (!((_a2 = this.elMenu) == null ? void 0 : _a2.classList.contains("apexcharts-menu-open"))) {
                            this.toggleMenu();
                        }
                        window.setTimeout(() => {
                            const idx = e.key === "ArrowDown" ? 0 : this.elMenuItems.length - 1;
                            if (this.elMenuItems[idx])
                                this.elMenuItems[idx].focus();
                        }, 20);
                    }
                }
            );
            this.elMenuItems.forEach((m, idx) => {
                m.addEventListener("keydown", (e) => {
                    var _a2;
                    if (e.key === "ArrowDown") {
                        e.preventDefault();
                        const next = this.elMenuItems[idx + 1] || this.elMenuItems[0];
                        next.focus();
                    } else if (e.key === "ArrowUp") {
                        e.preventDefault();
                        const prev = this.elMenuItems[idx - 1] || this.elMenuItems[this.elMenuItems.length - 1];
                        prev.focus();
                    } else if (e.key === "Escape" || e.key === "Tab") {
                        this._closeMenu();
                        (_a2 = this.elMenuIcon) == null ? void 0 : _a2.focus();
                        if (e.key === "Tab");
                        else {
                            e.preventDefault();
                        }
                    } else if (e.key === "Enter" || e.key === " ") {
                        e.preventDefault();
                        m.click();
                    }
                });
            });
        }
        /**
         * @param {string} type
         */
        toggleZoomSelection(type) {
            const charts = this.ctx.getSyncedCharts();
            charts.forEach((ch) => {
                ch.ctx.toolbar.toggleOtherControls();
                const el = type === "selection" ? ch.ctx.toolbar.elSelection : ch.ctx.toolbar.elZoom;
                const enabledType = type === "selection" ? "selectionEnabled" : "zoomEnabled";
                ch.w.globals[enabledType] = !ch.w.globals[enabledType];
                if (!el.classList.contains(ch.ctx.toolbar.selectedClass)) {
                    el.classList.add(ch.ctx.toolbar.selectedClass);
                } else {
                    el.classList.remove(ch.ctx.toolbar.selectedClass);
                }
                el.setAttribute("aria-pressed", String(ch.w.globals[enabledType]));
            });
        }
        getToolbarIconsReference() {
            const w = this.w;
            if (!this.elZoom) {
                this.elZoom = w.dom.baseEl.querySelector(".apexcharts-zoom-icon");
            }
            if (!this.elPan) {
                this.elPan = w.dom.baseEl.querySelector(".apexcharts-pan-icon");
            }
            if (!this.elSelection) {
                this.elSelection = w.dom.baseEl.querySelector(
                    ".apexcharts-selection-icon"
                );
            }
        }
        /**
         * @param {string} type
         */
        enableZoomPanFromToolbar(type) {
            this.toggleOtherControls();
            type === "pan" ? this.w.interact.panEnabled = true : this.w.interact.zoomEnabled = true;
            const el = type === "pan" ? this.elPan : this.elZoom;
            const el2 = type === "pan" ? this.elZoom : this.elPan;
            if (el) {
                el.classList.add(this.selectedClass);
            }
            if (el2) {
                el2.classList.remove(this.selectedClass);
            }
        }
        togglePanning() {
            const charts = this.ctx.getSyncedCharts();
            charts.forEach((ch) => {
                ch.ctx.toolbar.toggleOtherControls();
                ch.w.interact.panEnabled = !ch.w.interact.panEnabled;
                if (!ch.ctx.toolbar.elPan.classList.contains(ch.ctx.toolbar.selectedClass)) {
                    ch.ctx.toolbar.elPan.classList.add(ch.ctx.toolbar.selectedClass);
                } else {
                    ch.ctx.toolbar.elPan.classList.remove(ch.ctx.toolbar.selectedClass);
                }
                ch.ctx.toolbar.elPan.setAttribute(
                    "aria-pressed",
                    String(ch.w.interact.panEnabled)
                );
            });
        }
        toggleOtherControls() {
            const w = this.w;
            w.interact.panEnabled = false;
            w.interact.zoomEnabled = false;
            w.interact.selectionEnabled = false;
            this.getToolbarIconsReference();
            const toggleEls = [this.elPan, this.elSelection, this.elZoom];
            toggleEls.forEach((el) => {
                if (el) {
                    el.classList.remove(this.selectedClass);
                }
            });
        }
        /**
         * Read the current x-range from globals at click time.
         * Toolbar instance is kept alive across updates (Phase 8 lazy
         * instantiation), so cached this.minX/maxX go stale after a zoom.
         * @returns {{minX: number, maxX: number}}
         */
        _currentXRange() {
            const w = this.w;
            if (w.axisFlags.isRangeBar) {
                return {
                    minX: w.globals.minY,
                    maxX: w.globals.maxY
                };
            }
            return {
                minX: w.globals.minX,
                maxX: w.globals.maxX
            };
        }
        handleZoomIn() {
            const w = this.w;
            const {
                minX,
                maxX
            } = this._currentXRange();
            this.minX = minX;
            this.maxX = maxX;
            const centerX = (minX + maxX) / 2;
            const newMinX = (minX + centerX) / 2;
            const newMaxX = (maxX + centerX) / 2;
            const newMinXMaxX = this._getNewMinXMaxX(newMinX, newMaxX);
            if (!w.interact.disableZoomIn) {
                this.zoomUpdateOptions(newMinXMaxX.minX, newMinXMaxX.maxX);
            }
        }
        handleZoomOut() {
            const w = this.w;
            const {
                minX,
                maxX
            } = this._currentXRange();
            this.minX = minX;
            this.maxX = maxX;
            if (w.config.xaxis.type === "datetime" && new Date(minX).getUTCFullYear() < 1e3) {
                return;
            }
            const centerX = (minX + maxX) / 2;
            const newMinX = minX - (centerX - minX);
            const newMaxX = maxX - (centerX - maxX);
            const newMinXMaxX = this._getNewMinXMaxX(newMinX, newMaxX);
            if (!w.interact.disableZoomOut) {
                this.zoomUpdateOptions(newMinXMaxX.minX, newMinXMaxX.maxX);
            }
        }
        /**
         * @param {number} newMinX
         * @param {number} newMaxX
         */
        _getNewMinXMaxX(newMinX, newMaxX) {
            const shouldFloor = this.w.config.xaxis.convertedCatToNumeric;
            return {
                minX: shouldFloor ? Math.floor(newMinX) : newMinX,
                maxX: shouldFloor ? Math.floor(newMaxX) : newMaxX
            };
        }
        /**
         * @param {number} newMinX
         * @param {number} newMaxX
         */
        zoomUpdateOptions(newMinX, newMaxX) {
            const w = this.w;
            if (newMinX === void 0 && newMaxX === void 0) {
                this.handleZoomReset();
                return;
            }
            if (w.config.xaxis.convertedCatToNumeric) {
                if (newMinX < 1) {
                    newMinX = 1;
                    newMaxX = w.globals.dataPoints;
                }
                if (newMaxX - newMinX < 2) {
                    return;
                }
            }
            let xaxis = {
                min: newMinX,
                max: newMaxX
            };
            const beforeZoomRange = this.getBeforeZoomRange(
                xaxis,
                /** @type {any} */
                void 0
            );
            if (beforeZoomRange) {
                xaxis = beforeZoomRange.xaxis;
            }
            const options2 = {
                xaxis
            };
            if (!w.globals.initialConfig) return;
            const yaxis = Utils$1.clone(w.globals.initialConfig.yaxis);
            if (!w.config.chart.group) {
                options2.yaxis = yaxis;
            }
            this.w.interact.zoomed = true;
            this.ctx.updateHelpers._updateOptions(
                options2,
                false,
                this.w.config.chart.animations.dynamicAnimation.enabled
            );
            this.zoomCallback(xaxis, yaxis);
        }
        /**
         * @param {Record<string, any>} xaxis
         * @param {Record<string, any>} yaxis
         */
        zoomCallback(xaxis, yaxis) {
            if (typeof this.ev.zoomed === "function") {
                this.ev.zoomed(this.ctx, {
                    xaxis,
                    yaxis
                });
                this.ctx.events.fireEvent("zoomed", {
                    xaxis,
                    yaxis
                });
            }
        }
        /**
         * @param {Record<string, any>} xaxis
         * @param {Record<string, any>} yaxis
         */
        getBeforeZoomRange(xaxis, yaxis) {
            let newRange = null;
            if (typeof this.ev.beforeZoom === "function") {
                newRange = this.ev.beforeZoom(this, {
                    xaxis,
                    yaxis
                });
            }
            return newRange;
        }
        toggleMenu() {
            window.setTimeout(() => {
                var _a, _b, _c;
                if ((_a = this.elMenu) == null ? void 0 : _a.classList.contains("apexcharts-menu-open")) {
                    this._closeMenu();
                } else {
                    (_b = this.elMenu) == null ? void 0 : _b.classList.add("apexcharts-menu-open");
                    (_c = this.elMenuIcon) == null ? void 0 : _c.setAttribute("aria-expanded", "true");
                }
            }, 0);
        }
        _closeMenu() {
            var _a, _b;
            (_a = this.elMenu) == null ? void 0 : _a.classList.remove("apexcharts-menu-open");
            (_b = this.elMenuIcon) == null ? void 0 : _b.setAttribute("aria-expanded", "false");
        }
        /**
         * @param {string} type
         */
        handleDownload(type) {
            const w = this.w;
            const exprt = new Exports(this.w, this.ctx);
            switch (type) {
                case "svg":
                    exprt.exportToSVG();
                    break;
                case "png":
                    exprt.exportToPng();
                    break;
                case "csv":
                    exprt.exportToCSV({
                        series: w.config.series,
                        columnDelimiter: w.config.chart.toolbar.export.csv.columnDelimiter
                    });
                    break;
            }
        }
        handleZoomReset() {
            const charts = this.ctx.getSyncedCharts();
            charts.forEach((ch) => {
                const w = ch.w;
                if (!w.interact.zoomed) return;
                w.globals.lastXAxis.min = w.globals.initialConfig.xaxis.min;
                w.globals.lastXAxis.max = w.globals.initialConfig.xaxis.max;
                ch.updateHelpers.revertDefaultAxisMinMax();
                if (typeof w.config.chart.events.beforeResetZoom === "function") {
                    const resetZoomRange = w.config.chart.events.beforeResetZoom(ch, w);
                    if (resetZoomRange) {
                        ch.updateHelpers.revertDefaultAxisMinMax(resetZoomRange);
                    }
                }
                if (typeof w.config.chart.events.zoomed === "function") {
                    ch.ctx.toolbar.zoomCallback({
                        min: w.config.xaxis.min,
                        max: w.config.xaxis.max
                    });
                }
                const series = ch.ctx.series.emptyCollapsedSeries(
                    Utils$1.clone(w.globals.initialSeries)
                );
                ch.updateHelpers._updateSeries(
                    series,
                    w.config.chart.animations.dynamicAnimation.enabled
                );
                w.interact.zoomed = false;
            });
        }
        destroy() {
            this.elZoom = null;
            this.elZoomIn = null;
            this.elZoomOut = null;
            this.elPan = null;
            this.elSelection = null;
            this.elZoomReset = null;
            this.elMenuIcon = null;
        }
    }
    class ZoomPanSelection extends Toolbar {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            super(w, ctx);
            this.w = w;
            this.ctx = ctx;
            this.dragged = false;
            this.graphics = new Graphics(this.w);
            this.eventList = [
                "mousedown",
                "mouseleave",
                "mousemove",
                "touchstart",
                "touchmove",
                "mouseup",
                "touchend",
                "wheel"
            ];
            this.clientX = 0;
            this.clientY = 0;
            this.startX = 0;
            this.endX = 0;
            this.dragX = 0;
            this.startY = 0;
            this.endY = 0;
            this.dragY = 0;
            this.moveDirection = "none";
            this.debounceTimer = null;
            this.debounceDelay = 100;
            this.wheelDelay = 400;
        }
        /** @param {{xyRatios: any}} opts */
        init({
            xyRatios
        }) {
            const w = this.w;
            const me = this;
            this.xyRatios = xyRatios;
            this.zoomRect = this.graphics.drawRect(0, 0, 0, 0);
            this.selectionRect = this.graphics.drawRect(0, 0, 0, 0);
            this.gridRect = w.dom.baseEl.querySelector(".apexcharts-grid");
            this.constraints = new Box(0, 0, w.layout.gridWidth, w.layout.gridHeight);
            this.zoomRect.node.classList.add("apexcharts-zoom-rect");
            this.selectionRect.node.classList.add("apexcharts-selection-rect");
            w.dom.Paper.add(this.zoomRect);
            w.dom.Paper.add(this.selectionRect);
            if (w.config.chart.selection.type === "x") {
                this.slDraggableRect = this.selectionRect.draggable({
                    minX: 0,
                    minY: 0,
                    maxX: w.layout.gridWidth,
                    maxY: w.layout.gridHeight
                }).on("dragmove.namespace", this.selectionDragging.bind(this, "dragging"));
            } else if (w.config.chart.selection.type === "y") {
                this.slDraggableRect = this.selectionRect.draggable({
                    minX: 0,
                    maxX: w.layout.gridWidth
                }).on("dragmove.namespace", this.selectionDragging.bind(this, "dragging"));
            } else {
                this.slDraggableRect = this.selectionRect.draggable().on("dragmove.namespace", this.selectionDragging.bind(this, "dragging"));
            }
            this.preselectedSelection();
            this.hoverArea = /** @type {Element} */
                w.dom.baseEl.querySelector(`${w.globals.chartClass} .apexcharts-svg`);
            if (!this.hoverArea) return;
            this.hoverArea.classList.add("apexcharts-zoomable");
            this.eventList.forEach((event) => {
                var _a;
                (_a = this.hoverArea) == null ? void 0 : _a.addEventListener(
                    event,
                    me.svgMouseEvents.bind(me, xyRatios), {
                        capture: false,
                        passive: true
                    }
                );
            });
            if (w.config.chart.zoom.enabled && w.config.chart.zoom.allowMouseWheelZoom) {
                this.hoverArea.addEventListener("wheel", me.mouseWheelEvent.bind(me), {
                    capture: false,
                    passive: false
                });
            }
        }
        // remove the event listeners which were previously added on hover area
        destroy() {
            if (this.slDraggableRect) {
                this.slDraggableRect.draggable(false);
                this.slDraggableRect.off();
                this.selectionRect.off();
            }
            this.selectionRect = null;
            this.zoomRect = null;
            this.gridRect = null;
        }
        /**
         * @param {import('../types/internal').XYRatios} xyRatios
         * @param {any} e
         */
        svgMouseEvents(xyRatios, e) {
            var _a;
            const w = this.w;
            const toolbar = this.ctx.toolbar;
            const zoomtype = w.interact.zoomEnabled ? w.config.chart.zoom.type : w.config.chart.selection.type;
            const autoSelected = w.config.chart.toolbar.autoSelected;
            if (e.shiftKey) {
                this.shiftWasPressed = true;
                toolbar.enableZoomPanFromToolbar(autoSelected === "pan" ? "zoom" : "pan");
            } else {
                if (this.shiftWasPressed) {
                    toolbar.enableZoomPanFromToolbar(autoSelected);
                    this.shiftWasPressed = false;
                }
            }
            if (!e.target) return;
            const tc = e.target.classList;
            let pc;
            if (e.target.parentNode && e.target.parentNode !== null) {
                pc = e.target.parentNode.classList;
            }
            const falsePositives = tc.contains("apexcharts-legend-marker") || tc.contains("apexcharts-legend-text") || pc && pc.contains("apexcharts-toolbar");
            if (falsePositives) return;
            this.clientX = e.type === "touchmove" || e.type === "touchstart" ? e.touches[0].clientX : e.type === "touchend" ? e.changedTouches[0].clientX : e.clientX;
            this.clientY = e.type === "touchmove" || e.type === "touchstart" ? e.touches[0].clientY : e.type === "touchend" ? e.changedTouches[0].clientY : e.clientY;
            if (e.type === "mousedown" && e.which === 1 || e.type === "touchstart") {
                const gridRectDim = (_a = this.gridRect) == null ? void 0 : _a.getBoundingClientRect();
                if (!gridRectDim) return;
                this.startX = this.clientX - gridRectDim.left - w.globals.barPadForNumericAxis;
                this.startY = this.clientY - gridRectDim.top;
                this.dragged = false;
                this.w.interact.mousedown = true;
            }
            if (e.type === "mousemove" && e.which === 1 || e.type === "touchmove") {
                this.dragged = true;
                if (w.interact.panEnabled) {
                    w.interact.selection = null;
                    if (this.w.interact.mousedown) {
                        this.panDragging({
                            context: this,
                            zoomtype,
                            xyRatios
                        });
                    }
                } else {
                    if (this.w.interact.mousedown && w.interact.zoomEnabled || this.w.interact.mousedown && w.interact.selectionEnabled) {
                        this.selection = this.selectionDrawing({
                            context: this,
                            zoomtype
                        });
                    }
                }
            }
            if (e.type === "mouseup" || e.type === "touchend" || e.type === "mouseleave") {
                this.handleMouseUp({
                    zoomtype
                });
            }
            this.makeSelectionRectDraggable();
        }
        /** @param {{ zoomtype?: any, isResized?: any }} opts */
        handleMouseUp({
            zoomtype,
            isResized
        }) {
            var _a;
            const w = this.w;
            const gridRectDim = (_a = this.gridRect) == null ? void 0 : _a.getBoundingClientRect();
            if (gridRectDim && (this.w.interact.mousedown || isResized)) {
                this.endX = this.clientX - gridRectDim.left - w.globals.barPadForNumericAxis;
                this.endY = this.clientY - gridRectDim.top;
                this.dragX = Math.abs(this.endX - this.startX);
                this.dragY = Math.abs(this.endY - this.startY);
                if (w.interact.zoomEnabled || w.interact.selectionEnabled) {
                    this.selectionDrawn({
                        context: this,
                        zoomtype
                    });
                }
            }
            if (w.interact.zoomEnabled) {
                this.hideSelectionRect(this.selectionRect);
            }
            this.dragged = false;
            this.w.interact.mousedown = false;
        }
        /**
         * @param {Event} e
         */
        mouseWheelEvent(e) {
            const w = this.w;
            e.preventDefault();
            const now = Date.now();
            if (now - w.interact.lastWheelExecution > this.wheelDelay) {
                this.executeMouseWheelZoom(e);
                w.interact.lastWheelExecution = now;
            }
            if (this.debounceTimer) clearTimeout(this.debounceTimer);
            this.debounceTimer = setTimeout(() => {
                if (now - w.interact.lastWheelExecution > this.wheelDelay) {
                    this.executeMouseWheelZoom(e);
                    w.interact.lastWheelExecution = now;
                }
            }, this.debounceDelay);
        }
        /**
         * @param {any} e
         */
        executeMouseWheelZoom(e) {
            var _a, _b, _c;
            const w = this.w;
            this.minX = w.axisFlags.isRangeBar ? w.globals.minY : w.globals.minX;
            this.maxX = w.axisFlags.isRangeBar ? w.globals.maxY : w.globals.maxX;
            const gridRectDim = (_a = this.gridRect) == null ? void 0 : _a.getBoundingClientRect();
            if (!gridRectDim) return;
            const mouseX = (e.clientX - gridRectDim.left) / gridRectDim.width;
            const currentMinX = this.minX;
            const currentMaxX = this.maxX;
            const totalX = currentMaxX - currentMinX;
            const zoomFactorIn = 0.5;
            const zoomFactorOut = 1.5;
            let zoomRange;
            let newMinX, newMaxX;
            if (e.deltaY < 0) {
                zoomRange = zoomFactorIn * totalX;
                const midPoint = currentMinX + mouseX * totalX;
                newMinX = midPoint - zoomRange / 2;
                newMaxX = midPoint + zoomRange / 2;
            } else {
                zoomRange = zoomFactorOut * totalX;
                newMinX = currentMinX - zoomRange / 2;
                newMaxX = currentMaxX + zoomRange / 2;
            }
            if (!w.axisFlags.isRangeBar) {
                const clampMin = (_b = w.globals.dataReducerRawMinX) != null ? _b : w.globals.initialMinX;
                const clampMax = (_c = w.globals.dataReducerRawMaxX) != null ? _c : w.globals.initialMaxX;
                newMinX = Math.max(newMinX, clampMin);
                newMaxX = Math.min(newMaxX, clampMax);
                const minRange = (clampMax - clampMin) * 0.01;
                if (newMaxX - newMinX < minRange) {
                    const midPoint = (newMinX + newMaxX) / 2;
                    newMinX = midPoint - minRange / 2;
                    newMaxX = midPoint + minRange / 2;
                }
            }
            const newMinXMaxX = this._getNewMinXMaxX(newMinX, newMaxX);
            if (!isNaN(newMinXMaxX.minX) && !isNaN(newMinXMaxX.maxX)) {
                this.zoomUpdateOptions(newMinXMaxX.minX, newMinXMaxX.maxX);
            }
        }
        makeSelectionRectDraggable() {
            const w = this.w;
            if (!this.selectionRect) return;
            const rectDim = this.selectionRect.node.getBoundingClientRect();
            if (rectDim.width > 0 && rectDim.height > 0) {
                this.selectionRect.select(false).resize(false);
                this.selectionRect.select({
                    createRot: () => {},
                    updateRot: () => {},
                    createHandle: (group, p, index, pointArr, handleName) => {
                        if (handleName === "l" || handleName === "r")
                            return group.circle(8).css({
                                "stroke-width": 1,
                                stroke: "#333",
                                fill: "#fff"
                            });
                        return group.circle(0);
                    },
                    updateHandle: (group, p) => {
                        return group.center(p[0], p[1]);
                    }
                }).resize().on("resize", () => {
                    const zoomtype = w.interact.zoomEnabled ? w.config.chart.zoom.type : w.config.chart.selection.type;
                    this.handleMouseUp({
                        zoomtype,
                        isResized: true
                    });
                });
            }
        }
        preselectedSelection() {
            const w = this.w;
            const xyRatios = this.xyRatios;
            if (!w.interact.zoomEnabled) {
                if (typeof w.interact.selection !== "undefined" && w.interact.selection !== null) {
                    this.drawSelectionRect(__spreadProps(__spreadValues({}, w.interact.selection), {
                        translateX: w.layout.translateX,
                        translateY: w.layout.translateY
                    }));
                } else {
                    if (w.config.chart.selection.xaxis.min !== void 0 && w.config.chart.selection.xaxis.max !== void 0) {
                        let x = (w.config.chart.selection.xaxis.min - w.globals.minX) / xyRatios.xRatio;
                        let width = w.layout.gridWidth - (w.globals.maxX - w.config.chart.selection.xaxis.max) / xyRatios.xRatio - x;
                        if (w.axisFlags.isRangeBar) {
                            x = (w.config.chart.selection.xaxis.min - w.globals.yAxisScale[0].niceMin) / xyRatios.invertedYRatio;
                            width = (w.config.chart.selection.xaxis.max - w.config.chart.selection.xaxis.min) / xyRatios.invertedYRatio;
                        }
                        const selectionRect = {
                            x,
                            y: 0,
                            width,
                            height: w.layout.gridHeight,
                            translateX: w.layout.translateX,
                            translateY: w.layout.translateY,
                            selectionEnabled: true
                        };
                        this.drawSelectionRect(selectionRect);
                        this.makeSelectionRectDraggable();
                        if (typeof w.config.chart.events.selection === "function") {
                            w.config.chart.events.selection(this.ctx, {
                                xaxis: {
                                    min: w.config.chart.selection.xaxis.min,
                                    max: w.config.chart.selection.xaxis.max
                                },
                                yaxis: {}
                            });
                        }
                    }
                }
            }
        }
        /** @param {{x: any, y: any, width: any, height: any, translateX: any, translateY: any}} opts */
        drawSelectionRect({
            x,
            y,
            width,
            height,
            translateX = 0,
            translateY = 0
        }) {
            const w = this.w;
            const zoomRect = this.zoomRect;
            const selectionRect = this.selectionRect;
            if (this.dragged || w.interact.selection !== null) {
                const scalingAttrs = {
                    transform: "translate(" + translateX + ", " + translateY + ")"
                };
                if (w.interact.zoomEnabled && this.dragged) {
                    if (width < 0) width = 1;
                    zoomRect.attr({
                        x,
                        y,
                        width,
                        height,
                        fill: w.config.chart.zoom.zoomedArea.fill.color,
                        "fill-opacity": w.config.chart.zoom.zoomedArea.fill.opacity,
                        stroke: w.config.chart.zoom.zoomedArea.stroke.color,
                        "stroke-width": w.config.chart.zoom.zoomedArea.stroke.width,
                        "stroke-opacity": w.config.chart.zoom.zoomedArea.stroke.opacity
                    });
                    Graphics.setAttrs(zoomRect.node, scalingAttrs);
                }
                if (w.interact.selectionEnabled) {
                    selectionRect.attr({
                        x,
                        y,
                        width: width > 0 ? width : 0,
                        height: height > 0 ? height : 0,
                        fill: w.config.chart.selection.fill.color,
                        "fill-opacity": w.config.chart.selection.fill.opacity,
                        stroke: w.config.chart.selection.stroke.color,
                        "stroke-width": w.config.chart.selection.stroke.width,
                        "stroke-dasharray": w.config.chart.selection.stroke.dashArray,
                        "stroke-opacity": w.config.chart.selection.stroke.opacity
                    });
                    Graphics.setAttrs(selectionRect.node, scalingAttrs);
                }
            }
        }
        /**
         * @param {any} rect
         */
        hideSelectionRect(rect) {
            if (rect) {
                rect.attr({
                    x: 0,
                    y: 0,
                    width: 0,
                    height: 0
                });
            }
        }
        selectionDrawing({
            context,
            zoomtype
        }) {
            var _a;
            const w = this.w;
            const me = context;
            const gridRectDim = (_a = this.gridRect) == null ? void 0 : _a.getBoundingClientRect();
            if (!gridRectDim) return;
            const startX = me.startX - 1;
            const startY = me.startY;
            let inversedX = false;
            let inversedY = false;
            const left = me.clientX - gridRectDim.left - w.globals.barPadForNumericAxis;
            const top = me.clientY - gridRectDim.top;
            let selectionWidth = left - startX;
            let selectionHeight = top - startY;
            let selectionRect = {
                translateX: w.layout.translateX,
                translateY: w.layout.translateY
            };
            if (Math.abs(selectionWidth + startX) > w.layout.gridWidth) {
                selectionWidth = w.layout.gridWidth - startX;
            } else if (left < 0) {
                selectionWidth = startX;
            }
            if (startX > left) {
                inversedX = true;
                selectionWidth = Math.abs(selectionWidth);
            }
            if (startY > top) {
                inversedY = true;
                selectionHeight = Math.abs(selectionHeight);
            }
            if (zoomtype === "x") {
                selectionRect = {
                    x: inversedX ? startX - selectionWidth : startX,
                    y: 0,
                    width: selectionWidth,
                    height: w.layout.gridHeight
                };
            } else if (zoomtype === "y") {
                selectionRect = {
                    x: 0,
                    y: inversedY ? startY - selectionHeight : startY,
                    width: w.layout.gridWidth,
                    height: selectionHeight
                };
            } else {
                selectionRect = {
                    x: inversedX ? startX - selectionWidth : startX,
                    y: inversedY ? startY - selectionHeight : startY,
                    width: selectionWidth,
                    height: selectionHeight
                };
            }
            selectionRect = __spreadProps(__spreadValues({}, selectionRect), {
                translateX: w.layout.translateX,
                translateY: w.layout.translateY
            });
            me.drawSelectionRect(selectionRect);
            me.selectionDragging("resizing");
            return selectionRect;
        }
        /**
         * @param {string} type
         * @param {CustomEvent} e
         */
        selectionDragging(type, e) {
            var _a;
            const w = this.w;
            if (!e) return;
            e.preventDefault();
            const {
                handler,
                box
            } = e.detail;
            const constraints = (
                /** @type {any} */
                this.constraints
            );
            let {
                x,
                y
            } = box;
            if (x < constraints.x) {
                x = constraints.x;
            }
            if (y < constraints.y) {
                y = constraints.y;
            }
            if (box.x2 > constraints.x2) {
                x = constraints.x2 - box.w;
            }
            if (box.y2 > constraints.y2) {
                y = constraints.y2 - box.h;
            }
            handler.move(x, y);
            const xyRatios = this.xyRatios;
            const selRect = this.selectionRect;
            let timerInterval = 0;
            if (type === "resizing") {
                timerInterval = 30;
            }
            const getSelAttr = (attr) => {
                return parseFloat(selRect.node.getAttribute(attr));
            };
            const draggedProps = {
                x: getSelAttr("x"),
                y: getSelAttr("y"),
                width: getSelAttr("width"),
                height: getSelAttr("height")
            };
            w.interact.selection = draggedProps;
            if (typeof w.config.chart.events.selection === "function" && w.interact.selectionEnabled) {
                clearTimeout((_a = this.w.globals.selectionResizeTimer) != null ? _a : void 0);
                this.w.globals.selectionResizeTimer = window.setTimeout(() => {
                    var _a2;
                    const gridRectDim = (_a2 = this.gridRect) == null ? void 0 : _a2.getBoundingClientRect();
                    if (!gridRectDim) return;
                    const selectionRect = selRect.node.getBoundingClientRect();
                    let minX, maxX, minY, maxY;
                    if (!w.axisFlags.isRangeBar) {
                        if (!w.globals.xAxisScale) return;
                        minX = w.globals.xAxisScale.niceMin + (selectionRect.left - gridRectDim.left) * xyRatios.xRatio;
                        maxX = w.globals.xAxisScale.niceMin + (selectionRect.right - gridRectDim.left) * xyRatios.xRatio;
                        minY = w.globals.yAxisScale[0].niceMin + (gridRectDim.bottom - selectionRect.bottom) * xyRatios.yRatio[0];
                        maxY = w.globals.yAxisScale[0].niceMax - (selectionRect.top - gridRectDim.top) * xyRatios.yRatio[0];
                    } else {
                        minX = w.globals.yAxisScale[0].niceMin + (selectionRect.left - gridRectDim.left) * xyRatios.invertedYRatio;
                        maxX = w.globals.yAxisScale[0].niceMin + (selectionRect.right - gridRectDim.left) * xyRatios.invertedYRatio;
                        minY = 0;
                        maxY = 1;
                    }
                    const xyAxis = {
                        xaxis: {
                            min: minX,
                            max: maxX
                        },
                        yaxis: {
                            min: minY,
                            max: maxY
                        }
                    };
                    w.config.chart.events.selection(this.ctx, xyAxis);
                    if (w.config.chart.brush.enabled && w.config.chart.events.brushScrolled !== void 0) {
                        w.config.chart.events.brushScrolled(this.ctx, xyAxis);
                    }
                }, timerInterval);
            }
        }
        /** @param {{context: any, zoomtype: any}} opts */
        selectionDrawn({
            context,
            zoomtype
        }) {
            var _a, _b;
            const w = this.w;
            const me = context;
            const xyRatios = this.xyRatios;
            const toolbar = this.ctx.toolbar;
            const selRect = w.interact.zoomEnabled ? me.zoomRect.node.getBoundingClientRect() : me.selectionRect.node.getBoundingClientRect();
            const gridRectDim = me.gridRect.getBoundingClientRect();
            const localStartX = selRect.left - gridRectDim.left - w.globals.barPadForNumericAxis;
            const localEndX = selRect.right - gridRectDim.left - w.globals.barPadForNumericAxis;
            const localStartY = selRect.top - gridRectDim.top;
            const localEndY = selRect.bottom - gridRectDim.top;
            let xLowestValue, xHighestValue;
            if (!w.axisFlags.isRangeBar) {
                const niceMin = (_b = (_a = w.globals.xAxisScale) == null ? void 0 : _a.niceMin) != null ? _b : 0;
                xLowestValue = niceMin + localStartX * xyRatios.xRatio;
                xHighestValue = niceMin + localEndX * xyRatios.xRatio;
            } else {
                xLowestValue = w.globals.yAxisScale[0].niceMin + localStartX * xyRatios.invertedYRatio;
                xHighestValue = w.globals.yAxisScale[0].niceMin + localEndX * xyRatios.invertedYRatio;
            }
            const yHighestValue = [];
            const yLowestValue = [];
            w.config.yaxis.forEach((yaxe, index) => {
                const seriesIndex = w.globals.seriesYAxisMap[index][0];
                const highestVal = w.globals.yAxisScale[index].niceMax - xyRatios.yRatio[seriesIndex] * localStartY;
                const lowestVal = w.globals.yAxisScale[index].niceMax - xyRatios.yRatio[seriesIndex] * localEndY;
                yHighestValue.push(highestVal);
                yLowestValue.push(lowestVal);
            });
            if (me.dragged && (me.dragX > 10 || me.dragY > 10) && xLowestValue !== xHighestValue) {
                if (w.interact.zoomEnabled) {
                    if (!w.globals.initialConfig) return;
                    let yaxis = Utils$1.clone(w.globals.initialConfig.yaxis);
                    let xaxis = Utils$1.clone(w.globals.initialConfig.xaxis);
                    w.interact.zoomed = true;
                    if (w.config.xaxis.convertedCatToNumeric) {
                        xLowestValue = Math.floor(xLowestValue);
                        xHighestValue = Math.floor(xHighestValue);
                        if (xLowestValue < 1) {
                            xLowestValue = 1;
                            xHighestValue = w.globals.dataPoints;
                        }
                        if (xHighestValue - xLowestValue < 2) {
                            xHighestValue = xLowestValue + 1;
                        }
                    }
                    if (zoomtype === "xy" || zoomtype === "x") {
                        xaxis = {
                            min: xLowestValue,
                            max: xHighestValue
                        };
                    }
                    if (zoomtype === "xy" || zoomtype === "y") {
                        yaxis.forEach((yaxe, index) => {
                            yaxis[index].min = yLowestValue[index];
                            yaxis[index].max = yHighestValue[index];
                        });
                    }
                    if (toolbar) {
                        const beforeZoomRange = toolbar.getBeforeZoomRange(xaxis, yaxis);
                        if (beforeZoomRange) {
                            xaxis = beforeZoomRange.xaxis ? beforeZoomRange.xaxis : xaxis;
                            yaxis = beforeZoomRange.yaxis ? beforeZoomRange.yaxis : yaxis;
                        }
                    }
                    const options2 = {
                        xaxis
                    };
                    if (!w.config.chart.group) {
                        options2.yaxis = yaxis;
                    }
                    me.ctx.updateHelpers._updateOptions(
                        options2,
                        false,
                        me.w.config.chart.animations.dynamicAnimation.enabled
                    );
                    if (typeof w.config.chart.events.zoomed === "function") {
                        toolbar.zoomCallback(xaxis, yaxis);
                    }
                } else if (w.interact.selectionEnabled) {
                    let yaxis = null;
                    let xaxis = null;
                    xaxis = {
                        min: xLowestValue,
                        max: xHighestValue
                    };
                    if (zoomtype === "xy" || zoomtype === "y") {
                        const yaxisCopy = (
                            /** @type {ApexYAxis[]} */
                            Utils$1.clone(w.config.yaxis)
                        );
                        yaxis = yaxisCopy;
                        yaxisCopy.forEach((yaxe, index) => {
                            yaxisCopy[index].min = yLowestValue[index];
                            yaxisCopy[index].max = yHighestValue[index];
                        });
                    }
                    w.interact.selection = me.selection;
                    if (typeof w.config.chart.events.selection === "function") {
                        w.config.chart.events.selection(me.ctx, {
                            xaxis,
                            yaxis
                        });
                    }
                }
            }
        }
        /** @param {{ context?: any, zoomtype?: any, xyRatios?: any }} opts */
        panDragging({
            context
        }) {
            var _a;
            const w = this.w;
            const me = context;
            if (typeof w.interact.lastClientPosition.x !== "undefined") {
                const deltaX = w.interact.lastClientPosition.x - me.clientX;
                const deltaY = ((_a = w.interact.lastClientPosition.y) != null ? _a : 0) - me.clientY;
                if (Math.abs(deltaX) > Math.abs(deltaY) && deltaX > 0) {
                    this.moveDirection = "left";
                } else if (Math.abs(deltaX) > Math.abs(deltaY) && deltaX < 0) {
                    this.moveDirection = "right";
                } else if (Math.abs(deltaY) > Math.abs(deltaX) && deltaY > 0) {
                    this.moveDirection = "up";
                } else if (Math.abs(deltaY) > Math.abs(deltaX) && deltaY < 0) {
                    this.moveDirection = "down";
                }
            }
            w.interact.lastClientPosition = {
                x: me.clientX,
                y: me.clientY
            };
            const xLowestValue = w.axisFlags.isRangeBar ? w.globals.minY : w.globals.minX;
            const xHighestValue = w.axisFlags.isRangeBar ? w.globals.maxY : w.globals.maxX;
            me.panScrolled(xLowestValue, xHighestValue);
        }
        // delayedPanScrolled() {
        //   const w = this.w
        //   let newMinX = w.globals.minX
        //   let newMaxX = w.globals.maxX
        //   const centerX = (w.globals.maxX - w.globals.minX) / 2
        //   if (this.moveDirection === 'left') {
        //     newMinX = w.globals.minX + centerX
        //     newMaxX = w.globals.maxX + centerX
        //   } else if (this.moveDirection === 'right') {
        //     newMinX = w.globals.minX - centerX
        //     newMaxX = w.globals.maxX - centerX
        //   }
        //   newMinX = Math.floor(newMinX)
        //   newMaxX = Math.floor(newMaxX)
        //   this.updateScrolledChart(
        //     { xaxis: { min: newMinX, max: newMaxX } },
        //     newMinX,
        //     newMaxX
        //   )
        // }
        /**
         * @param {number} xLowestValue
         * @param {number} xHighestValue
         */
        panScrolled(xLowestValue, xHighestValue) {
            var _a, _b;
            const w = this.w;
            const xyRatios = this.xyRatios;
            if (!w.globals.initialConfig) return;
            const yaxis = Utils$1.clone(w.globals.initialConfig.yaxis);
            let xRatio = xyRatios.xRatio;
            let minX = w.globals.minX;
            let maxX = w.globals.maxX;
            if (w.axisFlags.isRangeBar) {
                xRatio = xyRatios.invertedYRatio;
                minX = w.globals.minY;
                maxX = w.globals.maxY;
            }
            if (this.moveDirection === "left") {
                xLowestValue = minX + w.layout.gridWidth / 15 * xRatio;
                xHighestValue = maxX + w.layout.gridWidth / 15 * xRatio;
            } else if (this.moveDirection === "right") {
                xLowestValue = minX - w.layout.gridWidth / 15 * xRatio;
                xHighestValue = maxX - w.layout.gridWidth / 15 * xRatio;
            }
            if (!w.axisFlags.isRangeBar) {
                const clampMin = (_a = w.globals.dataReducerRawMinX) != null ? _a : w.globals.initialMinX;
                const clampMax = (_b = w.globals.dataReducerRawMaxX) != null ? _b : w.globals.initialMaxX;
                if (xLowestValue < clampMin || xHighestValue > clampMax) {
                    xLowestValue = minX;
                    xHighestValue = maxX;
                }
            }
            const xaxis = {
                min: xLowestValue,
                max: xHighestValue
            };
            const options2 = {
                xaxis
            };
            if (!w.config.chart.group) {
                options2.yaxis = yaxis;
            }
            this.updateScrolledChart(options2, xLowestValue, xHighestValue);
        }
        /**
         * @param {object} options
         * @param {number} xLowestValue
         * @param {number} xHighestValue
         */
        updateScrolledChart(options2, xLowestValue, xHighestValue) {
            const w = this.w;
            this.ctx.updateHelpers._updateOptions(options2, false, false);
            if (typeof w.config.chart.events.scrolled === "function") {
                const args = {
                    xaxis: {
                        min: xLowestValue,
                        max: xHighestValue
                    }
                };
                w.config.chart.events.scrolled(this.ctx, args);
                this.ctx.events.fireEvent("scrolled", args);
            }
        }
    }
    ApexCharts.registerFeatures({
        toolbar: Toolbar,
        zoomPanSelection: ZoomPanSelection
    });
    let Helpers$2 = class Helpers {
        /**
         * @param {import('./Annotations').default} annoCtx
         */
        constructor(annoCtx) {
            this.w = annoCtx.w;
            this.annoCtx = annoCtx;
        }
        /**
         * @param {Record<string, any>} anno
         * @param {number | null} [annoIndex]
         */
        setOrientations(anno, annoIndex = null) {
            var _a, _b;
            const w = this.w;
            if (anno.label.orientation === "vertical") {
                const i = annoIndex !== null ? annoIndex : 0;
                const xAnno = w.dom.baseEl.querySelector(
                    `.apexcharts-xaxis-annotations .apexcharts-xaxis-annotation-label[rel='${i}']`
                );
                if (xAnno !== null) {
                    const xAnnoCoord = (
                        /** @type {SVGGraphicsElement} */
                        xAnno.getBBox()
                    );
                    xAnno.setAttribute(
                        "x",
                        String(
                            parseFloat((_a = xAnno.getAttribute("x")) != null ? _a : "0") - xAnnoCoord.height + 4
                        )
                    );
                    const yOffset = anno.label.position === "top" ? xAnnoCoord.width : -xAnnoCoord.width;
                    xAnno.setAttribute(
                        "y",
                        String(parseFloat((_b = xAnno.getAttribute("y")) != null ? _b : "0") + yOffset)
                    );
                    const {
                        x,
                        y
                    } = this.annoCtx.graphics.rotateAroundCenter(xAnno);
                    xAnno.setAttribute("transform", `rotate(-90 ${x} ${y})`);
                }
            }
        }
        /**
         * @param {any} annoEl
         * @param {Record<string, any>} anno
         */
        addBackgroundToAnno(annoEl, anno) {
            const w = this.w;
            if (!annoEl || !anno.label.text || !String(anno.label.text).trim()) {
                return null;
            }
            const gridEl = w.dom.baseEl.querySelector(".apexcharts-grid");
            if (!gridEl) return null;
            const elGridRect = gridEl.getBoundingClientRect();
            const gridBBox = (
                /** @type {SVGGraphicsElement} */
                gridEl.getBBox()
            );
            const zoom = elGridRect.width / gridBBox.width || 1;
            const coords = annoEl.getBoundingClientRect();
            let {
                left: pleft,
                right: pright,
                top: ptop,
                bottom: pbottom
            } = anno.label.style.padding;
            if (anno.label.orientation === "vertical") {
                [ptop, pbottom, pleft, pright] = [pleft, pright, ptop, pbottom];
            }
            const x1 = (coords.left - elGridRect.left) / zoom - pleft;
            const y1 = (coords.top - elGridRect.top) / zoom - ptop;
            const elRect = this.annoCtx.graphics.drawRect(
                x1 - w.globals.barPadForNumericAxis,
                y1,
                coords.width / zoom + pleft + pright,
                coords.height / zoom + ptop + pbottom,
                anno.label.borderRadius,
                anno.label.style.background,
                1,
                anno.label.borderWidth,
                anno.label.borderColor,
                0
            );
            if (anno.id) {
                elRect.node.classList.add(anno.id);
            }
            return elRect;
        }
        annotationsBackground() {
            const w = this.w;
            const add = (anno, i, type) => {
                const annoLabel = w.dom.baseEl.querySelector(
                    `.apexcharts-${type}-annotations .apexcharts-${type}-annotation-label[rel='${i}']`
                );
                if (annoLabel) {
                    const parent = annoLabel.parentNode;
                    const elRect = this.addBackgroundToAnno(annoLabel, anno);
                    if (elRect) {
                        parent == null ? void 0 : parent.insertBefore(elRect.node, annoLabel);
                        const labelX = annoLabel.getAttribute("x");
                        if (labelX !== null) {
                            applyProgressiveReveal(elRect, parseFloat(labelX), w);
                        }
                        if (anno.label.mouseEnter) {
                            elRect.node.addEventListener(
                                "mouseenter",
                                anno.label.mouseEnter.bind(this, anno)
                            );
                        }
                        if (anno.label.mouseLeave) {
                            elRect.node.addEventListener(
                                "mouseleave",
                                anno.label.mouseLeave.bind(this, anno)
                            );
                        }
                        if (anno.label.click) {
                            elRect.node.addEventListener(
                                "click",
                                anno.label.click.bind(this, anno)
                            );
                        }
                    }
                }
            };
            w.config.annotations.xaxis.forEach(
                (anno, i) => add(anno, i, "xaxis")
            );
            w.config.annotations.yaxis.forEach(
                (anno, i) => add(anno, i, "yaxis")
            );
            w.config.annotations.points.forEach(
                (anno, i) => add(anno, i, "point")
            );
        }
        /**
         * @param {string} type
         * @param {Record<string, any>} anno
         */
        getY1Y2(type, anno) {
            var _a, _b;
            const w = this.w;
            const y = type === "y1" ? anno.y : anno.y2;
            let yP;
            let clipped = false;
            if (this.annoCtx.invertAxis) {
                const labels = w.config.xaxis.convertedCatToNumeric ? w.labelData.categoryLabels : w.labelData.labels;
                const catIndex = labels.indexOf(y);
                const xLabel = w.dom.baseEl.querySelector(
                    `.apexcharts-yaxis-texts-g text:nth-child(${catIndex + 1})`
                );
                yP = xLabel ? parseFloat((_a = xLabel.getAttribute("y")) != null ? _a : "0") : (w.layout.gridHeight / labels.length - 1) * (catIndex + 1) - w.globals.barHeight;
                if (anno.seriesIndex !== void 0 && w.globals.barHeight) {
                    yP -= w.globals.barHeight / 2 * (w.seriesData.series.length - 1) - w.globals.barHeight * anno.seriesIndex;
                }
            } else {
                const seriesIndex = w.globals.seriesYAxisMap[anno.yAxisIndex][0];
                const yPos = w.config.yaxis[anno.yAxisIndex].logarithmic ? new CoreUtils(this.w).getLogVal(
                        w.config.yaxis[anno.yAxisIndex].logBase,
                        y,
                        seriesIndex
                    ) / /** @type {any} */
                    w.globals.yLogRatio[seriesIndex] : (y - w.globals.minYArr[seriesIndex]) / (w.globals.yRange[seriesIndex] / w.layout.gridHeight);
                yP = w.layout.gridHeight - Math.min(Math.max(yPos, 0), w.layout.gridHeight);
                clipped = yPos > w.layout.gridHeight || yPos < 0;
                if (anno.marker && (anno.y === void 0 || anno.y === null)) {
                    yP = 0;
                }
                if ((_b = w.config.yaxis[anno.yAxisIndex]) == null ? void 0 : _b.reversed) {
                    yP = yPos;
                }
            }
            if (typeof y === "string" && y.includes("px")) {
                yP = parseFloat(y);
            }
            return {
                yP,
                clipped
            };
        }
        /**
         * @param {string} type
         * @param {Record<string, any>} anno
         */
        getX1X2(type, anno) {
            const w = this.w;
            const x = type === "x1" ? anno.x : anno.x2;
            const min = this.annoCtx.invertAxis ? w.globals.minY : w.globals.minX;
            const max = this.annoCtx.invertAxis ? w.globals.maxY : w.globals.maxX;
            const range = this.annoCtx.invertAxis ? w.globals.yRange[0] : w.globals.xRange;
            let clipped = false;
            let xP = this.annoCtx.inversedReversedAxis ? (max - x) / (range / w.layout.gridWidth) : (x - min) / (range / w.layout.gridWidth);
            if ((w.config.xaxis.type === "category" || w.config.xaxis.convertedCatToNumeric) && !this.annoCtx.invertAxis && !w.axisFlags.dataFormatXNumeric) {
                if (!w.config.chart.sparkline.enabled) {
                    xP = this.getStringX(x);
                }
            }
            if (typeof x === "string" && x.includes("px")) {
                xP = parseFloat(x);
            }
            if ((x === void 0 || x === null) && anno.marker) {
                xP = w.layout.gridWidth;
            }
            if (anno.seriesIndex !== void 0 && w.globals.barWidth && !this.annoCtx.invertAxis) {
                xP -= w.globals.barWidth / 2 * (w.seriesData.series.length - 1) - w.globals.barWidth * anno.seriesIndex;
            }
            if (typeof xP !== "number") {
                xP = 0;
                clipped = true;
            }
            if (parseFloat(xP.toFixed(10)) > parseFloat(w.layout.gridWidth.toFixed(10))) {
                xP = w.layout.gridWidth;
                clipped = true;
            } else if (xP < 0) {
                xP = 0;
                clipped = true;
            }
            return {
                x: xP,
                clipped
            };
        }
        /**
         * @param {number} x
         */
        getStringX(x) {
            var _a;
            const w = this.w;
            let rX = x;
            if (w.config.xaxis.convertedCatToNumeric && w.labelData.categoryLabels.length) {
                const strX = String(x);
                x = w.labelData.categoryLabels.findIndex(
                    (l) => String(l) === strX
                ) + 1;
            }
            const catIndex = w.labelData.labels.map(
                (item) => Array.isArray(item) ? item.join(" ") : item
            ).indexOf(x);
            const xLabel = w.dom.baseEl.querySelector(
                `.apexcharts-xaxis-texts-g text:nth-child(${catIndex + 1})`
            );
            if (xLabel) {
                rX = parseFloat((_a = xLabel.getAttribute("x")) != null ? _a : "0");
            }
            return rX;
        }
    };
    class XAnnotations {
        /**
         * @param {import('./Annotations').default} annoCtx
         */
        constructor(annoCtx) {
            this.w = annoCtx.w;
            this.annoCtx = annoCtx;
            this.invertAxis = this.annoCtx.invertAxis;
            this.helpers = new Helpers$2(this.annoCtx);
        }
        /**
         * @param {XAxisAnnotations} anno
         * @param {Element} parent
         * @param {number} index
         */
        addXaxisAnnotation(anno, parent, index) {
            const w = this.w;
            const result = this.helpers.getX1X2("x1", anno);
            let x1 = result.x;
            const clipX1 = result.clipped;
            let clipX2 = true;
            let x2;
            const text = anno.label.text;
            const strokeDashArray = anno.strokeDashArray;
            if (!Utils$1.isNumber(x1)) return;
            if (anno.x2 === null || typeof anno.x2 === "undefined") {
                if (!clipX1) {
                    const line = this.annoCtx.graphics.drawLine(
                        x1 + anno.offsetX,
                        // x1
                        0 + anno.offsetY,
                        // y1
                        x1 + anno.offsetX,
                        // x2
                        w.layout.gridHeight + anno.offsetY,
                        // y2
                        anno.borderColor,
                        // lineColor
                        strokeDashArray,
                        //dashArray
                        anno.borderWidth
                    );
                    parent.appendChild(line.node);
                    if (anno.id) {
                        line.node.classList.add(anno.id);
                    }
                    applyProgressiveReveal(line, x1 + anno.offsetX, w);
                }
            } else {
                const result2 = this.helpers.getX1X2("x2", anno);
                x2 = result2.x;
                clipX2 = result2.clipped;
                if (x2 < x1) {
                    const temp = x1;
                    x1 = x2;
                    x2 = temp;
                }
                const rect = this.annoCtx.graphics.drawRect(
                    x1 + anno.offsetX,
                    // x1
                    0 + anno.offsetY,
                    // y1
                    x2 - x1,
                    // x2
                    w.layout.gridHeight + anno.offsetY,
                    // y2
                    0,
                    // radius
                    anno.fillColor,
                    // color
                    anno.opacity,
                    // opacity,
                    1,
                    // strokeWidth
                    anno.borderColor,
                    // strokeColor
                    strokeDashArray
                    // stokeDashArray
                );
                rect.node.classList.add("apexcharts-annotation-rect");
                rect.attr("clip-path", `url(#gridRectMask${w.globals.cuid})`);
                parent.appendChild(rect.node);
                if (anno.id) {
                    rect.node.classList.add(anno.id);
                }
                applyProgressiveReveal(rect, x1 + anno.offsetX, w);
            }
            if (!(clipX1 && clipX2)) {
                const textRects = this.annoCtx.graphics.getTextRects(
                    text,
                    anno.label.style.fontSize
                );
                const textY = anno.label.position === "top" ? 4 : anno.label.position === "center" ? w.layout.gridHeight / 2 + (anno.label.orientation === "vertical" ? textRects.width / 2 : 0) : w.layout.gridHeight;
                const elText = this.annoCtx.graphics.drawText({
                    x: x1 + anno.label.offsetX,
                    y: textY + anno.label.offsetY - (anno.label.orientation === "vertical" ? anno.label.position === "top" ? textRects.width / 2 - 12 : -textRects.width / 2 : 0),
                    text,
                    textAnchor: anno.label.textAnchor,
                    fontSize: anno.label.style.fontSize,
                    fontFamily: anno.label.style.fontFamily,
                    fontWeight: anno.label.style.fontWeight,
                    foreColor: anno.label.style.color,
                    cssClass: `apexcharts-xaxis-annotation-label ${anno.label.style.cssClass} ${anno.id ? anno.id : ""}`
                });
                elText.attr({
                    rel: index
                });
                parent.appendChild(elText.node);
                applyProgressiveReveal(elText, x1 + anno.label.offsetX, w);
                this.annoCtx.helpers.setOrientations(anno, index);
            }
        }
        drawXAxisAnnotations() {
            const w = this.w;
            const elg = this.annoCtx.graphics.group({
                class: "apexcharts-xaxis-annotations"
            });
            w.config.annotations.xaxis.map(
                (anno, index) => {
                    this.addXaxisAnnotation(anno, elg.node, index);
                }
            );
            return elg;
        }
    }
    class YAnnotations {
        /**
         * @param {import('./Annotations').default} annoCtx
         */
        constructor(annoCtx) {
            this.w = annoCtx.w;
            this.annoCtx = annoCtx;
            this.helpers = new Helpers$2(this.annoCtx);
            this.axesUtils = new AxesUtils(this.annoCtx.w, {
                theme: this.annoCtx.theme,
                timeScale: this.annoCtx.timeScale
            });
        }
        /**
         * @param {YAxisAnnotations} anno
         * @param {Element} parent
         * @param {number} index
         */
        addYaxisAnnotation(anno, parent, index) {
            const w = this.w;
            const strokeDashArray = anno.strokeDashArray;
            let result = this.helpers.getY1Y2("y1", anno);
            let y1 = result.yP;
            const clipY1 = result.clipped;
            let y2;
            let clipY2 = true;
            let drawn = false;
            const text = anno.label.text;
            if (anno.y2 === null || typeof anno.y2 === "undefined") {
                if (!clipY1) {
                    drawn = true;
                    const line = this.annoCtx.graphics.drawLine(
                        0 + anno.offsetX,
                        // x1
                        y1 + anno.offsetY,
                        // y1
                        this._getYAxisAnnotationWidth(anno),
                        // x2
                        y1 + anno.offsetY,
                        // y2
                        anno.borderColor,
                        // lineColor
                        strokeDashArray,
                        // dashArray
                        anno.borderWidth
                    );
                    parent.appendChild(line.node);
                    if (anno.id) {
                        line.node.classList.add(anno.id);
                    }
                }
            } else {
                result = this.helpers.getY1Y2("y2", anno);
                y2 = result.yP;
                clipY2 = result.clipped;
                if (y2 > y1) {
                    const temp = y1;
                    y1 = y2;
                    y2 = temp;
                }
                if (!(clipY1 && clipY2)) {
                    drawn = true;
                    const rect = this.annoCtx.graphics.drawRect(
                        0 + anno.offsetX,
                        // x1
                        y2 + anno.offsetY,
                        // y1
                        this._getYAxisAnnotationWidth(anno),
                        // x2
                        y1 - y2,
                        // y2
                        0,
                        // radius
                        anno.fillColor,
                        // color
                        anno.opacity,
                        // opacity,
                        1,
                        // strokeWidth
                        anno.borderColor,
                        // strokeColor
                        strokeDashArray
                        // stokeDashArray
                    );
                    rect.node.classList.add("apexcharts-annotation-rect");
                    rect.attr("clip-path", `url(#gridRectMask${w.globals.cuid})`);
                    parent.appendChild(rect.node);
                    if (anno.id) {
                        rect.node.classList.add(anno.id);
                    }
                }
            }
            if (drawn) {
                const textX = anno.label.position === "right" ? w.layout.gridWidth : anno.label.position === "center" ? w.layout.gridWidth / 2 : 0;
                const elText = this.annoCtx.graphics.drawText({
                    x: textX + anno.label.offsetX,
                    y: (y2 != null ? y2 : y1) + anno.label.offsetY - 3,
                    text,
                    textAnchor: anno.label.textAnchor,
                    fontSize: anno.label.style.fontSize,
                    fontFamily: anno.label.style.fontFamily,
                    fontWeight: anno.label.style.fontWeight,
                    foreColor: anno.label.style.color,
                    cssClass: `apexcharts-yaxis-annotation-label ${anno.label.style.cssClass} ${anno.id ? anno.id : ""}`
                });
                elText.attr({
                    rel: index
                });
                parent.appendChild(elText.node);
            }
        }
        /**
         * @param {YAxisAnnotations} anno
         */
        _getYAxisAnnotationWidth(anno) {
            const w = this.w;
            let width = w.layout.gridWidth;
            if (anno.width.indexOf("%") > -1) {
                width = w.layout.gridWidth * parseInt(anno.width, 10) / 100;
            } else {
                width = parseInt(anno.width, 10);
            }
            return width + anno.offsetX;
        }
        drawYAxisAnnotations() {
            const w = this.w;
            const elg = this.annoCtx.graphics.group({
                class: "apexcharts-yaxis-annotations"
            });
            w.config.annotations.yaxis.forEach(
                (anno, index) => {
                    anno.yAxisIndex = this.axesUtils.translateYAxisIndex(anno.yAxisIndex);
                    if (!(this.axesUtils.isYAxisHidden(anno.yAxisIndex) && this.axesUtils.yAxisAllSeriesCollapsed(anno.yAxisIndex))) {
                        this.addYaxisAnnotation(anno, elg.node, index);
                    }
                }
            );
            return elg;
        }
    }
    class PointAnnotations {
        /**
         * @param {import('./Annotations').default} annoCtx
         */
        constructor(annoCtx) {
            this.w = annoCtx.w;
            this.annoCtx = annoCtx;
            this.helpers = new Helpers$2(this.annoCtx);
        }
        /**
         * @param {Record<string, any>} anno
         * @param {Element} parent
         * @param {number} index
         */
        addPointAnnotation(anno, parent, index) {
            const w = this.w;
            if (w.globals.collapsedSeriesIndices.indexOf(anno.seriesIndex) > -1) {
                return;
            }
            const resultX = this.helpers.getX1X2("x1", anno);
            const x = resultX.x;
            const clipX = resultX.clipped;
            const resultY = this.helpers.getY1Y2("y1", anno);
            const y = resultY.yP;
            const clipY = resultY.clipped;
            if (!Utils$1.isNumber(x)) return;
            if (!(clipY || clipX)) {
                const optsPoints = {
                    pSize: anno.marker.size,
                    pointStrokeWidth: anno.marker.strokeWidth,
                    pointFillColor: anno.marker.fillColor,
                    pointStrokeColor: anno.marker.strokeColor,
                    shape: anno.marker.shape,
                    pRadius: anno.marker.radius,
                    class: `apexcharts-point-annotation-marker ${anno.marker.cssClass} ${anno.id ? anno.id : ""}`
                };
                let point = this.annoCtx.graphics.drawMarker(
                    x + anno.marker.offsetX,
                    y + anno.marker.offsetY,
                    optsPoints
                );
                parent.appendChild(point.node);
                applyProgressiveReveal(point, x, w);
                const text = anno.label.text ? anno.label.text : "";
                const elText = this.annoCtx.graphics.drawText({
                    x: x + anno.label.offsetX,
                    y: y + anno.label.offsetY - anno.marker.size - parseFloat(anno.label.style.fontSize) / 1.6,
                    text,
                    textAnchor: anno.label.textAnchor,
                    fontSize: anno.label.style.fontSize,
                    fontFamily: anno.label.style.fontFamily,
                    fontWeight: anno.label.style.fontWeight,
                    foreColor: anno.label.style.color,
                    cssClass: `apexcharts-point-annotation-label ${anno.label.style.cssClass} ${anno.id ? anno.id : ""}`
                });
                elText.attr({
                    rel: index
                });
                parent.appendChild(elText.node);
                applyProgressiveReveal(elText, x, w);
                if (anno.customSVG.SVG) {
                    const g = this.annoCtx.graphics.group({
                        class: "apexcharts-point-annotations-custom-svg " + anno.customSVG.cssClass
                    });
                    g.attr({
                        transform: `translate(${x + anno.customSVG.offsetX}, ${y + anno.customSVG.offsetY})`
                    });
                    g.node.innerHTML = anno.customSVG.SVG;
                    parent.appendChild(g.node);
                }
                if (anno.image.path) {
                    const imgWidth = anno.image.width ? anno.image.width : 20;
                    const imgHeight = anno.image.height ? anno.image.height : 20;
                    point = this.annoCtx.addImage({
                        x: x + anno.image.offsetX - imgWidth / 2,
                        y: y + anno.image.offsetY - imgHeight / 2,
                        width: imgWidth,
                        height: imgHeight,
                        path: anno.image.path,
                        appendTo: ".apexcharts-point-annotations"
                    });
                }
                if (anno.mouseEnter) {
                    point.node.addEventListener(
                        "mouseenter",
                        anno.mouseEnter.bind(this, anno)
                    );
                }
                if (anno.mouseLeave) {
                    point.node.addEventListener(
                        "mouseleave",
                        anno.mouseLeave.bind(this, anno)
                    );
                }
                if (anno.click) {
                    point.node.addEventListener("click", anno.click.bind(this, anno));
                }
            }
        }
        drawPointAnnotations() {
            const w = this.w;
            const elg = this.annoCtx.graphics.group({
                class: "apexcharts-point-annotations"
            });
            w.config.annotations.points.map(
                (anno, index) => {
                    this.addPointAnnotation(anno, elg.node, index);
                }
            );
            return elg;
        }
    }
    class Annotations {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         */
        constructor(w, {
            theme = null,
            timeScale = null
        } = {}) {
            this.w = w;
            this.theme = theme;
            this.timeScale = timeScale;
            this.invertAxis = void 0;
            this.inversedReversedAxis = void 0;
            this.graphics = new Graphics(this.w);
            if (this.w.globals.isBarHorizontal) {
                this.invertAxis = true;
            }
            this.helpers = new Helpers$2(this);
            this.xAxisAnnotations = new XAnnotations(this);
            this.yAxisAnnotations = new YAnnotations(this);
            this.pointsAnnotations = new PointAnnotations(this);
            if (this.w.globals.isBarHorizontal && this.w.config.yaxis[0].reversed) {
                this.inversedReversedAxis = true;
            }
            this.xDivision = this.w.layout.gridWidth / this.w.globals.dataPoints;
        }
        drawAxesAnnotations() {
            const w = this.w;
            if (w.globals.axisCharts && w.globals.dataPoints) {
                const yAnnotations = this.yAxisAnnotations.drawYAxisAnnotations();
                const xAnnotations = this.xAxisAnnotations.drawXAxisAnnotations();
                const pointAnnotations = this.pointsAnnotations.drawPointAnnotations();
                const initialAnim = w.config.chart.animations.enabled;
                const annoArray = [yAnnotations, xAnnotations, pointAnnotations];
                const annoElArray = [
                    xAnnotations.node,
                    yAnnotations.node,
                    pointAnnotations.node
                ];
                const progressiveAnnos = w.config.chart.type === "line" || w.config.chart.type === "area" || w.config.chart.type === "rangeArea";
                const skipGroupHide = [progressiveAnnos, false, progressiveAnnos];
                for (let i = 0; i < 3; i++) {
                    w.dom.elGraphical.add(annoArray[i]);
                    if (initialAnim && !w.globals.resized && !w.globals.dataChanged) {
                        if (w.config.chart.type !== "scatter" && w.config.chart.type !== "bubble" && w.globals.dataPoints > 1 && !skipGroupHide[i]) {
                            annoElArray[i].classList.add("apexcharts-element-hidden");
                        }
                    }
                    w.globals.delayedElements.push({
                        el: annoElArray[i],
                        index: 0
                    });
                }
                this.helpers.annotationsBackground();
            }
        }
        drawImageAnnos() {
            const w = this.w;
            w.config.annotations.images.map((s) => {
                this.addImage(s);
            });
        }
        drawTextAnnos() {
            const w = this.w;
            w.config.annotations.texts.map((t) => {
                this.addText(t);
            });
        }
        /**
         * @param {Record<string, any>} anno
         * @param {Element} parent
         * @param {number} index
         */
        addXaxisAnnotation(anno, parent, index) {
            this.xAxisAnnotations.addXaxisAnnotation(anno, parent, index);
        }
        /**
         * @param {Record<string, any>} anno
         * @param {Element} parent
         * @param {number} index
         */
        addYaxisAnnotation(anno, parent, index) {
            this.yAxisAnnotations.addYaxisAnnotation(anno, parent, index);
        }
        /**
         * @param {Record<string, any>} anno
         * @param {Element} parent
         * @param {number} index
         */
        addPointAnnotation(anno, parent, index) {
            this.pointsAnnotations.addPointAnnotation(anno, parent, index);
        }
        /**
         * @param {Record<string, any>} params
         */
        addText(params) {
            const {
                x,
                y,
                text,
                textAnchor,
                foreColor,
                fontSize,
                fontFamily,
                fontWeight,
                cssClass,
                backgroundColor,
                borderWidth,
                strokeDashArray,
                borderRadius,
                borderColor,
                appendTo = ".apexcharts-svg",
                paddingLeft = 4,
                paddingRight = 4,
                paddingBottom = 2,
                paddingTop = 2
            } = params;
            const w = this.w;
            const elText = this.graphics.drawText({
                x,
                y,
                text,
                textAnchor: textAnchor || "start",
                fontSize: fontSize || "12px",
                fontWeight: fontWeight || "regular",
                fontFamily: fontFamily || w.config.chart.fontFamily,
                foreColor: foreColor || w.config.chart.foreColor,
                cssClass: "apexcharts-text " + cssClass ? cssClass : ""
            });
            const parent = w.dom.baseEl.querySelector(appendTo);
            if (parent) {
                parent.appendChild(elText.node);
            }
            const textRect = elText.bbox();
            if (text) {
                const elRect = this.graphics.drawRect(
                    textRect.x - paddingLeft,
                    textRect.y - paddingTop,
                    textRect.width + paddingLeft + paddingRight,
                    textRect.height + paddingBottom + paddingTop,
                    borderRadius,
                    backgroundColor ? backgroundColor : "transparent",
                    1,
                    borderWidth,
                    borderColor,
                    strokeDashArray
                );
                parent.insertBefore(elRect.node, elText.node);
            }
        }
        /**
         * @param {Record<string, any>} params
         */
        addImage(params) {
            const w = this.w;
            const {
                path,
                x = 0,
                y = 0,
                width = 20,
                height = 20,
                appendTo = ".apexcharts-svg"
            } = params;
            const img = w.dom.Paper.image(path);
            img.size(width, height).move(x, y);
            const parent = w.dom.baseEl.querySelector(appendTo);
            if (parent) {
                parent.appendChild(img.node);
            }
            return img;
        }
        // The addXaxisAnnotation method requires a parent class, and user calling this method externally on the chart instance may not specify parent, hence a different method
        /**
         * @param {Record<string, any>} params
         * @param {boolean} pushToMemory
         * @param {any} context
         */
        addXaxisAnnotationExternal(params, pushToMemory, context) {
            this.addAnnotationExternal({
                params,
                pushToMemory,
                context,
                type: "xaxis",
                contextMethod: context.addXaxisAnnotation
            });
            return context;
        }
        /**
         * @param {Record<string, any>} params
         * @param {boolean} pushToMemory
         * @param {any} context
         */
        addYaxisAnnotationExternal(params, pushToMemory, context) {
            this.addAnnotationExternal({
                params,
                pushToMemory,
                context,
                type: "yaxis",
                contextMethod: context.addYaxisAnnotation
            });
            return context;
        }
        /**
         * @param {Record<string, any>} params
         * @param {boolean} pushToMemory
         * @param {any} context
         */
        addPointAnnotationExternal(params, pushToMemory, context) {
            if (typeof this.invertAxis === "undefined") {
                this.invertAxis = context.w.globals.isBarHorizontal;
            }
            this.addAnnotationExternal({
                params,
                pushToMemory,
                context,
                type: "point",
                contextMethod: context.addPointAnnotation
            });
            return context;
        }
        /** @param {{params: any, pushToMemory: any, context: any, type: any, contextMethod: any}} opts */
        addAnnotationExternal({
            params,
            pushToMemory,
            context,
            type,
            contextMethod
        }) {
            const me = context;
            const w = me.w;
            const parent = w.dom.baseEl.querySelector(`.apexcharts-${type}-annotations`);
            const index = parent.childNodes.length + 1;
            const options2 = new Options();
            const axesAnno = Object.assign({},
                type === "xaxis" ? options2.xAxisAnnotation : type === "yaxis" ? options2.yAxisAnnotation : options2.pointAnnotation
            );
            const anno = Utils$1.extend(axesAnno, params);
            switch (type) {
                case "xaxis":
                    this.addXaxisAnnotation(anno, parent, index);
                    break;
                case "yaxis":
                    this.addYaxisAnnotation(anno, parent, index);
                    break;
                case "point":
                    this.addPointAnnotation(anno, parent, index);
                    break;
            }
            const axesAnnoLabel = w.dom.baseEl.querySelector(
                `.apexcharts-${type}-annotations .apexcharts-${type}-annotation-label[rel='${index}']`
            );
            const elRect = this.helpers.addBackgroundToAnno(axesAnnoLabel, anno);
            if (elRect) {
                parent.insertBefore(elRect.node, axesAnnoLabel);
            }
            if (pushToMemory) {
                w.globals.memory.methodsToExec.push({
                    context: me,
                    id: anno.id ? anno.id : Utils$1.randomId(),
                    method: contextMethod,
                    label: "addAnnotation",
                    params
                });
            }
            return context;
        }
        /**
         * @param {import('../../types/internal').ChartContext} ctx
         */
        clearAnnotations(ctx) {
            const w = ctx.w;
            const annos = w.dom.baseEl.querySelectorAll(
                ".apexcharts-yaxis-annotations, .apexcharts-xaxis-annotations, .apexcharts-point-annotations"
            );
            for (let i = w.globals.memory.methodsToExec.length - 1; i >= 0; i--) {
                if (w.globals.memory.methodsToExec[i].label === "addText" || w.globals.memory.methodsToExec[i].label === "addAnnotation") {
                    w.globals.memory.methodsToExec.splice(i, 1);
                }
            }
            Array.prototype.forEach.call(annos, (a) => {
                while (a.firstChild) {
                    a.removeChild(a.firstChild);
                }
            });
        }
        /**
         * @param {import('../../types/internal').ChartContext} ctx
         * @param {string} id
         */
        removeAnnotation(ctx, id) {
            const w = ctx.w;
            const annos = w.dom.baseEl.querySelectorAll(`.${id}`);
            if (annos) {
                w.globals.memory.methodsToExec.map((m, i) => {
                    if (m.id === id) {
                        w.globals.memory.methodsToExec.splice(i, 1);
                    }
                });
                Object.keys(w.config.annotations).forEach((key) => {
                    const annotationArray = w.config.annotations[key];
                    if (Array.isArray(annotationArray)) {
                        w.config.annotations[key] = annotationArray.filter((m) => m.id !== id);
                    }
                });
                Array.prototype.forEach.call(annos, (a) => {
                    a.parentElement.removeChild(a);
                });
            }
        }
    }
    ApexCharts.registerFeatures({
        annotations: Annotations
    });
    class KeyboardNavigation {
        /**
         * @param {import('../../types/internal').ChartStateW} w
         * @param {import('../../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this.seriesIndex = 0;
            this.dataPointIndex = 0;
            this.active = false;
            this._tooltipDismissed = false;
            this._focusedEl = null;
            this._hoveredBarEl = null;
            this._enlargedScatterMarker = null;
            this._onKeyDown = this._onKeyDown.bind(this);
            this._onFocus = this._onFocus.bind(this);
            this._onBlur = this._onBlur.bind(this);
            this._onLegendClick = this._onLegendClick.bind(this);
            this._onPointerDown = this._onPointerDown.bind(this);
            this._lastPointerDownAt = 0;
        }
        // ─── Public API ───────────────────────────────────────────────────────────
        /**
         * Called after the chart and tooltip have been fully rendered.
         * Attaches event listeners and makes the SVG keyboard-focusable.
         */
        init() {
            const w = this.w;
            const svgEl = w.dom.Paper.node;
            if (!svgEl) return;
            svgEl.setAttribute("tabindex", "0");
            svgEl.addEventListener("focus", this._onFocus);
            svgEl.addEventListener("blur", this._onBlur);
            svgEl.addEventListener("mousedown", this._onPointerDown, {
                capture: true
            });
            svgEl.addEventListener("pointerdown", this._onPointerDown, {
                capture: true
            });
            svgEl.addEventListener("touchstart", this._onPointerDown, {
                capture: true,
                passive: true
            });
            svgEl.addEventListener("keydown", this._onKeyDown, {
                passive: false
            });
            this.ctx.events.addEventListener("legendClick", this._onLegendClick);
        }
        /**
         * Removes all event listeners. Called from chart.destroy().
         */
        destroy() {
            const w = this.w;
            const svgEl = w.dom.Paper && w.dom.Paper.node;
            if (!svgEl) return;
            svgEl.removeEventListener("focus", this._onFocus);
            svgEl.removeEventListener("blur", this._onBlur);
            svgEl.removeEventListener("keydown", this._onKeyDown);
            svgEl.removeEventListener(
                "mousedown",
                this._onPointerDown,
                /** @type {any} */
                {
                    capture: true
                }
            );
            svgEl.removeEventListener(
                "pointerdown",
                this._onPointerDown,
                /** @type {any} */
                {
                    capture: true
                }
            );
            svgEl.removeEventListener(
                "touchstart",
                this._onPointerDown,
                /** @type {any} */
                {
                    capture: true
                }
            );
            this.ctx.events.removeEventListener("legendClick", this._onLegendClick);
        }
        // Records the timestamp of the most recent pointer-down inside the SVG.
        // `_onFocus` reads this to distinguish keyboard-driven focus (no recent
        // pointer activity) from mouse-driven focus (pointer event within the
        // last 100 ms). Stays a no-op for keyboard users.
        _onPointerDown() {
            this._lastPointerDownAt = Date.now();
        }
        /**
         * Called from Events.js keydown handler. Navigation keys are already handled
         * by the direct SVG listener (which can call preventDefault). This entry
         * point is intentionally a no-op — Events.js still fires the public keyDown
         * callback and fireEvent('keydown') independently.
         * @param {Event} _e
         */
        handleKey(_e) {}
        // ─── Focus / blur ─────────────────────────────────────────────────────────
        _onFocus() {
            if (!this._isNavEnabled()) return;
            if (Date.now() - this._lastPointerDownAt < 100) {
                return;
            }
            this.active = true;
            this._clampCursor();
            this._snapToVisibleRange();
            this._showCurrentPoint();
        }
        _onBlur() {
            this.active = false;
            this._tooltipDismissed = false;
            this._hideFocus();
        }
        // Called when the user clicks a legend item (collapse/expand a series).
        // Hide the keyboard-nav tooltip — the chart is about to re-render and the
        // current position may no longer be valid.
        _onLegendClick() {
            if (!this.active) return;
            this.active = false;
            this._hideFocus();
        }
        // ─── Key handler ──────────────────────────────────────────────────────────
        /**
         * @param {KeyboardEvent} e
         */
        _onKeyDown(e) {
            var _a, _b, _c;
            if (!this._isNavEnabled() || !this.active) return;
            if (e.shiftKey && (e.key === "ArrowRight" || e.key === "ArrowLeft") && this._canPan()) {
                e.preventDefault();
                this._panBy(e.key === "ArrowRight" ? 1 : -1);
                return;
            }
            switch (e.key) {
                case "ArrowRight":
                    e.preventDefault();
                    this._move(0, 1);
                    break;
                case "ArrowLeft":
                    e.preventDefault();
                    this._move(0, -1);
                    break;
                case "ArrowUp":
                    e.preventDefault();
                    this._move(-1, 0);
                    break;
                case "ArrowDown":
                    e.preventDefault();
                    this._move(1, 0);
                    break;
                case "Home":
                    e.preventDefault();
                    this.dataPointIndex = 0;
                    this._skipNullForward();
                    this._showCurrentPoint();
                    break;
                case "End":
                    e.preventDefault();
                    this.dataPointIndex = this._getDataPointCount(this.seriesIndex) - 1;
                    this._skipNullBackward();
                    this._showCurrentPoint();
                    break;
                case "Enter":
                case " ":
                    e.preventDefault();
                    this._fireClick();
                    break;
                case "+":
                case "=":
                    if (this._canZoom()) {
                        e.preventDefault();
                        (_a = this.ctx.toolbar) == null ? void 0 : _a.handleZoomIn();
                        this._announce("Zoomed in");
                    }
                    break;
                case "-":
                case "_":
                    if (this._canZoom()) {
                        e.preventDefault();
                        (_b = this.ctx.toolbar) == null ? void 0 : _b.handleZoomOut();
                        this._announce("Zoomed out");
                    }
                    break;
                case "0":
                    if (this._canZoom() && this.w.interact.zoomed) {
                        e.preventDefault();
                        (_c = this.ctx.toolbar) == null ? void 0 : _c.handleZoomReset();
                        this._announce("Zoom reset");
                    }
                    break;
                case "Escape":
                    e.preventDefault();
                    if (!this._tooltipDismissed) {
                        this._tooltipDismissed = true;
                        this._hideFocus();
                    } else {
                        this.active = false;
                        this._tooltipDismissed = false;
                        this._hideFocus();
                    }
                    break;
            }
        }
        // ─── Zoom / pan (keyboard alternatives for drag gestures) ─────────────────
        _canZoom() {
            const w = this.w;
            return Boolean(
                w.globals.axisCharts && w.config.chart.zoom && w.config.chart.zoom.enabled
            );
        }
        _canPan() {
            return this._canZoom();
        }
        /**
         * Shift the visible x-range by ~10% in the given direction.
         * @param {number} direction +1 = right, -1 = left
         */
        _panBy(direction) {
            const w = this.w;
            const toolbar = this.ctx.toolbar;
            if (!toolbar) return;
            const minX = Number(w.globals.minX);
            const maxX = Number(w.globals.maxX);
            if (!isFinite(minX) || !isFinite(maxX) || minX === maxX) return;
            const span = maxX - minX;
            const step = span * 0.1 * direction;
            toolbar.zoomUpdateOptions(minX + step, maxX + step);
            this._announce(direction > 0 ? "Panned right" : "Panned left");
        }
        // ─── Navigation ───────────────────────────────────────────────────────────
        /**
         * @param {number} dSeries
         * @param {number} dPoint
         */
        _move(dSeries, dPoint) {
            const w = this.w;
            const wrapAround = w.config.chart.accessibility.keyboard.navigation.wrapAround;
            if (dSeries !== 0) {
                const ttCtx = this.w.globals.tooltip;
                if (ttCtx && ttCtx.tConfig && ttCtx.tConfig.shared) {
                    const j = this.dataPointIndex;
                    const isActuallyShared = ttCtx.tooltipUtil && ttCtx.tooltipUtil.isXoverlap(j) && ttCtx.tooltipUtil.isInitialSeriesSameLen();
                    if (isActuallyShared) return;
                }
                const total = this._getSeriesCount();
                let si = this.seriesIndex + dSeries;
                let attempts = 0;
                while (attempts < total) {
                    if (si < 0) si = wrapAround ? total - 1 : 0;
                    if (si >= total) si = wrapAround ? 0 : total - 1;
                    if (!w.globals.collapsedSeriesIndices.includes(si)) break;
                    si += dSeries;
                    attempts++;
                }
                this.seriesIndex = si;
                const dpCount = this._getDataPointCount(si);
                if (this.dataPointIndex >= dpCount) {
                    this.dataPointIndex = dpCount - 1;
                }
            }
            if (dPoint !== 0) {
                const dpCount = this._getDataPointCount(this.seriesIndex);
                let di = this.dataPointIndex + dPoint;
                if (di < 0) di = wrapAround ? dpCount - 1 : 0;
                if (di >= dpCount) di = wrapAround ? 0 : dpCount - 1;
                this.dataPointIndex = di;
                if (dPoint > 0) {
                    this._skipNullForward();
                } else {
                    this._skipNullBackward();
                }
                if (!this._isDataPointVisible(this.seriesIndex, this.dataPointIndex)) {
                    this._snapToVisibleRangeInDirection(dPoint);
                }
            }
            this._showCurrentPoint();
        }
        /** Advance dataPointIndex forward past any nulls */
        _skipNullForward() {
            const w = this.w;
            const si = this.seriesIndex;
            const dpCount = this._getDataPointCount(si);
            let di = this.dataPointIndex;
            let attempts = 0;
            if (!Array.isArray(w.seriesData.series[si])) return;
            while (attempts < dpCount && w.seriesData.series[si][di] === null) {
                di = (di + 1) % dpCount;
                attempts++;
            }
            this.dataPointIndex = di;
        }
        /** Retreat dataPointIndex backward past any nulls */
        _skipNullBackward() {
            const w = this.w;
            const si = this.seriesIndex;
            const dpCount = this._getDataPointCount(si);
            let di = this.dataPointIndex;
            let attempts = 0;
            if (!Array.isArray(w.seriesData.series[si])) return;
            while (attempts < dpCount && w.seriesData.series[si][di] === null) {
                di = (di - 1 + dpCount) % dpCount;
                attempts++;
            }
            this.dataPointIndex = di;
        }
        // ─── Display ──────────────────────────────────────────────────────────────
        _showCurrentPoint() {
            const {
                seriesIndex: i,
                dataPointIndex: j
            } = this;
            const w = this.w;
            const ttCtx = w.globals.tooltip;
            if (!ttCtx || !ttCtx.ttItems) return;
            w.interact.capturedSeriesIndex = i;
            w.interact.capturedDataPointIndex = j;
            this._applyFocusClass(i, j);
            this._showTooltip(
                i,
                j,
                /** @type {any} */
                ttCtx
            );
        }
        _hideFocus() {
            const w = this.w;
            const ttCtx = (
                /** @type {any} */
                w.globals.tooltip
            );
            this._removeFocusClass();
            this._leaveHoveredBar();
            if (!ttCtx) return;
            if (ttCtx.marker) {
                ttCtx.marker.resetPointsSize();
            }
            this._enlargedScatterMarker = null;
            const tooltipEl = ttCtx.getElTooltip();
            if (tooltipEl) {
                tooltipEl.classList.remove("apexcharts-active");
                if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.announcements.enabled) {
                    tooltipEl.setAttribute("aria-hidden", "true");
                }
            }
            w.dom.baseEl.classList.remove("apexcharts-tooltip-active");
            const xcrosshairs = ttCtx.getElXCrosshairs();
            if (xcrosshairs) xcrosshairs.classList.remove("apexcharts-active");
        }
        // ─── Tooltip display per chart type ───────────────────────────────────────
        /**
         * @param {number} i
         * @param {number} j
         * @param {import('../tooltip/Tooltip').default} ttCtx
         */
        _showTooltip(i, j, ttCtx) {
            const w = this.w;
            const type = w.config.chart.type;
            const tooltipEl = ttCtx.getElTooltip();
            if (!tooltipEl) return;
            const cachedDims = ttCtx.getCachedDimensions();
            ttCtx.tooltipRect = {
                x: 0,
                y: 0,
                ttWidth: cachedDims.ttWidth || 0,
                ttHeight: cachedDims.ttHeight || 0
            };
            this._setSyntheticEvent(i, j, ttCtx);
            w.dom.baseEl.classList.add("apexcharts-tooltip-active");
            tooltipEl.classList.add("apexcharts-active");
            if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.announcements.enabled) {
                tooltipEl.removeAttribute("aria-hidden");
            }
            if (type === "pie" || type === "donut" || type === "polarArea") {
                this._showTooltipNonAxis(i, j, ttCtx, tooltipEl);
            } else if (type === "radialBar") {
                this._showTooltipRadialBar(i, j, ttCtx, tooltipEl);
            } else if (type === "heatmap" || type === "treemap") {
                this._showTooltipHeatTree(i, j, ttCtx, tooltipEl, type);
            } else if (type === "bar" || type === "candlestick" || type === "boxPlot" || type === "rangeBar") {
                this._showTooltipBar(i, j, ttCtx);
            } else {
                this._showTooltipAxisLine(i, j, ttCtx);
            }
        }
        /**
         * Set ttCtx.e to a synthetic mouse-event-like object whose clientX/Y point
         * to the centre of the current data-point element.  This ensures that any
         * positioning helper that reads ttCtx.e (followCursor path in moveTooltip,
         * moveStickyTooltipOverBars, moveDynamicPointsOnHover, etc.) gets valid
         * coordinates rather than crashing on undefined.
         *
         * For chart types that don't have a concrete SVG element per data point
         * (pie, radialBar) we fall back to the SVG centre.
         * @param {number} i
         * @param {number} j
         * @param {import('../tooltip/Tooltip').default} ttCtx
         */
        _setSyntheticEvent(i, j, ttCtx) {
            const w = this.w;
            const type = w.config.chart.type;
            let clientX = 0;
            let clientY = 0;
            const el = this._getFocusableElement(i, j);
            if (el) {
                const rect = el.getBoundingClientRect();
                clientX = rect.left + rect.width / 2;
                clientY = rect.top + rect.height / 2;
            } else if (w.globals.pointsArray && w.globals.pointsArray[i] && w.globals.pointsArray[i][j]) {
                const pt = w.globals.pointsArray[i][j];
                const elGrid = ttCtx.getElGrid && ttCtx.getElGrid();
                if (elGrid) {
                    const gridRect = elGrid.getBoundingClientRect();
                    clientX = gridRect.left + (pt[0] || 0);
                    clientY = gridRect.top + (pt[1] || 0);
                }
            } else {
                const svgEl = w.dom.Paper && w.dom.Paper.node;
                if (svgEl) {
                    const svgRect = svgEl.getBoundingClientRect();
                    clientX = svgRect.left + svgRect.width / 2;
                    clientY = svgRect.top + svgRect.height / 2;
                }
            }
            if (type === "line" || type === "area" || type === "rangeArea" || type === "scatter" || type === "bubble" || type === "radar") {
                if (w.globals.pointsArray && w.globals.pointsArray[i] && w.globals.pointsArray[i][j]) {
                    const pt = w.globals.pointsArray[i][j];
                    const elGrid = ttCtx.getElGrid && ttCtx.getElGrid();
                    if (elGrid) {
                        const gridRect = elGrid.getBoundingClientRect();
                        clientX = gridRect.left + (pt[0] || 0);
                        clientY = gridRect.top + (pt[1] || 0);
                    }
                }
            }
            ttCtx.e = {
                type: "mousemove",
                clientX,
                clientY
            };
        }
        /**
         * bar / column / candlestick / boxPlot / rangeBar
         * @param {number} i
         * @param {number} j
         * @param {import('../tooltip/Tooltip').default} ttCtx
         */
        _showTooltipBar(i, j, ttCtx) {
            var _a, _b, _c, _d;
            const w = this.w;
            const shared = ttCtx.tConfig.shared && (ttCtx.tooltipUtil.isXoverlap(j) || w.globals.isBarHorizontal) && ttCtx.tooltipUtil.isInitialSeriesSameLen();
            const rangeData = (
                /** @type {any} */
                (_d = (_c = (_b = (_a = w.rangeData.seriesRange) == null ? void 0 : _a[i]) == null ? void 0 : _b[j]) == null ? void 0 : _c.y) == null ? void 0 : _d[0]
            );
            ttCtx.tooltipLabels.drawSeriesTexts(__spreadProps(__spreadValues(__spreadValues({
                ttItems: ttCtx.ttItems,
                i,
                j
            }, (rangeData == null ? void 0 : rangeData.y1) !== void 0 && {
                y1: rangeData.y1
            }), (rangeData == null ? void 0 : rangeData.y2) !== void 0 && {
                y2: rangeData.y2
            }), {
                shared
            }));
            const parent = `.apexcharts-series[data\\:realIndex='${i}']`;
            const elPath = w.dom.Paper.findOne(
                `${parent} path[j='${j}'], ${parent} circle[j='${j}'], ${parent} rect[j='${j}']`
            );
            if (elPath) {
                this._leaveHoveredBar();
                const graphics = new Graphics(this.w, this.ctx);
                graphics.pathMouseEnter(elPath, null);
                this._hoveredBarEl = elPath;
            }
            if (w.globals.isBarHorizontal) {
                const barDomEl = elPath && elPath.node;
                if (barDomEl) {
                    const wrapRect = w.dom.elWrap.getBoundingClientRect();
                    const barRect = barDomEl.getBoundingClientRect();
                    const barCx = barRect.left - wrapRect.left;
                    const barCy = barRect.top - wrapRect.top;
                    const bh = barRect.height;
                    const bw = barRect.width;
                    const ttWidth = ttCtx.tooltipRect.ttWidth || 0;
                    const ttHeight = ttCtx.tooltipRect.ttHeight || 0;
                    const y = barCy + bh / 2 - ttHeight / 2;
                    let x = barCx + bw;
                    const baselineX = ttCtx.xyRatios && ttCtx.xyRatios.baseLineInvertedY != null ? ttCtx.xyRatios.baseLineInvertedY : wrapRect.width / 2;
                    if (barCx < baselineX) {
                        x = barCx - ttWidth;
                    }
                    const tooltipEl = ttCtx.getElTooltip();
                    if (tooltipEl) {
                        tooltipEl.style.left = x + "px";
                        tooltipEl.style.top = y + "px";
                    }
                }
            } else {
                ttCtx.tooltipPosition.moveStickyTooltipOverBars(j, i);
            }
        }
        /**
         * line / area / scatter / bubble / radar / rangeArea
         * @param {number} i
         * @param {number} j
         * @param {import('../tooltip/Tooltip').default} ttCtx
         */
        _showTooltipAxisLine(i, j, ttCtx) {
            const w = this.w;
            const type = w.config.chart.type;
            const sharedConfigured = ttCtx.tConfig.shared;
            const shared = sharedConfigured && ttCtx.tooltipUtil.isXoverlap(j) && ttCtx.tooltipUtil.isInitialSeriesSameLen();
            ttCtx.tooltipLabels.drawSeriesTexts({
                ttItems: ttCtx.ttItems,
                i,
                j,
                shared
            });
            const isScatterLike = type === "scatter" || type === "bubble";
            const hasVisibleMarkers = w.globals.markers.largestSize > 0;
            if (isScatterLike) {
                this._showScatterBubblePoint(i, j, ttCtx);
            } else if (hasVisibleMarkers) {
                if (shared) {
                    ttCtx.marker.enlargePoints(j);
                } else {
                    ttCtx.tooltipPosition.moveDynamicPointOnHover(j, i);
                }
            } else if (shared) {
                ttCtx.tooltipPosition.moveDynamicPointsOnHover(j);
            } else {
                ttCtx.tooltipPosition.moveDynamicPointOnHover(j, i);
            }
        }
        /**
         * Scatter / bubble: find the specific marker element for (seriesIndex i,
         * dataPointIndex j), resize only that element, and position the tooltip at
         * its coordinates — mirroring what Position.moveMarkers does for mouse hover.
         *
         * Unlike enlargePoints(j) which queries ALL series for rel===j (causing
         * multiple bubbles to enlarge and tooltip to land on the wrong one), this
         * method queries by both series index AND data-point index for precision.
         * @param {number} i
         * @param {number} j
         * @param {import('../tooltip/Tooltip').default} ttCtx
         */
        _showScatterBubblePoint(i, j, ttCtx) {
            const baseEl = this.w.dom.baseEl;
            if (this._enlargedScatterMarker) {
                ttCtx.marker.oldPointSize(this._enlargedScatterMarker);
                this._enlargedScatterMarker = null;
            }
            const seriesEl = baseEl.querySelector(
                `.apexcharts-series[data\\:realIndex='${i}']`
            );
            if (!seriesEl) return;
            const markerEl = seriesEl.querySelector(`.apexcharts-marker[rel='${j}']`);
            if (!markerEl) return;
            ttCtx.marker.enlargeCurrentPoint(j, markerEl);
            this._enlargedScatterMarker = markerEl;
        }
        /**
         * pie / donut / polarArea
         * @param {number} i
         * @param {number} j
         * @param {import('../tooltip/Tooltip').default} ttCtx
         * @param {HTMLElement} tooltipEl
         */
        _showTooltipNonAxis(i, j, ttCtx, tooltipEl) {
            var _a, _b;
            const w = this.w;
            ttCtx.tooltipLabels.drawSeriesTexts({
                ttItems: ttCtx.ttItems,
                i: j,
                shared: false
            });
            const tooltipBound = tooltipEl.getBoundingClientRect();
            const ttWidth = tooltipBound.width || ttCtx.tooltipRect.ttWidth || 0;
            const ttHeight = tooltipBound.height || ttCtx.tooltipRect.ttHeight || 0;
            const sliceEl = w.dom.baseEl.querySelector(`.apexcharts-pie-area[j='${j}']`);
            if (sliceEl) {
                const cx = parseFloat((_a = sliceEl.getAttribute("data:cx")) != null ? _a : "");
                const cy = parseFloat((_b = sliceEl.getAttribute("data:cy")) != null ? _b : "");
                if (!isNaN(cx) && !isNaN(cy)) {
                    const svgBound = w.dom.Paper.node.getBoundingClientRect();
                    const wrapBound = w.dom.elWrap.getBoundingClientRect();
                    const offsetX = svgBound.left - wrapBound.left;
                    const offsetY = svgBound.top - wrapBound.top;
                    tooltipEl.style.left = offsetX + cx - ttWidth / 2 + "px";
                    tooltipEl.style.top = offsetY + cy - ttHeight - 10 + "px";
                }
            }
        }
        /**
         * radialBar — one ring per series, single value each
         * @param {number} i
         * @param {any} _j
         * @param {import('../tooltip/Tooltip').default} ttCtx
         * @param {HTMLElement} tooltipEl
         */
        _showTooltipRadialBar(i, _j, ttCtx, tooltipEl) {
            var _a;
            const w = this.w;
            ttCtx.tooltipLabels.drawSeriesTexts({
                ttItems: ttCtx.ttItems,
                i,
                shared: false
            });
            const {
                ttWidth = 0, ttHeight = 0
            } = ttCtx.getCachedDimensions();
            const arcEl = w.dom.baseEl.querySelector(
                `.apexcharts-radialbar-series[data\\:realIndex='${i}'] path`
            );
            if (arcEl) {
                const angle = parseFloat((_a = arcEl.getAttribute("data:angle")) != null ? _a : "") || 0;
                const initialAngle = w.config.plotOptions.radialBar.startAngle || 0;
                const midAngle = initialAngle + angle / 2;
                const centerX = w.layout.gridWidth / 2;
                const centerY = w.layout.gridHeight / 2;
                const radialSize = w.globals.radialSize || Math.min(w.layout.gridWidth, w.layout.gridHeight) / 2;
                const seriesCount = w.seriesData.series.length;
                const trackSize = radialSize / Math.max(seriesCount, 1);
                const outerRadius = radialSize - i * trackSize;
                const innerRadius = outerRadius - trackSize;
                const ringRadius = (outerRadius + innerRadius) / 2;
                const centroid = Utils$1.polarToCartesian(
                    centerX,
                    centerY,
                    ringRadius,
                    midAngle
                );
                const x = centroid.x + (w.layout.translateX || 0);
                const y = centroid.y + (w.layout.translateY || 0);
                tooltipEl.style.left = x - ttWidth / 2 + "px";
                tooltipEl.style.top = y - ttHeight - 10 + "px";
            }
        }
        /**
         * heatmap / treemap — position tooltip using element bounding rect
         * @param {number} i
         * @param {number} j
         * @param {import('../tooltip/Tooltip').default} ttCtx
         * @param {HTMLElement} tooltipEl
         * @param {string} type
         */
        _showTooltipHeatTree(i, j, ttCtx, tooltipEl, type) {
            var _a, _b;
            const w = this.w;
            ttCtx.tooltipLabels.drawSeriesTexts({
                ttItems: ttCtx.ttItems,
                i,
                j,
                shared: false
            });
            const tooltipRect = tooltipEl.getBoundingClientRect();
            const ttWidth = tooltipRect.width || ttCtx.tooltipRect.ttWidth || 0;
            const ttHeight = tooltipRect.height || ttCtx.tooltipRect.ttHeight || 0;
            const rectClass = type === "heatmap" ? "apexcharts-heatmap-rect" : "apexcharts-treemap-rect";
            const cell = w.dom.baseEl.querySelector(`.${rectClass}[i='${i}'][j='${j}']`);
            if (cell) {
                const wrapRect = w.dom.elWrap.getBoundingClientRect();
                const cellRect = cell.getBoundingClientRect();
                const cellCx = cellRect.left - wrapRect.left;
                const cellCy = cellRect.top - wrapRect.top;
                const cellWidth = cellRect.width;
                const cellHeight = cellRect.height;
                const cx = parseFloat((_a = cell.getAttribute("cx")) != null ? _a : "");
                const cellWidthAttr = parseFloat((_b = cell.getAttribute("width")) != null ? _b : "");
                ttCtx.tooltipPosition.moveXCrosshairs(cx + cellWidthAttr / 2);
                let x = cellCx + cellWidth + ttWidth / 2;
                const y = cellCy + cellHeight / 2 - ttHeight / 2;
                if (cellCx + cellWidth > w.layout.gridWidth / 2) {
                    x = cellCx - ttWidth / 2;
                }
                tooltipEl.style.left = x + "px";
                tooltipEl.style.top = y + "px";
            }
        }
        // ─── Focus class management ───────────────────────────────────────────────
        /**
         * @param {number} i
         * @param {number} j
         */
        _applyFocusClass(i, j) {
            this._removeFocusClass();
            const el = this._getFocusableElement(i, j);
            if (el) {
                el.classList.add("apexcharts-keyboard-focused");
                el.setAttribute("role", "img");
                const label = this._buildPointLabel(i, j);
                if (label) el.setAttribute("aria-label", label);
                this._focusedEl = el;
            }
        }
        _removeFocusClass() {
            if (this._focusedEl) {
                this._focusedEl.classList.remove("apexcharts-keyboard-focused");
                this._focusedEl.removeAttribute("role");
                this._focusedEl.removeAttribute("aria-label");
                this._focusedEl = null;
            }
        }
        /**
         * Build an accessible label for the data point at (i, j) using the same
         * formatters the visible tooltip / axis labels use, so SR output matches
         * the visual presentation.
         * @param {number} i
         * @param {number} j
         * @returns {string}
         */
        _buildPointLabel(i, j) {
            var _a, _b, _c, _d, _e, _f, _g, _h;
            const w = this.w;
            const type = w.config.chart.type;
            const seriesNames = w.seriesData.seriesNames || [];
            const series = w.seriesData.series || [];
            if (type === "pie" || type === "donut" || type === "polarArea") {
                const sliceLabel = (_b = ((_a = w.labelData) == null ? void 0 : _a.labels) && w.labelData.labels[j]) != null ? _b : "";
                const value = Array.isArray(series) ? series[j] : "";
                return sliceLabel ? `${sliceLabel}: ${value}` : `${value}`;
            }
            if (type === "radialBar") {
                const seriesName2 = seriesNames[i] || `Series ${i + 1}`;
                const value = Array.isArray(series) ? series[i] : "";
                return `${seriesName2}: ${value}`;
            }
            const seriesName = seriesNames[i] || `Series ${i + 1}`;
            const row = Array.isArray(series[i]) ? series[i] : [];
            const rawValue = row[j];
            let formattedValue = rawValue == null ? "" : String(rawValue);
            const yFormatter = (_d = (_c = w.formatters) == null ? void 0 : _c.yLabelFormatters) == null ? void 0 : _d[i];
            if (typeof yFormatter === "function") {
                try {
                    formattedValue = yFormatter(rawValue, {
                        seriesIndex: i,
                        dataPointIndex: j,
                        w
                    });
                } catch (e) {}
            }
            let category = "";
            const categoryLabels = (_e = w.labelData) == null ? void 0 : _e.categoryLabels;
            const seriesX = (_g = (_f = w.seriesData) == null ? void 0 : _f.seriesX) == null ? void 0 : _g[i];
            if (Array.isArray(categoryLabels) && categoryLabels[j] != null) {
                category = String(categoryLabels[j]);
            } else if (Array.isArray(seriesX) && seriesX[j] != null) {
                const xFormatter = (_h = w.formatters) == null ? void 0 : _h.xLabelFormatter;
                if (typeof xFormatter === "function") {
                    try {
                        category = String(
                            xFormatter(seriesX[j], {
                                seriesIndex: i,
                                dataPointIndex: j,
                                w
                            })
                        );
                    } catch (e) {
                        category = String(seriesX[j]);
                    }
                } else {
                    category = String(seriesX[j]);
                }
            }
            return category ? `${seriesName}: ${formattedValue}, ${category}` : `${seriesName}: ${formattedValue}`;
        }
        _leaveHoveredBar() {
            if (this._hoveredBarEl) {
                const graphics = new Graphics(this.w, this.ctx);
                graphics.pathMouseLeave(this._hoveredBarEl, null);
                this._hoveredBarEl = null;
            }
        }
        /**
         * @param {number} i
         * @param {number} j
         */
        _getFocusableElement(i, j) {
            const w = this.w;
            const type = w.config.chart.type;
            const baseEl = w.dom.baseEl;
            if (type === "pie" || type === "donut" || type === "polarArea") {
                return baseEl.querySelector(`.apexcharts-pie-area[j='${j}']`);
            }
            if (type === "heatmap") {
                return baseEl.querySelector(
                    `.apexcharts-heatmap-rect[i='${i}'][j='${j}']`
                );
            }
            if (type === "treemap") {
                return baseEl.querySelector(
                    `.apexcharts-treemap-rect[i='${i}'][j='${j}']`
                );
            }
            if (type === "radialBar") {
                return baseEl.querySelector(
                    `.apexcharts-radialbar-series[data\\:realIndex='${i}'] path`
                );
            }
            if (type === "bar" || type === "candlestick" || type === "boxPlot" || type === "rangeBar") {
                return baseEl.querySelector(
                    `.apexcharts-series[data\\:realIndex='${i}'] path[j='${j}']`
                );
            }
            const marker = baseEl.querySelector(
                `.apexcharts-series[data\\:realIndex='${i}'] .apexcharts-marker[rel='${j}']`
            );
            return marker || null;
        }
        // ─── Click / Enter ────────────────────────────────────────────────────────
        _fireClick() {
            const w = this.w;
            const ttCtx = w.globals.tooltip;
            if (!ttCtx) return;
            const syntheticEvent = {
                type: "mouseup",
                clientX: 0,
                clientY: 0
            };
            ttCtx.markerClick(syntheticEvent, this.seriesIndex, this.dataPointIndex);
        }
        // ─── Helpers ──────────────────────────────────────────────────────────────
        _isNavEnabled() {
            const a11y = this.w.config.chart.accessibility;
            return a11y.enabled && a11y.keyboard.enabled && a11y.keyboard.navigation.enabled;
        }
        _getSeriesCount() {
            const w = this.w;
            const type = w.config.chart.type;
            if (type === "pie" || type === "donut" || type === "polarArea") {
                return 1;
            }
            return w.seriesData.series.length;
        }
        /**
         * @param {number} si
         */
        _getDataPointCount(si) {
            const w = this.w;
            const type = w.config.chart.type;
            if (type === "pie" || type === "donut" || type === "polarArea") {
                return w.seriesData.series.length;
            }
            const series = w.seriesData.series;
            return series[si] && Array.isArray(series[si]) ? series[si].length : 0;
        }
        _clampCursor() {
            const seriesCount = this._getSeriesCount();
            if (this.seriesIndex >= seriesCount) this.seriesIndex = seriesCount - 1;
            if (this.seriesIndex < 0) this.seriesIndex = 0;
            const dpCount = this._getDataPointCount(this.seriesIndex);
            if (this.dataPointIndex >= dpCount) this.dataPointIndex = dpCount - 1;
            if (this.dataPointIndex < 0) this.dataPointIndex = 0;
        }
        /**
         * When the chart is zoomed in, the current dataPointIndex may point to a
         * data point that is outside the visible viewport. Snap the cursor to the
         * first data point whose x-value falls within [minX, maxX].
         *
         * Only adjusts when w.seriesData.seriesX is populated (numeric/datetime axes).
         * Category-only charts (seriesX entries are strings or auto-indices) are
         * unaffected — all points are always visible.
         */
        _snapToVisibleRange() {
            const w = this.w;
            const gl = w.globals;
            const si = this.seriesIndex;
            if (!w.interact.zoomed) return;
            const seriesX = w.seriesData.seriesX && w.seriesData.seriesX[si];
            if (!seriesX || !seriesX.length) return;
            const minX = gl.minX;
            const maxX = gl.maxX;
            if (minX === void 0 || maxX === void 0) return;
            const currentX = seriesX[this.dataPointIndex];
            if (currentX >= minX && currentX <= maxX) return;
            const dpCount = seriesX.length;
            for (let di = 0; di < dpCount; di++) {
                if (seriesX[di] >= minX && seriesX[di] <= maxX) {
                    this.dataPointIndex = di;
                    return;
                }
            }
        }
        /**
         * Snap to the nearest visible data point in the given navigation direction.
         * direction > 0 → find the first visible point (left boundary of zoomed range)
         * direction < 0 → find the last visible point (right boundary of zoomed range)
         * @param {number} direction
         */
        _snapToVisibleRangeInDirection(direction) {
            const w = this.w;
            const gl = w.globals;
            const si = this.seriesIndex;
            const seriesX = w.seriesData.seriesX && w.seriesData.seriesX[si];
            if (!seriesX || !seriesX.length) return;
            const minX = gl.minX;
            const maxX = gl.maxX;
            if (minX === void 0 || maxX === void 0) return;
            const dpCount = seriesX.length;
            if (direction >= 0) {
                for (let di = 0; di < dpCount; di++) {
                    if (seriesX[di] >= minX && seriesX[di] <= maxX) {
                        this.dataPointIndex = di;
                        return;
                    }
                }
            } else {
                for (let di = dpCount - 1; di >= 0; di--) {
                    if (seriesX[di] >= minX && seriesX[di] <= maxX) {
                        this.dataPointIndex = di;
                        return;
                    }
                }
            }
        }
        /**
         * Check whether the data point at (si, di) is within the current visible
         * x-axis range. Used to skip out-of-viewport points during keyboard nav.
         * @param {number} si
         * @param {number} di
         */
        _isDataPointVisible(si, di) {
            const w = this.w;
            const gl = w.globals;
            if (!w.interact.zoomed) return true;
            const seriesX = w.seriesData.seriesX && w.seriesData.seriesX[si];
            if (!seriesX) return true;
            const x = seriesX[di];
            if (x === void 0) return true;
            return x >= gl.minX && x <= gl.maxX;
        }
        /**
         * Push a short status message to the visually-hidden aria-live region so
         * screen readers announce zoom / pan / reset events that have no inherent
         * tooltip update. Silently no-op if the region is missing or announcements
         * are disabled.
         * @param {string} message
         */
        _announce(message) {
            const w = this.w;
            if (!w.config.chart.accessibility.announcements.enabled) return;
            const baseEl = w.dom.baseEl;
            if (!baseEl) return;
            const region = baseEl.querySelector(".apexcharts-sr-status");
            if (!region) return;
            region.textContent = "";
            setTimeout(() => {
                region.textContent = message;
            }, 0);
        }
    }
    ApexCharts.registerFeatures({
        keyboardNavigation: KeyboardNavigation
    });
    const BAR_FAMILY = /* @__PURE__ */ new Set(["bar", "funnel", "pyramid"]);
    const RADIAL_FAMILY = /* @__PURE__ */ new Set(["pie", "donut", "polarArea", "radialBar", "gauge"]);

    function familyOf(type) {
        if (BAR_FAMILY.has(type)) return "bar";
        if (RADIAL_FAMILY.has(type)) return "radial";
        return null;
    }
    class MorphTypeChange {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.w = w;
            this.ctx = ctx;
            this._snapshot = null;
        }
        /**
         * @param {string} fromType
         * @param {string} toType
         * @returns {boolean}
         */
        canMorphTypes(fromType, toType) {
            if (fromType === toType) return false;
            const ff = familyOf(fromType);
            const tf = familyOf(toType);
            if (!ff || !tf) return false;
            return true;
        }
        /**
         * @param {string} fromType
         * @param {string} toType
         * @param {any} newSeries
         * @returns {boolean}
         */
        isCompatibleSeriesShape(fromType, toType, newSeries) {
            if (!Array.isArray(newSeries) || newSeries.length === 0) return false;
            const ff = familyOf(fromType);
            const tf = familyOf(toType);
            if (tf === "radial") {
                return newSeries.every((v) => typeof v === "number");
            }
            if (tf === "bar") {
                return newSeries.every(
                    (s) => s && typeof s === "object" && Array.isArray(s.data)
                );
            }
            return ff !== null && tf !== null;
        }
        /**
         * Capture the live DOM of the *current* (outgoing) chart and stash it on
         * this module. Called from `apexcharts._updateOptions` before the config
         * merge that flips `chart.type`.
         *
         * Returns true if a morph is queued — caller doesn't need the value, but
         * tests use it.
         *
         * @param {{ fromType: string, toType: string, newSeries: any }} args
         * @returns {boolean}
         */
        captureBeforeDestroy({
            fromType,
            toType,
            newSeries
        }) {
            this._snapshot = null;
            if (!Environment.isBrowser()) return false;
            const animCfg = this.w.config.chart.animations;
            if (!animCfg || animCfg.enabled === false) return false;
            if (animCfg.chartTypeMorph && animCfg.chartTypeMorph.enabled === false)
                return false;
            if (animCfg.respectReducedMotion && prefersReducedMotion()) return false;
            if (!this.canMorphTypes(fromType, toType)) return false;
            if (!this.isCompatibleSeriesShape(fromType, toType, newSeries)) return false;
            const captured = this._captureFromDOM(fromType);
            if (!captured.length) return false;
            const mapping = this._buildMapping(captured, fromType, toType, newSeries);
            if (mapping.size === 0) return false;
            this._snapshot = {
                fromType,
                toType,
                mapping,
                oldLayout: {
                    translateX: this.w.layout.translateX || 0,
                    translateY: this.w.layout.translateY || 0
                }
            };
            this.w.globals.previousPaths = [];
            return true;
        }
        /**
         * Walk the outgoing chart's DOM and collect path `d` strings keyed by
         * (realIndex, j). The selectors are scoped to the chart family — bar
         * elements have `pathTo` set; pie/radial elements use their final `d`.
         *
         * @param {string} fromType
         * @returns {Array<{ realIndex: number, j: number, d: string, fill: string|null }>}
         */
        _captureFromDOM(fromType) {
            var _a;
            const baseEl = (_a = this.w.globals.dom) == null ? void 0 : _a.baseEl;
            if (!baseEl) return [];
            const captured = [];
            const fam = familyOf(fromType);
            if (fam === "bar") {
                const seriesNodes = baseEl.querySelectorAll(
                    ".apexcharts-bar-series .apexcharts-series"
                );
                seriesNodes.forEach((seriesNode) => {
                    var _a2;
                    const realIndex = parseInt(
                        (_a2 = seriesNode.getAttribute("data:realIndex")) != null ? _a2 : "0",
                        10
                    );
                    const paths = seriesNode.querySelectorAll("path[pathTo]");
                    paths.forEach((p, j) => {
                        const d = p.getAttribute("pathTo") || p.getAttribute("d");
                        if (!d) return;
                        captured.push({
                            realIndex,
                            j,
                            d,
                            fill: p.getAttribute("fill")
                        });
                    });
                });
            } else if (fam === "radial") {
                if (fromType === "radialBar" || fromType === "gauge") {
                    const centerX = this.w.layout.gridWidth / 2;
                    const centerY = Math.min(this.w.layout.gridWidth, this.w.layout.gridHeight) / 2;
                    const rings = baseEl.querySelectorAll(
                        ".apexcharts-radial-series .apexcharts-radialbar-area"
                    );
                    rings.forEach((p) => {
                        var _a2;
                        const parent = (
                            /** @type {Element|null} */
                            p.parentElement
                        );
                        const realIndex = parseInt(
                            (_a2 = parent == null ? void 0 : parent.getAttribute("data:realIndex")) != null ? _a2 : "0",
                            10
                        );
                        const rawD = p.getAttribute("d");
                        if (!rawD) return;
                        const strokeWidth = parseFloat(p.getAttribute("stroke-width") || "0");
                        const d = strokeWidth > 1 ? this._radialArcToFilledSegment(
                            rawD,
                            strokeWidth,
                            centerX,
                            centerY
                        ) || rawD : rawD;
                        captured.push({
                            realIndex,
                            j: 0,
                            d,
                            fill: p.getAttribute("stroke")
                        });
                    });
                } else {
                    const slices = baseEl.querySelectorAll(
                        ".apexcharts-pie-series .apexcharts-pie-area"
                    );
                    slices.forEach(
                        (p, i) => {
                            const d = p.getAttribute("d");
                            if (!d) return;
                            captured.push({
                                realIndex: i,
                                j: 0,
                                d,
                                fill: p.getAttribute("fill")
                            });
                        }
                    );
                }
            }
            return captured;
        }
        /**
         * Convert a radialBar's stroked open-arc `d` ("M x1 y1 A r r 0 large sweep
         * x2 y2") into a closed donut-segment polygon whose FILLED rendering
         * visually matches the original stroked arc — needed because the morph
         * target (pie/donut/polarArea) renders by fill, not stroke. Returns null
         * if the input doesn't match the expected M-then-A shape.
         *
         * @param {string} rawD
         * @param {number} strokeWidth
         * @param {number} centerX
         * @param {number} centerY
         * @returns {string | null}
         */
        _radialArcToFilledSegment(rawD, strokeWidth, centerX, centerY) {
            const m = rawD.match(
                /M\s*(-?[\d.]+)\s+(-?[\d.]+)\s+A\s*(-?[\d.]+)\s+(?:-?[\d.]+)\s+(?:-?[\d.]+)\s+(\d)\s+(\d)\s+(-?[\d.]+)\s+(-?[\d.]+)/
            );
            if (!m) return null;
            const x1 = parseFloat(m[1]);
            const y1 = parseFloat(m[2]);
            const r = parseFloat(m[3]);
            const large = parseInt(m[4], 10);
            const sweep = parseInt(m[5], 10);
            const x2 = parseFloat(m[6]);
            const y2 = parseFloat(m[7]);
            if (!isFinite(r) || r <= 0) return null;
            const half = strokeWidth / 2;
            const rOuter = r + half;
            const rInner = Math.max(0, r - half);
            const proj = (px, py, newR) => {
                const dx = px - centerX;
                const dy = py - centerY;
                const dist = Math.sqrt(dx * dx + dy * dy);
                if (dist === 0) return {
                    x: centerX,
                    y: centerY
                };
                const k = newR / dist;
                return {
                    x: centerX + dx * k,
                    y: centerY + dy * k
                };
            };
            const o1 = proj(x1, y1, rOuter);
            const o2 = proj(x2, y2, rOuter);
            const i1 = proj(x1, y1, rInner);
            const i2 = proj(x2, y2, rInner);
            const sweepBack = sweep ? 0 : 1;
            return `M ${o1.x} ${o1.y} A ${rOuter} ${rOuter} 0 ${large} ${sweep} ${o2.x} ${o2.y} L ${i2.x} ${i2.y} A ${rInner} ${rInner} 0 ${large} ${sweepBack} ${i1.x} ${i1.y} Z`;
        }
        /**
         * Build a closed donut-segment path for the given polar arc geometry. Used
         * by Radial.drawArcs when morphing FROM a filled wedge (pie/donut/polarArea)
         * TO a radialBar arc: the final radialBar is rendered as a stroked open arc,
         * but during the morph we tween d toward this closed-segment form (which
         * looks identical to the stroked arc when filled with the same color) so
         * the in-between frames remain visually consistent filled shapes rather
         * than a thick-outlined wedge.
         *
         * @param {number} centerX
         * @param {number} centerY
         * @param {number} ringRadius - centerline radius of the radialBar ring
         * @param {number} strokeWidth - the ring's stroke thickness
         * @param {number} startAngleDeg - in degrees, 0° = top (12 o'clock)
         * @param {number} endAngleDeg
         * @returns {string}
         */
        buildRingSegmentPath(centerX, centerY, ringRadius, strokeWidth, startAngleDeg, endAngleDeg) {
            const halfStroke = strokeWidth / 2;
            const rOuter = ringRadius + halfStroke;
            const rInner = Math.max(0, ringRadius - halfStroke);
            const sRad = (startAngleDeg - 90) * Math.PI / 180;
            const eRad = (endAngleDeg - 90) * Math.PI / 180;
            const oStart = {
                x: centerX + rOuter * Math.cos(sRad),
                y: centerY + rOuter * Math.sin(sRad)
            };
            const oEnd = {
                x: centerX + rOuter * Math.cos(eRad),
                y: centerY + rOuter * Math.sin(eRad)
            };
            const iStart = {
                x: centerX + rInner * Math.cos(sRad),
                y: centerY + rInner * Math.sin(sRad)
            };
            const iEnd = {
                x: centerX + rInner * Math.cos(eRad),
                y: centerY + rInner * Math.sin(eRad)
            };
            const sweep = endAngleDeg > startAngleDeg ? 1 : 0;
            const large = Math.abs(endAngleDeg - startAngleDeg) > 180 ? 1 : 0;
            return `M ${oStart.x} ${oStart.y} A ${rOuter} ${rOuter} 0 ${large} ${sweep} ${oEnd.x} ${oEnd.y} L ${iEnd.x} ${iEnd.y} A ${rInner} ${rInner} 0 ${large} ${1 - sweep} ${iStart.x} ${iStart.y} Z`;
        }
        /**
         * @returns {string | null} the chart-type the active snapshot was captured
         *   from, or null when no morph is in flight.
         */
        getFromType() {
            return this._snapshot ? this._snapshot.fromType : null;
        }
        /**
         * Build a (targetKey → captured) map. The targetKey matches the lookup
         * pattern each chart-type renderer uses when it asks
         * `getInitialPathFor(realIndex, j)`.
         *
         * Strategy: flatten the captured items into a linear sequence (matching the
         * source chart's natural DOM iteration order: series-then-point for bar,
         * ring-by-ring for radial), then walk the target's iteration positions in
         * the same order and pair them up 1:1. This handles every supported shape
         * without per-pair branching:
         *
         *   - bar (1 series, N pts) ↔ radial-family (N items)  → linear[k] ↔ k
         *   - bar (M series, 1 pt)  ↔ radial-family (M items)  → linear[k] ↔ k
         *   - radial-family (N items) ↔ bar (any matching shape) → linear[k] ↔ flat target
         *   - radial-family ↔ radial-family                    → linear[k] ↔ k
         *
         * @param {Array<{ realIndex: number, j: number, d: string, fill: string|null }>} captured
         * @param {string} _fromType
         * @param {string} toType
         * @param {any} newSeries - the series array being passed to the new chart;
         *   used only to derive the bar target's (realIndex, j) iteration positions.
         */
        _buildMapping(captured, _fromType, toType, newSeries) {
            const map = /* @__PURE__ */ new Map();
            const tf = familyOf(toType);
            const flat = captured.slice().sort((a, b) => a.realIndex - b.realIndex || a.j - b.j);
            if (tf === "radial") {
                flat.forEach((c, i) => {
                    map.set(`${i}:0`, {
                        d: c.d,
                        fill: c.fill
                    });
                });
                return map;
            }
            if (tf === "bar") {
                const positions = [];
                const series = Array.isArray(newSeries) ? newSeries : [];
                series.forEach((s, seriesIdx) => {
                    const data = s && Array.isArray(s.data) ? s.data : [];
                    for (let j = 0; j < data.length; j++) {
                        positions.push({
                            realIndex: seriesIdx,
                            j
                        });
                    }
                });
                flat.forEach((c, i) => {
                    const pos = positions[i];
                    if (pos) {
                        map.set(`${pos.realIndex}:${pos.j}`, {
                            d: c.d,
                            fill: c.fill
                        });
                    }
                });
                return map;
            }
            return map;
        }
        isActive() {
            return this._snapshot !== null;
        }
        /**
         * @param {number} realIndex
         * @param {number} j
         * @returns {string | null}
         */
        getInitialPathFor(realIndex, j) {
            if (!this._snapshot) return null;
            const entry = this._snapshot.mapping.get(`${realIndex}:${j}`);
            if (!entry) return null;
            const dx = this._snapshot.oldLayout.translateX - (this.w.layout.translateX || 0);
            const dy = this._snapshot.oldLayout.translateY - (this.w.layout.translateY || 0);
            return dx === 0 && dy === 0 ? entry.d : this._translatePathD(entry.d, dx, dy);
        }
        /**
         * Offset every absolute coordinate in an SVG path `d` by (dx, dy).
         *
         * Assumes the path uses only uppercase (absolute) commands — every path
         * ApexCharts generates does. Relative-command paths would pass through
         * unchanged at the lowercase, which is also semantically correct (deltas
         * don't shift under a parent translate).
         *
         * @param {string} d
         * @param {number} dx
         * @param {number} dy
         * @returns {string}
         */
        _translatePathD(d, dx, dy) {
            if (dx === 0 && dy === 0) return d;
            const commands = parsePath(d);
            return commands.map(
                /** @param {any[]} c */
                (c) => {
                    const cmd = c[0];
                    if (cmd === "Z") return "Z";
                    if (cmd === "M" || cmd === "L" || cmd === "T") {
                        return `${cmd} ${c[1] + dx} ${c[2] + dy}`;
                    }
                    if (cmd === "H") return `${cmd} ${c[1] + dx}`;
                    if (cmd === "V") return `${cmd} ${c[1] + dy}`;
                    if (cmd === "C") {
                        return `${cmd} ${c[1] + dx} ${c[2] + dy} ${c[3] + dx} ${c[4] + dy} ${c[5] + dx} ${c[6] + dy}`;
                    }
                    if (cmd === "S" || cmd === "Q") {
                        return `${cmd} ${c[1] + dx} ${c[2] + dy} ${c[3] + dx} ${c[4] + dy}`;
                    }
                    if (cmd === "A") {
                        return `${cmd} ${c[1]} ${c[2]} ${c[3]} ${c[4]} ${c[5]} ${c[6] + dx} ${c[7] + dy}`;
                    }
                    return c.join(" ");
                }
            ).join(" ");
        }
        /**
         * @param {number} realIndex
         * @param {number} j
         * @returns {string | null}
         */
        getInitialFillFor(realIndex, j) {
            if (!this._snapshot) return null;
            const entry = this._snapshot.mapping.get(`${realIndex}:${j}`);
            return entry ? entry.fill : null;
        }
        /** @returns {number} */
        getSpeed() {
            const animCfg = this.w.config.chart.animations;
            return animCfg.chartTypeMorph && animCfg.chartTypeMorph.speed || animCfg.speed || 600;
        }
        /**
         * Fade newly-mounted axes / grid / legend / titles from opacity 0 → 1 in
         * parallel with the morph. Without this the chart's chrome would pop in
         * abruptly while the series elements are still mid-tween, which reads as a
         * jarring layout shift.
         */
        applyChromeFade() {
            var _a;
            if (!this._snapshot || !Environment.isBrowser()) return;
            const baseEl = (_a = this.w.globals.dom) == null ? void 0 : _a.baseEl;
            if (!baseEl) return;
            const speed = this.getSpeed();
            const chromeSelectors = [
                ".apexcharts-xaxis",
                ".apexcharts-yaxis",
                ".apexcharts-grid",
                ".apexcharts-gridlines-horizontal",
                ".apexcharts-gridlines-vertical",
                ".apexcharts-legend",
                ".apexcharts-title-text",
                ".apexcharts-subtitle-text"
            ];
            chromeSelectors.forEach((sel) => {
                baseEl.querySelectorAll(sel).forEach((el) => {
                    if (!el.style) return;
                    el.style.opacity = "0";
                    el.style.transition = `opacity ${speed}ms ease-out`;
                    BrowserAPIs.requestAnimationFrame(() => {
                        el.style.opacity = "1";
                    });
                    setTimeout(() => {
                        el.style.transition = "";
                        el.style.opacity = "";
                    }, speed + 80);
                });
            });
            setTimeout(() => this.cleanup(), speed + 100);
        }
        cleanup() {
            this._snapshot = null;
        }
    }
    ApexCharts.registerFeatures({
        morphTypeChange: MorphTypeChange
    });
    class BarDataLabels {
        /**
         * @param {import('../../../charts/Bar').default} barCtx
         */
        constructor(barCtx) {
            this.w = barCtx.w;
            this.barCtx = barCtx;
            this.totalFormatter = this.w.config.plotOptions.bar.dataLabels.total.formatter;
            if (!this.totalFormatter) {
                this.totalFormatter = this.w.config.dataLabels.formatter;
            }
        }
        /** handleBarDataLabels is used to calculate the positions for the data-labels
         * It also sets the element's data attr for bars and calls drawCalculatedBarDataLabels()
         * After calculating, it also calls the function to draw data labels
         * @memberof Bar
         * @param {Record<string, any>} opts - bar properties used throughout the bar drawing function
         * @return {object} dataLabels node-element which you can append later
         **/
        handleBarDataLabels(opts) {
            const {
                x,
                y,
                y1,
                y2,
                i,
                j,
                realIndex,
                columnGroupIndex,
                series,
                barHeight,
                barWidth,
                barXPosition,
                barYPosition,
                visibleSeries
            } = opts;
            const w = this.w;
            const graphics = new Graphics(this.barCtx.w);
            const strokeWidth = Array.isArray(this.barCtx.strokeWidth) ? this.barCtx.strokeWidth[realIndex] : this.barCtx.strokeWidth;
            let bcx;
            let bcy;
            if (w.axisFlags.isXNumeric && !w.globals.isBarHorizontal) {
                bcx = x + barWidth * (visibleSeries + 1);
                bcy = y + barHeight * (visibleSeries + 1) - strokeWidth;
            } else {
                bcx = x + barWidth * visibleSeries;
                bcy = y + barHeight * visibleSeries;
            }
            let dataLabels = null;
            let totalDataLabels = null;
            let dataLabelsX = x;
            let dataLabelsY = y;
            let dataLabelsPos = (
                /** @type {any} */
                {}
            );
            const dataLabelsConfig = w.config.dataLabels;
            const barDataLabelsConfig = this.barCtx.barOptions.dataLabels;
            const barTotalDataLabelsConfig = this.barCtx.barOptions.dataLabels.total;
            if (typeof barYPosition !== "undefined" && (this.barCtx.isRangeBar || this.barCtx.isPyramid)) {
                bcy = barYPosition;
                dataLabelsY = barYPosition;
            }
            if (typeof barXPosition !== "undefined" && this.barCtx.isVerticalGroupedRangeBar) {
                bcx = barXPosition;
                dataLabelsX = barXPosition;
            }
            const offX = dataLabelsConfig.offsetX;
            const offY = dataLabelsConfig.offsetY;
            let textRects = {
                width: 0,
                height: 0
            };
            if (w.config.dataLabels.enabled) {
                const yLabel = w.seriesData.series[i][j];
                textRects = graphics.getTextRects(
                    w.config.dataLabels.formatter ? w.config.dataLabels.formatter(yLabel, __spreadProps(__spreadValues({}, w), {
                        seriesIndex: i,
                        dataPointIndex: j,
                        w
                    })) : w.formatters.yLabelFormatters[0](yLabel),
                    parseFloat(dataLabelsConfig.style.fontSize).toString()
                );
            }
            const params = {
                x,
                y,
                i,
                j,
                realIndex,
                columnGroupIndex,
                bcx,
                bcy,
                barHeight,
                barWidth,
                textRects,
                strokeWidth,
                dataLabelsX,
                dataLabelsY,
                dataLabelsConfig,
                barDataLabelsConfig,
                barTotalDataLabelsConfig,
                offX,
                offY
            };
            if (this.barCtx.isHorizontal) {
                dataLabelsPos = this.calculateBarsDataLabelsPosition(params);
            } else {
                dataLabelsPos = this.calculateColumnsDataLabelsPosition(params);
            }
            dataLabels = this.drawCalculatedDataLabels({
                x: dataLabelsPos.dataLabelsX,
                y: dataLabelsPos.dataLabelsY,
                val: this.barCtx.isRangeBar ? [y1, y2] : w.config.chart.stackType === "100%" ? series[realIndex][j] : w.seriesData.series[realIndex][j],
                i: realIndex,
                j,
                barWidth,
                barHeight,
                textRects,
                dataLabelsConfig
            });
            if (w.config.chart.stacked && barTotalDataLabelsConfig.enabled) {
                totalDataLabels = this.drawTotalDataLabels({
                    x: dataLabelsPos.totalDataLabelsX,
                    y: dataLabelsPos.totalDataLabelsY,
                    barWidth,
                    barHeight,
                    realIndex,
                    textAnchor: dataLabelsPos.totalDataLabelsAnchor,
                    val: this.getStackedTotalDataLabel({
                        realIndex,
                        j
                    }),
                    dataLabelsConfig,
                    barTotalDataLabelsConfig
                });
            }
            return {
                dataLabelsPos,
                dataLabels,
                totalDataLabels
            };
        }
        /** @param {{realIndex: any, j: any}} opts */
        getStackedTotalDataLabel({
            realIndex,
            j
        }) {
            const w = this.w;
            let val = this.barCtx.stackedSeriesTotals[j];
            if (this.totalFormatter) {
                val = this.totalFormatter(val, __spreadProps(__spreadValues({}, w), {
                    seriesIndex: realIndex,
                    dataPointIndex: j,
                    w
                }));
            }
            return val;
        }
        /**
         * @param {Record<string, any>} opts
         */
        calculateColumnsDataLabelsPosition(opts) {
            const w = this.w;
            let {
                i,
                j,
                realIndex,
                y,
                bcx,
                barWidth,
                barHeight,
                textRects,
                dataLabelsX,
                dataLabelsY,
                dataLabelsConfig,
                barDataLabelsConfig,
                barTotalDataLabelsConfig,
                strokeWidth,
                offX,
                offY
            } = opts;
            let totalDataLabelsY;
            let totalDataLabelsX;
            const totalDataLabelsAnchor = "middle";
            const totalDataLabelsBcx = bcx;
            barHeight = Math.abs(barHeight);
            const vertical = w.config.plotOptions.bar.dataLabels.orientation === "vertical";
            const {
                zeroEncounters
            } = this.barCtx.barHelpers.getZeroValueEncounters({
                i,
                j
            });
            bcx = bcx - strokeWidth / 2;
            const dataPointsDividedWidth = w.layout.gridWidth / w.globals.dataPoints;
            if (this.barCtx.isVerticalGroupedRangeBar) {
                dataLabelsX += barWidth / 2;
            } else {
                if (w.axisFlags.isXNumeric) {
                    dataLabelsX = bcx - barWidth / 2 + offX;
                } else {
                    dataLabelsX = bcx - dataPointsDividedWidth + barWidth / 2 + offX;
                }
                if (!w.config.chart.stacked && zeroEncounters > 0 && w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
                    dataLabelsX -= barWidth * zeroEncounters;
                }
            }
            if (vertical) {
                const offsetDLX = 2;
                dataLabelsX = dataLabelsX + textRects.height / 2 - strokeWidth / 2 - offsetDLX;
            }
            const valIsNegative = w.seriesData.series[i][j] < 0;
            let newY = y;
            if (this.barCtx.isReversed) {
                newY = y + (valIsNegative ? barHeight : -barHeight);
            }
            switch (barDataLabelsConfig.position) {
                case "center":
                    if (vertical) {
                        if (valIsNegative) {
                            dataLabelsY = newY - barHeight / 2 + offY;
                        } else {
                            dataLabelsY = newY + barHeight / 2 - offY;
                        }
                    } else {
                        if (valIsNegative) {
                            dataLabelsY = newY - barHeight / 2 + textRects.height / 2 + offY;
                        } else {
                            dataLabelsY = newY + barHeight / 2 + textRects.height / 2 - offY;
                        }
                    }
                    break;
                case "bottom":
                    if (vertical) {
                        if (valIsNegative) {
                            dataLabelsY = newY - barHeight + offY;
                        } else {
                            dataLabelsY = newY + barHeight - offY;
                        }
                    } else {
                        if (valIsNegative) {
                            dataLabelsY = newY - barHeight + textRects.height + strokeWidth + offY;
                        } else {
                            dataLabelsY = newY + barHeight - textRects.height / 2 + strokeWidth - offY;
                        }
                    }
                    break;
                case "top":
                    if (vertical) {
                        if (valIsNegative) {
                            dataLabelsY = newY + offY;
                        } else {
                            dataLabelsY = newY - offY;
                        }
                    } else {
                        if (valIsNegative) {
                            dataLabelsY = newY - textRects.height / 2 - offY;
                        } else {
                            dataLabelsY = newY + textRects.height + offY;
                        }
                    }
                    break;
            }
            let lowestPrevY = newY;
            w.labelData.seriesGroups.forEach((sg) => {
                var _a;
                (_a = this.barCtx[sg.join(",")]) == null ? void 0 : _a.prevY.forEach(
                    (arr) => {
                        if (valIsNegative) {
                            lowestPrevY = Math.max(arr[j], lowestPrevY);
                        } else {
                            lowestPrevY = Math.min(arr[j], lowestPrevY);
                        }
                    }
                );
            });
            if (this.barCtx.lastActiveBarSerieIndex === realIndex && barTotalDataLabelsConfig.enabled) {
                const ADDITIONAL_OFFY = 18;
                const graphics = new Graphics(this.barCtx.w);
                const totalLabeltextRects = graphics.getTextRects(
                    this.getStackedTotalDataLabel({
                        realIndex,
                        j
                    }),
                    dataLabelsConfig.fontSize
                );
                if (valIsNegative) {
                    totalDataLabelsY = lowestPrevY - totalLabeltextRects.height / 2 - offY - barTotalDataLabelsConfig.offsetY + ADDITIONAL_OFFY;
                } else {
                    totalDataLabelsY = lowestPrevY + totalLabeltextRects.height + offY + barTotalDataLabelsConfig.offsetY - ADDITIONAL_OFFY;
                }
                const xDivision = dataPointsDividedWidth;
                totalDataLabelsX = totalDataLabelsBcx + (w.axisFlags.isXNumeric ? -barWidth * w.globals.barGroups.length / 2 : w.globals.barGroups.length * barWidth / 2 - (w.globals.barGroups.length - 1) * barWidth - xDivision) + barTotalDataLabelsConfig.offsetX;
            }
            if (!w.config.chart.stacked) {
                if (dataLabelsY < 0) {
                    dataLabelsY = 0 + strokeWidth;
                } else if (dataLabelsY + textRects.height / 3 > w.layout.gridHeight) {
                    dataLabelsY = w.layout.gridHeight - strokeWidth;
                }
            }
            return {
                bcx,
                bcy: y,
                dataLabelsX,
                dataLabelsY,
                totalDataLabelsX,
                totalDataLabelsY,
                totalDataLabelsAnchor
            };
        }
        /**
         * @param {Record<string, any>} opts
         */
        calculateBarsDataLabelsPosition(opts) {
            var _a;
            const w = this.w;
            let {
                x,
                i,
                j,
                realIndex,
                bcy,
                barHeight,
                barWidth,
                textRects,
                dataLabelsX,
                strokeWidth,
                dataLabelsConfig,
                barDataLabelsConfig,
                barTotalDataLabelsConfig,
                offX,
                offY
            } = opts;
            const dataPointsDividedHeight = w.layout.gridHeight / w.globals.dataPoints;
            const {
                zeroEncounters
            } = this.barCtx.barHelpers.getZeroValueEncounters({
                i,
                j
            });
            barWidth = Math.abs(barWidth);
            let dataLabelsY;
            if (this.barCtx.isPyramid) {
                const centerOffset = (_a = textRects.centerOffset) != null ? _a : 0;
                dataLabelsY = bcy + barHeight / 2 + offY - centerOffset;
            } else {
                dataLabelsY = bcy - (this.barCtx.isRangeBar ? 0 : dataPointsDividedHeight) + barHeight / 2 + textRects.height / 2 + offY - 3;
            }
            if (!w.config.chart.stacked && zeroEncounters > 0 && w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
                dataLabelsY -= barHeight * zeroEncounters;
            }
            let totalDataLabelsX;
            let totalDataLabelsY;
            let totalDataLabelsAnchor = "start";
            const valIsNegative = w.seriesData.series[i][j] < 0;
            let newX = x;
            if (this.barCtx.isReversed) {
                newX = x + (valIsNegative ? -barWidth : barWidth);
                totalDataLabelsAnchor = valIsNegative ? "start" : "end";
            }
            if (this.barCtx.isPyramid) {
                dataLabelsX = w.layout.gridWidth / 2 + offX;
            } else {
                switch (barDataLabelsConfig.position) {
                    case "center":
                        if (valIsNegative) {
                            dataLabelsX = newX + barWidth / 2 - offX;
                        } else {
                            dataLabelsX = Math.max(textRects.width / 2, newX - barWidth / 2) + offX;
                        }
                        break;
                    case "bottom":
                        if (valIsNegative) {
                            dataLabelsX = newX + barWidth - strokeWidth - offX;
                        } else {
                            dataLabelsX = newX - barWidth + strokeWidth + offX;
                        }
                        break;
                    case "top":
                        if (valIsNegative) {
                            dataLabelsX = newX - strokeWidth - offX;
                        } else {
                            dataLabelsX = newX - strokeWidth + offX;
                        }
                        break;
                }
            }
            let lowestPrevX = newX;
            w.labelData.seriesGroups.forEach((sg) => {
                var _a2;
                (_a2 = this.barCtx[sg.join(",")]) == null ? void 0 : _a2.prevX.forEach(
                    (arr) => {
                        if (valIsNegative) {
                            lowestPrevX = Math.min(arr[j], lowestPrevX);
                        } else {
                            lowestPrevX = Math.max(arr[j], lowestPrevX);
                        }
                    }
                );
            });
            if (this.barCtx.lastActiveBarSerieIndex === realIndex && barTotalDataLabelsConfig.enabled) {
                const graphics = new Graphics(this.barCtx.w);
                const totalLabeltextRects = graphics.getTextRects(
                    this.getStackedTotalDataLabel({
                        realIndex,
                        j
                    }),
                    dataLabelsConfig.fontSize
                );
                if (valIsNegative) {
                    totalDataLabelsX = lowestPrevX - strokeWidth - offX - barTotalDataLabelsConfig.offsetX;
                    totalDataLabelsAnchor = "end";
                } else {
                    totalDataLabelsX = lowestPrevX + offX + barTotalDataLabelsConfig.offsetX + (this.barCtx.isReversed ? -(barWidth + strokeWidth) : strokeWidth);
                }
                totalDataLabelsY = dataLabelsY - textRects.height / 2 + totalLabeltextRects.height / 2 + barTotalDataLabelsConfig.offsetY + strokeWidth;
                if (w.globals.barGroups.length > 1) {
                    totalDataLabelsY = totalDataLabelsY - w.globals.barGroups.length / 2 * (barHeight / 2);
                }
            }
            if (!w.config.chart.stacked) {
                if (dataLabelsConfig.textAnchor === "start") {
                    if (dataLabelsX - textRects.width < 0) {
                        dataLabelsX = valIsNegative ? textRects.width + strokeWidth : strokeWidth;
                    } else if (dataLabelsX + textRects.width > w.layout.gridWidth) {
                        dataLabelsX = valIsNegative ? w.layout.gridWidth - strokeWidth : w.layout.gridWidth - textRects.width - strokeWidth;
                    }
                } else if (dataLabelsConfig.textAnchor === "middle") {
                    if (dataLabelsX - textRects.width / 2 < 0) {
                        dataLabelsX = textRects.width / 2 + strokeWidth;
                    } else if (dataLabelsX + textRects.width / 2 > w.layout.gridWidth) {
                        dataLabelsX = w.layout.gridWidth - textRects.width / 2 - strokeWidth;
                    }
                } else if (dataLabelsConfig.textAnchor === "end") {
                    if (dataLabelsX < 1) {
                        dataLabelsX = textRects.width + strokeWidth;
                    } else if (dataLabelsX + 1 > w.layout.gridWidth) {
                        dataLabelsX = w.layout.gridWidth - textRects.width - strokeWidth;
                    }
                }
            }
            return {
                bcx: x,
                bcy,
                dataLabelsX,
                dataLabelsY,
                totalDataLabelsX,
                totalDataLabelsY,
                totalDataLabelsAnchor
            };
        }
        /** @param {{x: any, y: any, val: any, i: any, j: any, textRects: any, barHeight: any, barWidth: any, dataLabelsConfig: any}} opts */
        drawCalculatedDataLabels({
            x,
            y,
            val,
            i,
            // = realIndex
            j,
            textRects,
            barHeight,
            barWidth,
            dataLabelsConfig
        }) {
            const w = this.w;
            let rotate = "rotate(0)";
            if (w.config.plotOptions.bar.dataLabels.orientation === "vertical")
                rotate = `rotate(-90, ${x}, ${y})`;
            const dataLabels = new DataLabels(this.barCtx.w, this.barCtx.ctx);
            const graphics = new Graphics(this.barCtx.w);
            const formatter = dataLabelsConfig.formatter;
            let elDataLabelsWrap = null;
            const isSeriesNotCollapsed = w.globals.collapsedSeriesIndices.indexOf(i) > -1;
            if (dataLabelsConfig.enabled && !isSeriesNotCollapsed) {
                elDataLabelsWrap = graphics.group({
                    class: "apexcharts-data-labels",
                    transform: rotate
                });
                let text = "";
                if (typeof val !== "undefined") {
                    text = formatter(val, __spreadProps(__spreadValues({}, w), {
                        seriesIndex: i,
                        dataPointIndex: j,
                        w
                    }));
                }
                if (!val && w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
                    text = "";
                }
                const valIsNegative = w.seriesData.series[i][j] < 0;
                const position = w.config.plotOptions.bar.dataLabels.position;
                if (w.config.plotOptions.bar.dataLabels.orientation === "vertical") {
                    if (position === "top") {
                        if (valIsNegative) dataLabelsConfig.textAnchor = "end";
                        else dataLabelsConfig.textAnchor = "start";
                    }
                    if (position === "center") {
                        dataLabelsConfig.textAnchor = "middle";
                    }
                    if (position === "bottom") {
                        if (valIsNegative) dataLabelsConfig.textAnchor = "end";
                        else dataLabelsConfig.textAnchor = "start";
                    }
                }
                if (this.barCtx.isRangeBar && this.barCtx.barOptions.dataLabels.hideOverflowingLabels) {
                    const txRect = graphics.getTextRects(
                        text,
                        parseFloat(dataLabelsConfig.style.fontSize).toString()
                    );
                    if (barWidth < txRect.width) {
                        text = "";
                    }
                }
                if (w.config.chart.stacked && this.barCtx.barOptions.dataLabels.hideOverflowingLabels) {
                    if (this.barCtx.isHorizontal) {
                        if (textRects.width / 1.6 > Math.abs(barWidth)) {
                            text = "";
                        }
                    } else {
                        if (textRects.height / 1.6 > Math.abs(barHeight)) {
                            text = "";
                        }
                    }
                }
                const modifiedDataLabelsConfig = __spreadValues({}, dataLabelsConfig);
                if (this.barCtx.isHorizontal) {
                    if (val < 0) {
                        if (dataLabelsConfig.textAnchor === "start") {
                            modifiedDataLabelsConfig.textAnchor = "end";
                        } else if (dataLabelsConfig.textAnchor === "end") {
                            modifiedDataLabelsConfig.textAnchor = "start";
                        }
                    }
                }
                dataLabels.plotDataLabelsText({
                    x,
                    y,
                    text,
                    i,
                    j,
                    parent: elDataLabelsWrap,
                    dataLabelsConfig: modifiedDataLabelsConfig,
                    alwaysDrawDataLabel: true,
                    offsetCorrection: true
                });
            }
            return elDataLabelsWrap;
        }
        /** @param {{ x?: any, y?: any, val?: any, realIndex?: any, textAnchor?: any, barWidth?: any, barHeight?: any, dataLabelsConfig?: any, barTotalDataLabelsConfig?: any }} opts */
        drawTotalDataLabels({
            x,
            y,
            val,
            realIndex,
            textAnchor,
            barTotalDataLabelsConfig
        }) {
            const graphics = new Graphics(this.barCtx.w);
            let totalDataLabelText;
            if (barTotalDataLabelsConfig.enabled && typeof x !== "undefined" && typeof y !== "undefined" && this.barCtx.lastActiveBarSerieIndex === realIndex) {
                totalDataLabelText = graphics.drawText({
                    x,
                    y,
                    foreColor: barTotalDataLabelsConfig.style.color,
                    text: val,
                    textAnchor,
                    fontFamily: barTotalDataLabelsConfig.style.fontFamily,
                    fontSize: barTotalDataLabelsConfig.style.fontSize,
                    fontWeight: barTotalDataLabelsConfig.style.fontWeight
                });
            }
            return totalDataLabelText;
        }
    }
    let Helpers$1 = class Helpers {
        /**
         * @param {Record<string, any>} barCtx
         */
        constructor(barCtx) {
            this.w = barCtx.w;
            this.barCtx = barCtx;
        }
        /**
         * @param {any[]} series
         */
        initVariables(series) {
            const w = this.w;
            this.barCtx.series = series;
            this.barCtx.totalItems = 0;
            this.barCtx.seriesLen = 0;
            this.barCtx.visibleI = -1;
            this.barCtx.visibleItems = 1;
            for (let sl = 0; sl < series.length; sl++) {
                if (series[sl].length > 0) {
                    this.barCtx.seriesLen = this.barCtx.seriesLen + 1;
                    this.barCtx.totalItems += series[sl].length;
                }
                if (w.axisFlags.isXNumeric) {
                    for (let j = 0; j < series[sl].length; j++) {
                        if (w.seriesData.seriesX[sl][j] > w.globals.minX && w.seriesData.seriesX[sl][j] < w.globals.maxX) {
                            this.barCtx.visibleItems++;
                        }
                    }
                } else {
                    this.barCtx.visibleItems = w.globals.dataPoints;
                }
            }
            this.arrBorderRadius = this.createBorderRadiusArr(w.seriesData.series);
            if (Utils$1.isSafari()) {
                this.arrBorderRadius = this.arrBorderRadius.map(
                    (brArr) => (
                        /**
                         * @param {any} _
                         */
                        brArr.map((_) => "none")
                    )
                );
            }
            if (this.barCtx.seriesLen === 0) {
                this.barCtx.seriesLen = 1;
            }
            this.barCtx.zeroSerieses = [];
            if (!w.globals.comboCharts) {
                this.checkZeroSeries({
                    series
                });
            }
        }
        /**
         * @param {number} realIndex
         */
        initialPositions(realIndex) {
            const w = this.w;
            let x, y, yDivision, xDivision, barHeight, barWidth, zeroH, zeroW;
            let dataPoints = w.globals.dataPoints;
            if (this.barCtx.isRangeBar) {
                dataPoints = w.labelData.labels.length;
            }
            let seriesLen = this.barCtx.seriesLen;
            if (w.config.plotOptions.bar.rangeBarGroupRows) {
                seriesLen = 1;
            }
            if (this.barCtx.isHorizontal) {
                yDivision = w.layout.gridHeight / dataPoints;
                barHeight = yDivision / seriesLen;
                if (w.axisFlags.isXNumeric) {
                    yDivision = w.layout.gridHeight / this.barCtx.totalItems;
                    barHeight = yDivision / this.barCtx.seriesLen;
                }
                barHeight = barHeight * parseInt(this.barCtx.barOptions.barHeight, 10) / 100;
                if (String(this.barCtx.barOptions.barHeight).indexOf("%") === -1) {
                    barHeight = parseInt(this.barCtx.barOptions.barHeight, 10);
                }
                zeroW = this.barCtx.baseLineInvertedY + w.globals.padHorizontal + (this.barCtx.isReversed ? w.layout.gridWidth : 0) - (this.barCtx.isReversed ? this.barCtx.baseLineInvertedY * 2 : 0);
                if (this.barCtx.isFunnel) {
                    zeroW = w.layout.gridWidth / 2;
                }
                y = (yDivision - barHeight * this.barCtx.seriesLen) / 2;
            } else {
                xDivision = w.layout.gridWidth / this.barCtx.visibleItems;
                if (w.config.xaxis.convertedCatToNumeric) {
                    xDivision = w.layout.gridWidth / w.globals.dataPoints;
                }
                barWidth = xDivision / seriesLen * parseInt(this.barCtx.barOptions.columnWidth, 10) / 100;
                if (w.axisFlags.isXNumeric) {
                    const xRatio = this.barCtx.xRatio;
                    if (w.globals.minXDiff && w.globals.minXDiff !== 0.5 && w.globals.minXDiff / xRatio > 0) {
                        xDivision = w.globals.minXDiff / xRatio;
                    }
                    barWidth = xDivision / seriesLen * parseInt(this.barCtx.barOptions.columnWidth, 10) / 100;
                    if (barWidth < 1) {
                        barWidth = 1;
                    }
                }
                if (String(this.barCtx.barOptions.columnWidth).indexOf("%") === -1) {
                    barWidth = parseInt(this.barCtx.barOptions.columnWidth, 10);
                }
                zeroH = w.layout.gridHeight - this.barCtx.baseLineY[this.barCtx.translationsIndex] - (this.barCtx.isReversed ? w.layout.gridHeight : 0) + (this.barCtx.isReversed ? this.barCtx.baseLineY[this.barCtx.translationsIndex] * 2 : 0);
                if (w.axisFlags.isXNumeric) {
                    const xForNumericX = this.barCtx.getBarXForNumericXAxis({
                        x,
                        j: 0,
                        realIndex,
                        barWidth
                    });
                    x = xForNumericX.x;
                } else {
                    x = w.globals.padHorizontal + Utils$1.noExponents(xDivision - barWidth * this.barCtx.seriesLen) / 2;
                }
            }
            w.globals.barHeight = barHeight;
            w.globals.barWidth = barWidth;
            return {
                x,
                y,
                yDivision,
                xDivision,
                barHeight,
                barWidth,
                zeroH,
                zeroW
            };
        }
        /**
         * @param {Record<string, any>} ctx
         */
        initializeStackedPrevVars(ctx) {
            const w = ctx.w;
            w.labelData.seriesGroups.forEach((group) => {
                if (!ctx[group]) ctx[group] = {};
                ctx[group].prevY = [];
                ctx[group].prevX = [];
                ctx[group].prevYF = [];
                ctx[group].prevXF = [];
                ctx[group].prevYVal = [];
                ctx[group].prevXVal = [];
            });
        }
        /**
         * @param {Record<string, any>} ctx
         */
        initializeStackedXYVars(ctx) {
            const w = ctx.w;
            w.labelData.seriesGroups.forEach((group) => {
                if (!ctx[group]) ctx[group] = {};
                ctx[group].xArrj = [];
                ctx[group].xArrjF = [];
                ctx[group].xArrjVal = [];
                ctx[group].yArrj = [];
                ctx[group].yArrjF = [];
                ctx[group].yArrjVal = [];
            });
        }
        /**
         * @param {any[]} series
         * @param {number} i
         * @param {number} j
         * @param {number} realIndex
         */
        getPathFillColor(series, i, j, realIndex) {
            var _a, _b, _c, _d;
            const w = this.w;
            const fill = new Fill(this.barCtx.w);
            let fillColor = null;
            const seriesNumber = this.barCtx.barOptions.distributed ? j : i;
            let useRangeColor = false;
            if (this.barCtx.barOptions.colors.ranges.length > 0) {
                const colorRange = this.barCtx.barOptions.colors.ranges;
                colorRange.map((range) => {
                    if (series[i][j] >= range.from && series[i][j] <= range.to) {
                        fillColor = range.color;
                        useRangeColor = true;
                    }
                });
            }
            const pathFill = fill.fillPath({
                seriesNumber: this.barCtx.barOptions.distributed ? seriesNumber : realIndex,
                dataPointIndex: j,
                color: fillColor,
                value: series[i][j],
                fillConfig: (_a = w.config.series[i].data[j]) == null ? void 0 : _a.fill,
                fillType: ((_c = (_b = w.config.series[i].data[j]) == null ? void 0 : _b.fill) == null ? void 0 : _c.type) ? (_d = w.config.series[i].data[j]) == null ? void 0 : _d.fill.type : Array.isArray(w.config.fill.type) ? w.config.fill.type[realIndex] : w.config.fill.type
            });
            return {
                color: pathFill,
                useRangeColor
            };
        }
        /**
         * @param {number} i
         * @param {number} j
         * @param {number} realIndex
         */
        getStrokeWidth(i, j, realIndex) {
            let strokeWidth = 0;
            const w = this.w;
            if (typeof this.barCtx.series[i][j] === "undefined" || this.barCtx.series[i][j] === null || w.config.chart.type === "bar" && !this.barCtx.series[i][j]) {
                this.barCtx.isNullValue = true;
            } else {
                this.barCtx.isNullValue = false;
            }
            if (w.config.stroke.show) {
                if (!this.barCtx.isNullValue) {
                    strokeWidth = Array.isArray(this.barCtx.strokeWidth) ? this.barCtx.strokeWidth[realIndex] : this.barCtx.strokeWidth;
                }
            }
            return strokeWidth;
        }
        /**
         * @param {any[]} series
         */
        createBorderRadiusArr(series) {
            var _a;
            const w = this.w;
            const alwaysApplyRadius = !this.w.config.chart.stacked || w.config.plotOptions.bar.borderRadius <= 0;
            const numSeries = series.length;
            const numColumns = ((_a = series[0]) == null ? void 0 : _a.length) | 0;
            const output = Array.from({
                    length: numSeries
                },
                () => Array(numColumns).fill(alwaysApplyRadius ? "top" : "none")
            );
            if (alwaysApplyRadius) return output;
            const chartType = this.w.config.chart.type;
            for (let j = 0; j < numColumns; j++) {
                const positiveIndices = [];
                const negativeIndices = [];
                let nonZeroCount = 0;
                for (let i = 0; i < numSeries; i++) {
                    const value = series[i][j];
                    if (value > 0) {
                        positiveIndices.push(i);
                        nonZeroCount++;
                    } else if (value < 0) {
                        negativeIndices.push(i);
                        nonZeroCount++;
                    }
                }
                if (positiveIndices.length > 0 && negativeIndices.length === 0) {
                    if (positiveIndices.length === 1) {
                        output[positiveIndices[0]][j] = chartType === "bar" && numColumns === 1 ? "top" : "both";
                    } else {
                        const firstPositiveIndex = positiveIndices[0];
                        const lastPositiveIndex = positiveIndices[positiveIndices.length - 1];
                        for (const i of positiveIndices) {
                            if (i === firstPositiveIndex) {
                                output[i][j] = chartType === "bar" && numColumns === 1 ? "top" : "bottom";
                            } else if (i === lastPositiveIndex) {
                                output[i][j] = "top";
                            } else {
                                output[i][j] = "none";
                            }
                        }
                    }
                } else if (negativeIndices.length > 0 && positiveIndices.length === 0) {
                    if (negativeIndices.length === 1) {
                        output[negativeIndices[0]][j] = "both";
                    } else {
                        const highestNegativeIndex = Math.max(...negativeIndices);
                        const lowestNegativeIndex = Math.min(...negativeIndices);
                        for (const i of negativeIndices) {
                            if (i === highestNegativeIndex) {
                                output[i][j] = "bottom";
                            } else if (i === lowestNegativeIndex) {
                                output[i][j] = "top";
                            } else {
                                output[i][j] = "none";
                            }
                        }
                    }
                } else if (positiveIndices.length > 0 && negativeIndices.length > 0) {
                    const lastPositiveIndex = positiveIndices[positiveIndices.length - 1];
                    for (const i of positiveIndices) {
                        if (i === lastPositiveIndex) {
                            output[i][j] = "top";
                        } else {
                            output[i][j] = "none";
                        }
                    }
                    const highestNegativeIndex = Math.max(...negativeIndices);
                    for (const i of negativeIndices) {
                        if (i === highestNegativeIndex) {
                            output[i][j] = "bottom";
                        } else {
                            output[i][j] = "none";
                        }
                    }
                } else if (nonZeroCount === 1) {
                    const index = positiveIndices[0] || negativeIndices[0];
                    output[index][j] = "both";
                }
            }
            return output;
        }
        /** @param {{ j?: any, i?: any, x1?: any, x2?: any, y1?: any, y2?: any, bc?: any, elSeries?: any }} opts */
        barBackground({
            j,
            i,
            x1,
            x2,
            y1,
            y2,
            elSeries
        }) {
            const w = this.w;
            const graphics = new Graphics(this.barCtx.w);
            const sr = new Series(this.barCtx.w);
            const activeSeriesIndex = sr.getActiveConfigSeriesIndex();
            if (this.barCtx.barOptions.colors.backgroundBarColors.length > 0 && activeSeriesIndex === i) {
                if (j >= this.barCtx.barOptions.colors.backgroundBarColors.length) {
                    j %= this.barCtx.barOptions.colors.backgroundBarColors.length;
                }
                const bcolor = this.barCtx.barOptions.colors.backgroundBarColors[j];
                const rect = graphics.drawRect(
                    typeof x1 !== "undefined" ? x1 : 0,
                    typeof y1 !== "undefined" ? y1 : 0,
                    typeof x2 !== "undefined" ? x2 : w.layout.gridWidth,
                    typeof y2 !== "undefined" ? y2 : w.layout.gridHeight,
                    this.barCtx.barOptions.colors.backgroundBarRadius,
                    bcolor,
                    this.barCtx.barOptions.colors.backgroundBarOpacity
                );
                elSeries.add(rect);
                rect.node.classList.add("apexcharts-backgroundBar");
            }
        }
        /** @param {{ barWidth?: any, barXPosition?: any, y1?: any, y2?: any, yRatio?: any, strokeWidth?: any, isReversed?: any, series?: any, seriesGroup?: any, realIndex?: any, i?: any, j?: any, w?: any }} opts */
        getColumnPaths({
            barWidth,
            barXPosition,
            y1,
            y2,
            strokeWidth,
            isReversed,
            series,
            seriesGroup,
            realIndex,
            i,
            j,
            w
        }) {
            var _a, _b, _c;
            const graphics = new Graphics(this.barCtx.w);
            strokeWidth = Array.isArray(strokeWidth) ? strokeWidth[realIndex] : strokeWidth;
            if (!strokeWidth) strokeWidth = 0;
            let bW = barWidth;
            let bXP = barXPosition;
            if ((_a = w.config.series[realIndex].data[j]) == null ? void 0 : _a.columnWidthOffset) {
                bXP = barXPosition - w.config.series[realIndex].data[j].columnWidthOffset / 2;
                bW = barWidth + w.config.series[realIndex].data[j].columnWidthOffset;
            }
            const strokeCenter = strokeWidth / 2;
            const x1 = bXP + strokeCenter;
            const x2 = bXP + bW - strokeCenter;
            const direction = (series[i][j] >= 0 ? 1 : -1) * (isReversed ? -1 : 1);
            y1 += 1e-3 - strokeCenter * direction;
            y2 += 1e-3 + strokeCenter * direction;
            const sl = graphics.line(x2, y1);
            const closing = w.config.plotOptions.bar.borderRadiusApplication === "around" || this.arrBorderRadius[realIndex][j] === "both" ? " Z" : " z";
            let pathTo = graphics.move(x1, y1) + graphics.line(x1, y2) + graphics.line(x2, y2) + sl + closing;
            if (this.arrBorderRadius[realIndex][j] !== "none") {
                pathTo = graphics.roundPathCorners(
                    pathTo,
                    w.config.plotOptions.bar.borderRadius
                );
            }
            let pathFrom;
            const morphFrom = (_c = (_b = this.barCtx.ctx) == null ? void 0 : _b.morphTypeChange) == null ? void 0 : _c.getInitialPathFor(
                realIndex,
                j
            );
            if (morphFrom) {
                pathFrom = morphFrom;
            } else if (w.globals.previousPaths.length > 0) {
                pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo);
            } else {
                pathFrom = graphics.move(x1, y1) + graphics.line(x1, y1) + sl + sl + sl + sl + sl + graphics.line(x1, y1) + closing;
            }
            if (w.config.chart.stacked) {
                let _ctx = this.barCtx;
                _ctx = this.barCtx[seriesGroup];
                _ctx.yArrj.push(y2 - strokeCenter * direction);
                _ctx.yArrjF.push(Math.abs(y1 - y2 + strokeWidth * direction));
                _ctx.yArrjVal.push(this.barCtx.series[i][j]);
            }
            return {
                pathTo,
                pathFrom
            };
        }
        /**
         * Build a trapezoidal funnel-stage path. Used when
         * `plotOptions.funnel.shape === 'trapezoid'` is active alongside `isFunnel`.
         *
         * Each stage is a 4-corner polygon whose top width matches the current
         * stage's value and bottom width matches the next stage's value, producing
         * continuous sloped sides between consecutive stages.
         *
         * For the last stage, the bottom width is configurable:
         * - `lastShape: 'flat'`  → bottom width = top width (parallel sides)
         * - `lastShape: 'taper'` → bottom width = 0 (taper to a point)
         *
         * @param {{ barYPosition: number, barHeight: number, series: any[][], i: number, j: number, realIndex: number, strokeWidth: number, w: any }} opts
         */
        getFunnelTrapezoidPaths({
            barYPosition,
            barHeight,
            series,
            i,
            j,
            realIndex,
            strokeWidth,
            w
        }) {
            var _a, _b;
            const graphics = new Graphics(this.barCtx.w);
            const center = w.layout.gridWidth / 2;
            const halfWidthFor = (v) => Math.abs(v / this.barCtx.invertedYRatio) / 2;
            const topHalf = halfWidthFor(series[i][j]);
            const lastIdx = series[i].length - 1;
            const isLast = j === lastIdx;
            const lastShape = w.config.plotOptions.funnel.lastShape === "taper" ? "taper" : "flat";
            let bottomHalf;
            if (isLast) {
                bottomHalf = lastShape === "taper" ? 0 : topHalf;
            } else {
                bottomHalf = halfWidthFor(series[i][j + 1]);
            }
            const strokeCenter = strokeWidth / 2;
            const y1 = barYPosition + strokeCenter;
            const y2 = barYPosition + barHeight - strokeCenter;
            const topLeftX = center - topHalf;
            const topRightX = center + topHalf;
            const bottomLeftX = center - bottomHalf;
            const bottomRightX = center + bottomHalf;
            const pathTo = graphics.move(topLeftX, y1) + graphics.line(topRightX, y1) + graphics.line(bottomRightX, y2) + graphics.line(bottomLeftX, y2) + " Z";
            let pathFrom;
            const morphFrom = (_b = (_a = this.barCtx.ctx) == null ? void 0 : _a.morphTypeChange) == null ? void 0 : _b.getInitialPathFor(
                realIndex,
                j
            );
            if (morphFrom) {
                pathFrom = morphFrom;
            } else if (w.globals.previousPaths.length > 0) {
                pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo);
            } else {
                pathFrom = graphics.move(center, y1) + graphics.line(center, y1) + graphics.line(center, y2) + graphics.line(center, y2) + " Z";
            }
            return {
                pathTo,
                pathFrom,
                // x is the right edge of the wider (top) side — used by dataLabel
                // positioning helpers that expect a "right" reference.
                x: topRightX,
                x1: topLeftX,
                barXPosition: center
            };
        }
        /**
         * Pre-compute the per-segment layout for a value-proportional pyramid.
         *
         * Each segment is a horizontal slice of a triangle whose apex sits at the
         * top of the plot area (width = 0) and whose base spans `gridWidth` at the
         * bottom. The vertical extent of each slice is its share of the total
         * series value, so areas track value contribution and segments share
         * edges (no gaps). The first data point is the apex, the last is the base.
         *
         * @param {any[]} seriesData - 1D array of values for a single series row
         * @returns {{ y: number, height: number, topHalf: number, bottomHalf: number }[]}
         */
        computePyramidLayout(seriesData) {
            const w = this.w;
            const gridHeight = w.layout.gridHeight;
            const gridWidth = w.layout.gridWidth;
            const values = seriesData.map(
                /** @param {any} v */
                (v) => Math.abs(Number(v) || 0)
            );
            const total = values.reduce(
                /** @param {number} a @param {number} b */
                (a, b) => a + b,
                0
            );
            if (total === 0 || gridHeight <= 0) {
                return values.map(() => ({
                    y: 0,
                    height: 0,
                    topHalf: 0,
                    bottomHalf: 0
                }));
            }
            const halfWidth = gridWidth / 2;
            let cumulative = 0;
            const layout = [];
            for (let j = 0; j < values.length; j++) {
                const topRatio = cumulative / total;
                cumulative += values[j];
                const bottomRatio = cumulative / total;
                const topY = topRatio * gridHeight;
                const bottomY = bottomRatio * gridHeight;
                layout.push({
                    y: topY,
                    height: bottomY - topY,
                    topHalf: topRatio * halfWidth,
                    bottomHalf: bottomRatio * halfWidth
                });
            }
            return layout;
        }
        /**
         * Build a single pyramid stage path. Geometry is precomputed by
         * `computePyramidLayout`; this method only renders that geometry into an
         * SVG path string plus a `pathFrom` for entry/morph animations.
         *
         * @param {{ barYPosition: number, barHeight: number, topHalf: number, bottomHalf: number, realIndex: number, j: number, strokeWidth: number, w: any }} opts
         */
        getPyramidPaths({
            barYPosition,
            barHeight,
            topHalf,
            bottomHalf,
            realIndex,
            j,
            strokeWidth,
            w
        }) {
            var _a, _b;
            const graphics = new Graphics(this.barCtx.w);
            const center = w.layout.gridWidth / 2;
            const strokeCenter = strokeWidth / 2;
            const y1 = barYPosition + strokeCenter;
            const y2 = barYPosition + barHeight - strokeCenter;
            const topLeftX = center - topHalf;
            const topRightX = center + topHalf;
            const bottomLeftX = center - bottomHalf;
            const bottomRightX = center + bottomHalf;
            const pathTo = graphics.move(topLeftX, y1) + graphics.line(topRightX, y1) + graphics.line(bottomRightX, y2) + graphics.line(bottomLeftX, y2) + " Z";
            let pathFrom;
            const morphFrom = (_b = (_a = this.barCtx.ctx) == null ? void 0 : _a.morphTypeChange) == null ? void 0 : _b.getInitialPathFor(
                realIndex,
                j
            );
            if (morphFrom) {
                pathFrom = morphFrom;
            } else if (w.globals.previousPaths.length > 0) {
                pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo);
            } else {
                pathFrom = graphics.move(center, y1) + graphics.line(center, y1) + graphics.line(center, y2) + graphics.line(center, y2) + " Z";
            }
            return {
                pathTo,
                pathFrom,
                x: topRightX,
                x1: topLeftX,
                barXPosition: center
            };
        }
        /** @param {{ barYPosition?: any, barHeight?: any, x1?: any, x2?: any, strokeWidth?: any, isReversed?: any, series?: any, seriesGroup?: any, realIndex?: any, i?: any, j?: any, w?: any }} opts */
        getBarpaths({
            barYPosition,
            barHeight,
            x1,
            x2,
            strokeWidth,
            isReversed,
            series,
            seriesGroup,
            realIndex,
            i,
            j,
            w
        }) {
            var _a, _b, _c;
            const graphics = new Graphics(this.barCtx.w);
            strokeWidth = Array.isArray(strokeWidth) ? strokeWidth[realIndex] : strokeWidth;
            if (!strokeWidth) strokeWidth = 0;
            let bYP = barYPosition;
            let bH = barHeight;
            if ((_a = w.config.series[realIndex].data[j]) == null ? void 0 : _a.barHeightOffset) {
                bYP = barYPosition - w.config.series[realIndex].data[j].barHeightOffset / 2;
                bH = barHeight + w.config.series[realIndex].data[j].barHeightOffset;
            }
            const strokeCenter = strokeWidth / 2;
            const y1 = bYP + strokeCenter;
            const y2 = bYP + bH - strokeCenter;
            const direction = (series[i][j] >= 0 ? 1 : -1) * (isReversed ? -1 : 1);
            x1 += 1e-3 + strokeCenter * direction;
            x2 += 1e-3 - strokeCenter * direction;
            const isFunnel = this.barCtx.isFunnel;
            const fromX = isFunnel ? (x1 + x2) / 2 : x1;
            const sl = graphics.line(x1, y2);
            const closing = w.config.plotOptions.bar.borderRadiusApplication === "around" || this.arrBorderRadius[realIndex][j] === "both" ? " Z" : " z";
            let pathTo = graphics.move(x1, y1) + graphics.line(x2, y1) + graphics.line(x2, y2) + sl + closing;
            if (this.arrBorderRadius[realIndex][j] !== "none") {
                pathTo = graphics.roundPathCorners(
                    pathTo,
                    w.config.plotOptions.bar.borderRadius
                );
            }
            let pathFrom;
            const morphFrom = (_c = (_b = this.barCtx.ctx) == null ? void 0 : _b.morphTypeChange) == null ? void 0 : _c.getInitialPathFor(
                realIndex,
                j
            );
            if (morphFrom) {
                pathFrom = morphFrom;
            } else if (w.globals.previousPaths.length > 0) {
                pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo);
            } else {
                const slFrom = isFunnel ? graphics.line(fromX, y2) : sl;
                pathFrom = graphics.move(fromX, y1) + graphics.line(fromX, y1) + slFrom + slFrom + slFrom + slFrom + slFrom + graphics.line(fromX, y1) + closing;
            }
            if (w.config.chart.stacked) {
                let _ctx = this.barCtx;
                _ctx = this.barCtx[seriesGroup];
                _ctx.xArrj.push(x2 + strokeCenter * direction);
                _ctx.xArrjF.push(Math.abs(x1 - x2 - strokeWidth * direction));
                _ctx.xArrjVal.push(this.barCtx.series[i][j]);
            }
            return {
                pathTo,
                pathFrom
            };
        }
        /** @param {{series: any}} opts */
        checkZeroSeries({
            series
        }) {
            const w = this.w;
            for (let zs = 0; zs < series.length; zs++) {
                let total = 0;
                for (let zsj = 0; zsj < series[w.globals.maxValsInArrayIndex].length; zsj++) {
                    total += series[zs][zsj];
                }
                if (total === 0) {
                    this.barCtx.zeroSerieses.push(zs);
                }
            }
        }
        /**
         * @param {number} value
         * @param {number} zeroW
         */
        getXForValue(value, zeroW, zeroPositionForNull = true) {
            let xForVal = zeroPositionForNull ? zeroW : null;
            if (typeof value !== "undefined" && value !== null) {
                xForVal = zeroW + value / this.barCtx.invertedYRatio - (this.barCtx.isReversed ? value / this.barCtx.invertedYRatio : 0) * 2;
            }
            return xForVal;
        }
        /**
         * @param {number} value
         * @param {number} zeroH
         * @param {number} translationsIndex
         */
        getYForValue(value, zeroH, translationsIndex, zeroPositionForNull = true) {
            let yForVal = zeroPositionForNull ? zeroH : null;
            if (typeof value !== "undefined" && value !== null) {
                yForVal = zeroH - value / this.barCtx.yRatio[translationsIndex] + (this.barCtx.isReversed ? value / this.barCtx.yRatio[translationsIndex] : 0) * 2;
            }
            return yForVal;
        }
        /**
         * @param {string} type
         * @param {number} zeroW
         * @param {number} zeroH
         * @param {number} i
         * @param {number} j
         * @param {number} translationsIndex
         */
        getGoalValues(type, zeroW, zeroH, i, j, translationsIndex) {
            const w = this.w;
            const goals = [];
            const pushGoal = (value, attrs) => {
                goals.push({
                    [type]: type === "x" ? this.getXForValue(value, zeroW, false) : this.getYForValue(value, zeroH, translationsIndex, false),
                    attrs
                });
            };
            if (w.seriesData.seriesGoals[i] && w.seriesData.seriesGoals[i][j] && Array.isArray(w.seriesData.seriesGoals[i][j])) {
                w.seriesData.seriesGoals[i][j].forEach((goal) => {
                    pushGoal(goal.value, goal);
                });
            }
            if (this.barCtx.barOptions.isDumbbell && w.rangeData.seriesRange.length) {
                const colors = this.barCtx.barOptions.dumbbellColors ? this.barCtx.barOptions.dumbbellColors : w.globals.colors;
                const commonAttrs = {
                    strokeHeight: type === "x" ? 0 : w.globals.markers.size[i],
                    strokeWidth: type === "x" ? w.globals.markers.size[i] : 0,
                    strokeDashArray: 0,
                    strokeLineCap: "round",
                    strokeColor: Array.isArray(colors[i]) ? colors[i][0] : colors[i]
                };
                pushGoal(w.rangeData.seriesRangeStart[i][j], commonAttrs);
                pushGoal(w.rangeData.seriesRangeEnd[i][j], __spreadProps(__spreadValues({}, commonAttrs), {
                    strokeColor: Array.isArray(colors[i]) ? colors[i][1] : colors[i]
                }));
            }
            return goals;
        }
        /** @param {{barXPosition: any, barYPosition: any, goalX: any, goalY: any, barWidth: any, barHeight: any}} opts */
        drawGoalLine({
            barXPosition,
            barYPosition,
            goalX,
            goalY,
            barWidth,
            barHeight
        }) {
            const graphics = new Graphics(this.barCtx.w);
            const lineGroup = graphics.group({
                className: "apexcharts-bar-goals-groups"
            });
            lineGroup.node.classList.add("apexcharts-element-hidden");
            this.barCtx.w.globals.delayedElements.push({
                el: lineGroup.node
            });
            lineGroup.attr(
                "clip-path",
                `url(#gridRectMarkerMask${this.barCtx.w.globals.cuid})`
            );
            let line = null;
            if (this.barCtx.isHorizontal) {
                if (Array.isArray(goalX)) {
                    goalX.forEach((goal) => {
                        if (goal.x >= -1 && goal.x <= graphics.w.layout.gridWidth + 1) {
                            const sHeight = typeof goal.attrs.strokeHeight !== "undefined" ? goal.attrs.strokeHeight : barHeight / 2;
                            const y = barYPosition + sHeight + barHeight / 2;
                            line = graphics.drawLine(
                                goal.x,
                                y - sHeight * 2,
                                goal.x,
                                y,
                                goal.attrs.strokeColor ? goal.attrs.strokeColor : void 0,
                                goal.attrs.strokeDashArray,
                                goal.attrs.strokeWidth ? goal.attrs.strokeWidth : 2,
                                goal.attrs.strokeLineCap
                            );
                            lineGroup.add(line);
                        }
                    });
                }
            } else {
                if (Array.isArray(goalY)) {
                    goalY.forEach((goal) => {
                        if (goal.y >= -1 && goal.y <= graphics.w.layout.gridHeight + 1) {
                            const sWidth = typeof goal.attrs.strokeWidth !== "undefined" ? goal.attrs.strokeWidth : barWidth / 2;
                            const x = barXPosition + sWidth + barWidth / 2;
                            line = graphics.drawLine(
                                x - sWidth * 2,
                                goal.y,
                                x,
                                goal.y,
                                goal.attrs.strokeColor ? goal.attrs.strokeColor : void 0,
                                goal.attrs.strokeDashArray,
                                goal.attrs.strokeHeight ? goal.attrs.strokeHeight : 2,
                                goal.attrs.strokeLineCap
                            );
                            lineGroup.add(line);
                        }
                    });
                }
            }
            return lineGroup;
        }
        /** @param {{prevPaths: any, currPaths: any, color: any, realIndex: any, j: any}} opts */
        drawBarShadow({
            prevPaths,
            currPaths,
            color,
            realIndex,
            j
        }) {
            const w = this.w;
            const {
                x: prevX2,
                x1: prevX1,
                barYPosition: prevY1
            } = prevPaths;
            const {
                x: currX2,
                x1: currX1,
                barYPosition: currY1
            } = currPaths;
            const prevY2 = prevY1 + currPaths.barHeight;
            const graphics = new Graphics(this.barCtx.w);
            const utils = new Utils$1();
            const shadowPath = graphics.move(prevX1, prevY2) + graphics.line(prevX2, prevY2) + graphics.line(currX2, currY1) + graphics.line(currX1, currY1) + graphics.line(prevX1, prevY2) + (w.config.plotOptions.bar.borderRadiusApplication === "around" || this.arrBorderRadius[realIndex][j] === "both" ? " Z" : " z");
            return graphics.drawPath({
                d: shadowPath,
                fill: utils.shadeColor(0.5, Utils$1.rgb2hex(color)),
                stroke: "none",
                strokeWidth: 0,
                fillOpacity: 1,
                classes: "apexcharts-bar-shadow apexcharts-decoration-element"
            });
        }
        /** @param {{i: any, j: any}} opts */
        getZeroValueEncounters({
            i,
            j
        }) {
            var _a;
            const w = this.w;
            let nonZeroColumns = 0;
            let zeroEncounters = 0;
            const seriesIndices = w.config.plotOptions.bar.horizontal ? w.seriesData.series.map((_, _i) => _i) : ((_a = w.globals.columnSeries) == null ? void 0 : _a.i.map((_i) => _i)) || [];
            seriesIndices.forEach((_si) => {
                const val = w.globals.seriesPercent[_si][j];
                if (val) {
                    nonZeroColumns++;
                }
                if (_si < i && val === 0) {
                    zeroEncounters++;
                }
            });
            return {
                nonZeroColumns,
                zeroEncounters
            };
        }
        /**
         * @param {number} seriesIndex
         */
        getGroupIndex(seriesIndex) {
            const w = this.w;
            const groupIndex = w.labelData.seriesGroups.findIndex(
                (group) => (
                    // w.config.series[i].name may be undefined, so use
                    // w.seriesData.seriesNames[i], which has default names for those
                    // series. w.labelData.seriesGroups[] uses the same default naming.
                    group.indexOf(w.seriesData.seriesNames[seriesIndex]) > -1
                )
            );
            const cGI = this.barCtx.columnGroupIndices;
            let columnGroupIndex = cGI.indexOf(groupIndex);
            if (columnGroupIndex < 0) {
                cGI.push(groupIndex);
                columnGroupIndex = cGI.length - 1;
            }
            return {
                groupIndex,
                columnGroupIndex
            };
        }
    };
    class Bar {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         * @param {import('../types/internal').XYRatios} xyRatios
         */
        constructor(w, ctx, xyRatios) {
            this.ctx = ctx;
            this.w = w;
            this.barOptions = w.config.plotOptions.bar;
            this.isHorizontal = this.barOptions.horizontal;
            this.strokeWidth = w.config.stroke.width;
            this.isNullValue = false;
            this.isRangeBar = w.rangeData.seriesRange.length && this.isHorizontal;
            this.isVerticalGroupedRangeBar = !w.globals.isBarHorizontal && w.rangeData.seriesRange.length && w.config.plotOptions.bar.rangeBarGroupRows;
            this.isFunnel = this.barOptions.isFunnel;
            this.isPyramid = this.barOptions.isPyramid;
            this.pyramidLayout = null;
            this.xyRatios = xyRatios;
            this.xRatio = 0;
            this.yRatio = [];
            this.invertedXRatio = 0;
            this.invertedYRatio = 0;
            this.baseLineY = [];
            this.baseLineInvertedY = 0;
            if (this.xyRatios !== null) {
                this.xRatio = xyRatios.xRatio;
                this.yRatio = xyRatios.yRatio;
                this.invertedXRatio = xyRatios.invertedXRatio;
                this.invertedYRatio = xyRatios.invertedYRatio;
                this.baseLineY = xyRatios.baseLineY;
                this.baseLineInvertedY = xyRatios.baseLineInvertedY;
            }
            this.yaxisIndex = 0;
            this.translationsIndex = 0;
            this.seriesLen = 0;
            this.pathArr = [];
            this.series = [];
            this.elSeries = null;
            this.visibleI = 0;
            this.isReversed = false;
            const ser = new Series(this.w);
            this.lastActiveBarSerieIndex = ser.getActiveConfigSeriesIndex("desc", [
                "bar",
                "column"
            ]);
            this.columnGroupIndices = [];
            const barSeriesIndices = ser.getBarSeriesIndices();
            const coreUtils = new CoreUtils(this.w);
            this.stackedSeriesTotals = coreUtils.getStackedSeriesTotals(
                this.w.config.series.map((s, i) => {
                    return barSeriesIndices.indexOf(i) === -1 ? i : -1;
                }).filter((s) => {
                    return s !== -1;
                })
            );
            this.barHelpers = new Helpers$1(this);
        }
        /** primary draw method which is called on bar object
         * @memberof Bar
         * @param {any[]} series - user supplied series values
         * @param {number} seriesIndex - the index by which series will be drawn on the svg
         * @return {Element} element which is supplied to parent chart draw method for appending
         **/
        draw(series, seriesIndex) {
            var _a, _b;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const coreUtils = new CoreUtils(this.w);
            series = coreUtils.getLogSeries(series);
            this.series = series;
            this.yRatio = coreUtils.getLogYRatios(this.yRatio);
            this.barHelpers.initVariables(series);
            const ret = graphics.group({
                class: "apexcharts-bar-series apexcharts-plot-series"
            });
            if (w.config.dataLabels.enabled) {
                if (this.totalItems > this.barOptions.dataLabels.maxItems) {
                    console.warn(
                        "WARNING: DataLabels are enabled but there are too many to display. This may cause performance issue when rendering - ApexCharts"
                    );
                }
            }
            for (let i = 0, bc = 0; i < series.length; i++, bc++) {
                let x, y;
                const yArrj = [];
                const xArrj = [];
                const realIndex = w.globals.comboCharts ? (
                    /** @type {any} */
                    seriesIndex[i]
                ) : i;
                const {
                    columnGroupIndex
                } = this.barHelpers.getGroupIndex(realIndex);
                const elSeries = graphics.group({
                    class: `apexcharts-series`,
                    rel: i + 1,
                    seriesName: Utils$1.escapeString(w.seriesData.seriesNames[realIndex]),
                    "data:realIndex": realIndex
                });
                Series.addCollapsedClassToSeries(this.w, elSeries, realIndex);
                if (series[i].length > 0) {
                    this.visibleI = this.visibleI + 1;
                }
                if (this.yRatio.length > 1) {
                    this.yaxisIndex = w.globals.seriesYAxisReverseMap[realIndex];
                    this.translationsIndex = realIndex;
                }
                const translationsIndex = this.translationsIndex;
                this.isReversed = w.config.yaxis[this.yaxisIndex] && w.config.yaxis[this.yaxisIndex].reversed;
                if (this.isPyramid) {
                    this.pyramidLayout = this.barHelpers.computePyramidLayout(series[i]);
                }
                const initPositions = this.barHelpers.initialPositions(realIndex);
                const {
                    y: initY,
                    yDivision,
                    // yDivision is the GRIDHEIGHT divided by number of datapoints (bars)
                    zeroW,
                    // zeroW is the baseline where 0 meets x axis
                    x: initX,
                    xDivision,
                    // xDivision is the GRIDWIDTH divided by number of datapoints (columns)
                    zeroH
                    // zeroH is the baseline where 0 meets y axis
                } = initPositions;
                let barHeight = initPositions.barHeight;
                let barWidth = initPositions.barWidth;
                y = initY;
                x = initX;
                if (!this.isHorizontal) {
                    xArrj.push(x + (barWidth != null ? barWidth : 0) / 2);
                }
                const elDataLabelsWrap = graphics.group({
                    class: "apexcharts-datalabels",
                    "data:realIndex": realIndex
                });
                w.globals.delayedElements.push({
                    el: elDataLabelsWrap.node
                });
                elDataLabelsWrap.node.classList.add("apexcharts-element-hidden");
                const elGoalsMarkers = graphics.group({
                    class: "apexcharts-bar-goals-markers"
                });
                const elBarShadows = graphics.group({
                    class: "apexcharts-bar-shadows"
                });
                w.globals.delayedElements.push({
                    el: elBarShadows.node
                });
                elBarShadows.node.classList.add("apexcharts-element-hidden");
                for (let j = 0; j < series[i].length; j++) {
                    const strokeWidth = this.barHelpers.getStrokeWidth(i, j, realIndex);
                    let paths = (
                        /** @type {any} */
                        null
                    );
                    const pathsParams = {
                        indexes: {
                            i,
                            j,
                            realIndex,
                            translationsIndex,
                            bc
                        },
                        x,
                        y,
                        strokeWidth,
                        elSeries
                    };
                    if (this.isHorizontal) {
                        paths = this.drawBarPaths(__spreadProps(__spreadValues({}, pathsParams), {
                            barHeight,
                            zeroW,
                            yDivision
                        }));
                        barWidth = this.series[i][j] / this.invertedYRatio;
                    } else {
                        paths = this.drawColumnPaths(__spreadProps(__spreadValues({}, pathsParams), {
                            xDivision,
                            barWidth,
                            zeroH
                        }));
                        barHeight = this.series[i][j] / this.yRatio[translationsIndex];
                    }
                    const pathFill = this.barHelpers.getPathFillColor(
                        series,
                        i,
                        j,
                        realIndex
                    );
                    if (this.isFunnel && !this.isPyramid && this.barOptions.isFunnel3d && ((_a = w.config.plotOptions.funnel) == null ? void 0 : _a.shape) !== "trapezoid" && this.pathArr.length && j > 0) {
                        const barShadow = this.barHelpers.drawBarShadow({
                            color: typeof pathFill.color === "string" && ((_b = pathFill.color) == null ? void 0 : _b.indexOf("url")) === -1 ? pathFill.color : Utils$1.hexToRgba(w.globals.colors[i]),
                            prevPaths: this.pathArr[this.pathArr.length - 1],
                            currPaths: paths,
                            realIndex,
                            j
                        });
                        elBarShadows.add(barShadow);
                        if (w.config.chart.dropShadow.enabled) {
                            const filters = new Filters(this.w);
                            filters.dropShadow(barShadow, w.config.chart.dropShadow, realIndex);
                        }
                    }
                    this.pathArr.push(paths);
                    const barGoalLine = this.barHelpers.drawGoalLine({
                        barXPosition: paths.barXPosition,
                        barYPosition: paths.barYPosition,
                        goalX: paths.goalX,
                        goalY: paths.goalY,
                        barHeight,
                        barWidth
                    });
                    if (barGoalLine) {
                        elGoalsMarkers.add(barGoalLine);
                    }
                    y = paths.y;
                    x = paths.x;
                    if (j > 0) {
                        xArrj.push(x + (barWidth != null ? barWidth : 0) / 2);
                    }
                    yArrj.push(y);
                    this.renderSeries(__spreadProps(__spreadValues({
                        realIndex,
                        pathFill: pathFill.color
                    }, pathFill.useRangeColor ? {
                        lineFill: pathFill.color
                    } : {}), {
                        j,
                        i,
                        columnGroupIndex,
                        pathFrom: paths.pathFrom,
                        pathTo: paths.pathTo,
                        strokeWidth,
                        elSeries,
                        x,
                        y,
                        series,
                        barHeight: Math.abs(paths.barHeight ? paths.barHeight : barHeight),
                        barWidth: Math.abs(paths.barWidth ? paths.barWidth : barWidth),
                        elDataLabelsWrap,
                        elGoalsMarkers,
                        elBarShadows,
                        visibleSeries: this.visibleI,
                        type: "bar"
                    }));
                }
                w.globals.seriesXvalues[realIndex] = xArrj;
                w.globals.seriesYvalues[realIndex] = yArrj;
                ret.add(elSeries);
            }
            return ret;
        }
        /** @param {{ realIndex?: any, pathFill?: any, lineFill?: any, j?: any, i?: any, columnGroupIndex?: any, pathFrom?: any, pathTo?: any, strokeWidth?: any, elSeries?: any, x?: any, y?: any, y1?: any, y2?: any, series?: any, barHeight?: any, barWidth?: any, barXPosition?: any, barYPosition?: any, elDataLabelsWrap?: any, elGoalsMarkers?: any, elBarShadows?: any, visibleSeries?: any, type?: any, classes?: any }} opts */
        renderSeries({
            realIndex,
            pathFill,
            lineFill,
            j,
            i,
            columnGroupIndex,
            pathFrom,
            pathTo,
            strokeWidth,
            elSeries,
            x,
            // x pos
            y,
            // y pos
            y1,
            // absolute value
            y2,
            // absolute value
            series,
            barHeight,
            barWidth,
            barXPosition,
            barYPosition,
            elDataLabelsWrap,
            elGoalsMarkers,
            elBarShadows,
            visibleSeries,
            type,
            classes
        }) {
            var _a;
            const w = this.w;
            const graphics = new Graphics(this.w, this.ctx);
            let skipDrawing = false;
            if (!elSeries._bindingsDelegated) {
                elSeries._bindingsDelegated = true;
                graphics.setupEventDelegation(elSeries, `.apexcharts-${type}-area`);
            }
            if (!lineFill) {
                let fetchColor = function(i2) {
                    const exp = w.config.stroke.colors;
                    let c;
                    if (Array.isArray(exp) && exp.length > 0) {
                        c = exp[i2];
                        if (!c) c = "";
                        if (typeof c === "function") {
                            return c({
                                value: w.seriesData.series[i2][j],
                                dataPointIndex: j,
                                w
                            });
                        }
                    }
                    return c;
                };
                const checkAvailableColor = typeof w.globals.stroke.colors[realIndex] === "function" ? fetchColor(realIndex) : w.globals.stroke.colors[realIndex];
                lineFill = this.barOptions.distributed ? w.globals.stroke.colors[j] : checkAvailableColor;
            }
            const barDataLabels = new BarDataLabels(this);
            const dataLabelsObj = (
                /** @type {any} */
                barDataLabels.handleBarDataLabels({
                    x,
                    y,
                    y1,
                    y2,
                    i,
                    j,
                    series,
                    realIndex,
                    columnGroupIndex,
                    barHeight,
                    barWidth,
                    barXPosition,
                    barYPosition,
                    visibleSeries
                })
            );
            if (!w.globals.isBarHorizontal) {
                if (dataLabelsObj.dataLabelsPos.dataLabelsX + Math.max(barWidth, w.globals.barPadForNumericAxis) < 0 || dataLabelsObj.dataLabelsPos.dataLabelsX - Math.max(barWidth, w.globals.barPadForNumericAxis) > w.layout.gridWidth) {
                    skipDrawing = true;
                }
            }
            if (
                /** @type {Record<string,any>} */
                w.config.series[i].data[j] && /** @type {Record<string,any>} */
                w.config.series[i].data[j].strokeColor
            ) {
                lineFill = /** @type {Record<string,any>} */
                    w.config.series[i].data[j].strokeColor;
            }
            if (this.isNullValue) {
                pathFill = "none";
            }
            const animCfg = w.config.chart.animations;
            const gradCfg = animCfg.animateGradually;
            const staggerEnabled = gradCfg && gradCfg.enabled !== false;
            let delay = 0;
            if (staggerEnabled) {
                const totalBars = w.globals.dataPoints || 1;
                const configStep = gradCfg.delay || 0;
                const baseDelayMs = Math.min(
                    configStep,
                    animCfg.speed * 0.5 / Math.max(1, totalBars)
                );
                let delayMs = computeStagger({
                    style: "sequential",
                    index: j,
                    baseDelay: baseDelayMs
                });
                if (w.config.chart.stacked) {
                    delayMs += i * baseDelayMs * 0.5;
                }
                const delayFactor = configStep || 1;
                delay = delayMs / delayFactor;
            }
            if (!skipDrawing) {
                const morphActive = ((_a = this.ctx.morphTypeChange) == null ? void 0 : _a.isActive()) === true;
                const dataChangeSpeed = morphActive ? this.ctx.morphTypeChange.getSpeed() : w.config.chart.animations.dynamicAnimation.speed;
                const renderedPath = (
                    /** @type {any} */
                    graphics.renderPaths({
                        i,
                        j,
                        realIndex,
                        pathFrom,
                        pathTo,
                        stroke: lineFill,
                        strokeWidth,
                        strokeLineCap: w.config.stroke.lineCap,
                        fill: pathFill,
                        animationDelay: delay,
                        initialSpeed: w.config.chart.animations.speed,
                        dataChangeSpeed,
                        className: `apexcharts-${type}-area ${classes}`,
                        chartType: type,
                        bindEventsOnPaths: false
                    })
                );
                renderedPath.attr("clip-path", `url(#gridRectBarMask${w.globals.cuid})`);
                const forecast = w.config.forecastDataPoints;
                if (forecast.count > 0) {
                    if (j >= w.globals.dataPoints - forecast.count) {
                        renderedPath.node.setAttribute("stroke-dasharray", forecast.dashArray);
                        renderedPath.node.setAttribute("stroke-width", forecast.strokeWidth);
                        renderedPath.node.setAttribute("fill-opacity", forecast.fillOpacity);
                    }
                }
                if (typeof y1 !== "undefined" && typeof y2 !== "undefined") {
                    renderedPath.attr("data-range-y1", y1);
                    renderedPath.attr("data-range-y2", y2);
                }
                const filters = new Filters(this.w);
                filters.setSelectionFilter(renderedPath, realIndex, j);
                elSeries.add(renderedPath);
                renderedPath.attr({
                    cy: dataLabelsObj.dataLabelsPos.bcy,
                    cx: dataLabelsObj.dataLabelsPos.bcx,
                    j,
                    val: w.seriesData.series[i][j],
                    barHeight,
                    barWidth
                });
                if (dataLabelsObj.dataLabels !== null) {
                    elDataLabelsWrap.add(dataLabelsObj.dataLabels);
                }
                if (dataLabelsObj.totalDataLabels) {
                    elDataLabelsWrap.add(dataLabelsObj.totalDataLabels);
                }
                elSeries.add(elDataLabelsWrap);
                if (elGoalsMarkers) {
                    elSeries.add(elGoalsMarkers);
                }
                if (elBarShadows) {
                    elSeries.add(elBarShadows);
                }
            }
            return elSeries;
        }
        /** @param {{indexes: any, barHeight: any, strokeWidth: any, zeroW: any, x: any, y: any, yDivision: any, elSeries: any}} opts */
        drawBarPaths({
            indexes,
            barHeight,
            strokeWidth,
            zeroW,
            x,
            y,
            yDivision,
            elSeries
        }) {
            const w = this.w;
            const i = indexes.i;
            const j = indexes.j;
            let barYPosition;
            if (w.axisFlags.isXNumeric) {
                y = (w.seriesData.seriesX[i][j] - w.globals.minX) / this.invertedXRatio - barHeight;
                barYPosition = y + barHeight * this.visibleI;
            } else {
                if (w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
                    const {
                        nonZeroColumns,
                        zeroEncounters
                    } = this.barHelpers.getZeroValueEncounters({
                        i,
                        j
                    });
                    if (nonZeroColumns > 0) {
                        barHeight = this.seriesLen * barHeight / nonZeroColumns;
                    }
                    barYPosition = y + barHeight * this.visibleI;
                    barYPosition -= barHeight * zeroEncounters;
                } else {
                    barYPosition = y + barHeight * this.visibleI;
                }
            }
            const useTrapezoid = this.isFunnel && w.config.plotOptions.funnel.shape === "trapezoid";
            const pyramidSeg = this.isPyramid && this.pyramidLayout ? this.pyramidLayout[j] : null;
            const usePyramid = !!pyramidSeg;
            if (pyramidSeg) {
                barYPosition = pyramidSeg.y;
                barHeight = pyramidSeg.height;
            } else if (this.isFunnel && !useTrapezoid) {
                const _zeroW = zeroW != null ? zeroW : 0;
                zeroW = _zeroW - /** @type {number} */
                    /** @type {any} */
                    (this.barHelpers.getXForValue(
                        /** @type {any} */
                        this.series[i][j],
                        _zeroW
                    ) - _zeroW) / 2;
            }
            x = this.barHelpers.getXForValue(
                /** @type {any} */
                this.series[i][j],
                zeroW != null ? zeroW : 0
            );
            let paths;
            if (pyramidSeg) {
                paths = /** @type {any} */
                    this.barHelpers.getPyramidPaths({
                        barYPosition,
                        barHeight,
                        topHalf: pyramidSeg.topHalf,
                        bottomHalf: pyramidSeg.bottomHalf,
                        realIndex: indexes.realIndex,
                        j,
                        strokeWidth,
                        w
                    });
            } else if (useTrapezoid) {
                paths = /** @type {any} */
                    this.barHelpers.getFunnelTrapezoidPaths({
                        barYPosition,
                        barHeight,
                        series: (
                            /** @type {any} */
                            this.series
                        ),
                        i,
                        j,
                        realIndex: indexes.realIndex,
                        strokeWidth,
                        w
                    });
            } else {
                paths = /** @type {any} */
                    this.barHelpers.getBarpaths({
                        barYPosition,
                        barHeight,
                        x1: zeroW,
                        x2: x,
                        strokeWidth,
                        isReversed: this.isReversed,
                        series: this.series,
                        realIndex: indexes.realIndex,
                        i,
                        j,
                        w
                    });
            }
            if (useTrapezoid || usePyramid) {
                zeroW = paths.x1;
                x = paths.x;
            }
            if (!w.axisFlags.isXNumeric && !usePyramid) {
                y = y + yDivision;
            }
            if (usePyramid) {
                y = barYPosition;
            }
            this.barHelpers.barBackground({
                j,
                i,
                y1: barYPosition - barHeight * this.visibleI,
                y2: barHeight * this.seriesLen,
                elSeries
            });
            return {
                pathTo: paths.pathTo,
                pathFrom: paths.pathFrom,
                x1: zeroW,
                x,
                y,
                goalX: this.barHelpers.getGoalValues(
                    "x",
                    zeroW,
                    /** @type {any} */
                    null,
                    i,
                    j,
                    0
                ),
                barYPosition,
                barHeight
            };
        }
        /** @param {{indexes: any, x: any, y: any, xDivision: any, barWidth: any, zeroH: any, strokeWidth: any, elSeries: any}} opts */
        drawColumnPaths({
            indexes,
            x,
            y,
            xDivision,
            barWidth,
            zeroH,
            strokeWidth,
            elSeries
        }) {
            const w = this.w;
            const realIndex = indexes.realIndex;
            const translationsIndex = indexes.translationsIndex;
            const i = indexes.i;
            const j = indexes.j;
            const bc = indexes.bc;
            let barXPosition;
            if (w.axisFlags.isXNumeric) {
                const xForNumericX = this.getBarXForNumericXAxis({
                    x,
                    j,
                    realIndex,
                    barWidth
                });
                x = xForNumericX.x;
                barXPosition = xForNumericX.barXPosition;
            } else {
                if (w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
                    const {
                        nonZeroColumns,
                        zeroEncounters
                    } = this.barHelpers.getZeroValueEncounters({
                        i,
                        j
                    });
                    if (nonZeroColumns > 0) {
                        barWidth = this.seriesLen * barWidth / nonZeroColumns;
                    }
                    barXPosition = x + barWidth * this.visibleI;
                    barXPosition -= barWidth * zeroEncounters;
                } else {
                    barXPosition = x + barWidth * this.visibleI;
                }
            }
            y = this.barHelpers.getYForValue(
                /** @type {any} */
                this.series[i][j],
                zeroH,
                translationsIndex
            );
            const paths = (
                /** @type {any} */
                this.barHelpers.getColumnPaths({
                    barXPosition,
                    barWidth,
                    y1: zeroH,
                    y2: y,
                    strokeWidth,
                    isReversed: this.isReversed,
                    series: this.series,
                    realIndex,
                    i,
                    j,
                    w
                })
            );
            if (!w.axisFlags.isXNumeric) {
                x = x + xDivision;
            }
            this.barHelpers.barBackground({
                bc,
                j,
                i,
                x1: barXPosition - strokeWidth / 2 - barWidth * this.visibleI,
                x2: barWidth * this.seriesLen + strokeWidth / 2,
                elSeries
            });
            return {
                pathTo: paths.pathTo,
                pathFrom: paths.pathFrom,
                x,
                y,
                goalY: this.barHelpers.getGoalValues(
                    "y",
                    /** @type {any} */
                    null,
                    zeroH,
                    i,
                    j,
                    translationsIndex
                ),
                barXPosition,
                barWidth
            };
        }
        /** @param {{x: any, barWidth: any, realIndex: any, j: any}} opts */
        getBarXForNumericXAxis({
            x,
            barWidth,
            realIndex,
            j
        }) {
            const w = this.w;
            let sxI = realIndex;
            if (!w.seriesData.seriesX[realIndex].length) {
                sxI = w.globals.maxValsInArrayIndex;
            }
            if (Utils$1.isNumber(w.seriesData.seriesX[sxI][j])) {
                x = (w.seriesData.seriesX[sxI][j] - w.globals.minX) / this.xRatio - barWidth * this.seriesLen / 2;
            }
            return {
                barXPosition: x + barWidth * this.visibleI,
                x
            };
        }
        /**
         * Resolve `pathFrom` for a bar on data update. Returns the previous render's
         * `d` string for the same `(realIndex, j)` only when its SVG command count
         * matches `pathTo` — that's the survivor-with-stable-shape case where SVG.js
         * morph produces a smooth resize. When commands mismatch (corner state
         * flipped, e.g. bar became new top-of-stack after legend toggle) or the bar
         * is genuinely new (no captured previous), returns `pathTo` — which makes
         * pathFrom === pathTo so morph is a visual no-op (snap).
         *
         * @param {number} realIndex - stable series index from `data:realIndex`
         * @param {number} j - data-point index within the series
         * @param {string} pathTo - the freshly-built path for this bar (post-roundPathCorners)
         * @returns {string}
         **/
        getPreviousPath(realIndex, j, pathTo) {
            const w = this.w;
            let oldD = null;
            for (let pp = 0; pp < w.globals.previousPaths.length; pp++) {
                const gpp = w.globals.previousPaths[pp];
                if (gpp.paths && gpp.paths.length > 0 && parseInt(gpp.realIndex, 10) === parseInt(String(realIndex), 10)) {
                    if (typeof gpp.paths[j] !== "undefined") {
                        oldD = gpp.paths[j].d;
                    }
                }
            }
            if (oldD && Bar.pathCommandCount(oldD) === Bar.pathCommandCount(pathTo)) {
                return oldD;
            }
            return pathTo;
        }
        /**
         * Count SVG path commands (M, L, C, Q, Z, etc.). Used to detect whether
         * two paths can be morphed safely — SVG.js requires matching command counts.
         *
         * @param {string} d
         * @returns {number}
         */
        static pathCommandCount(d) {
            if (!d) return 0;
            const matches = d.match(/[A-Za-z]/g);
            return matches ? matches.length : 0;
        }
    }
    class BarStacked extends Bar {
        /**
         * @param {any[]} series
         * @param {number} seriesIndex
         */
        draw(series, seriesIndex) {
            const w = this.w;
            this.graphics = new Graphics(this.w);
            this.bar = new Bar(this.w, this.ctx, this.xyRatios);
            const coreUtils = new CoreUtils(this.w);
            series = coreUtils.getLogSeries(series);
            this.yRatio = coreUtils.getLogYRatios(this.yRatio);
            this.barHelpers.initVariables(series);
            if (w.config.chart.stackType === "100%") {
                series = w.globals.comboCharts ? (
                    /** @type {any} */
                    seriesIndex.map(
                        (_) => w.globals.seriesPercent[_]
                    )
                ) : w.globals.seriesPercent.slice();
            }
            this.series = series;
            this.barHelpers.initializeStackedPrevVars(this);
            const ret = this.graphics.group({
                class: "apexcharts-bar-series apexcharts-plot-series"
            });
            let x = 0;
            let y = 0;
            for (let i = 0, bc = 0; i < series.length; i++, bc++) {
                const realIndex = w.globals.comboCharts ? (
                    /** @type {any} */
                    seriesIndex[i]
                ) : i;
                const {
                    groupIndex,
                    columnGroupIndex
                } = this.barHelpers.getGroupIndex(realIndex);
                this.groupCtx = /** @type {any} */
                    this[
                        /** @type {any} */
                        w.labelData.seriesGroups[groupIndex]
                    ];
                const xArrValues = [];
                const yArrValues = [];
                let translationsIndex = 0;
                if (this.yRatio.length > 1) {
                    this.yaxisIndex = /** @type {any} */
                        w.globals.seriesYAxisReverseMap[realIndex][0];
                    translationsIndex = realIndex;
                }
                this.isReversed = w.config.yaxis[this.yaxisIndex] && w.config.yaxis[this.yaxisIndex].reversed;
                let elSeries = this.graphics.group({
                    class: `apexcharts-series`,
                    seriesName: Utils$1.escapeString(w.seriesData.seriesNames[realIndex]),
                    rel: i + 1,
                    "data:realIndex": realIndex
                });
                Series.addCollapsedClassToSeries(this.w, elSeries, realIndex);
                const elDataLabelsWrap = this.graphics.group({
                    class: "apexcharts-datalabels",
                    "data:realIndex": realIndex
                });
                const elGoalsMarkers = this.graphics.group({
                    class: "apexcharts-bar-goals-markers"
                });
                const initPositions = this.initialPositions(
                    x,
                    y,
                    void 0,
                    void 0,
                    void 0,
                    void 0,
                    translationsIndex
                );
                const {
                    xDivision,
                    // xDivision is the GRIDWIDTH divided by number of datapoints (columns)
                    yDivision,
                    // yDivision is the GRIDHEIGHT divided by number of datapoints (bars)
                    zeroH,
                    // zeroH is the baseline where 0 meets y axis
                    zeroW
                    // zeroW is the baseline where 0 meets x axis
                } = initPositions;
                let barHeight = initPositions.barHeight;
                let barWidth = initPositions.barWidth;
                y = initPositions.y;
                x = initPositions.x;
                w.globals.barHeight = barHeight;
                w.globals.barWidth = barWidth;
                this.barHelpers.initializeStackedXYVars(this);
                if (this.groupCtx.prevY.length === 1 &&
                    /**
                     * @param {number} val
                     */
                    this.groupCtx.prevY[0].every((val) => isNaN(val))) {
                    this.groupCtx.prevY[0] = this.groupCtx.prevY[0].map(() => zeroH);
                    this.groupCtx.prevYF[0] = this.groupCtx.prevYF[0].map(() => 0);
                }
                for (let j = 0; j < w.globals.dataPoints; j++) {
                    const strokeWidth = this.barHelpers.getStrokeWidth(i, j, realIndex);
                    const commonPathOpts = {
                        indexes: {
                            i,
                            j,
                            realIndex,
                            translationsIndex,
                            bc
                        },
                        strokeWidth,
                        x,
                        y,
                        elSeries,
                        columnGroupIndex,
                        seriesGroup: w.labelData.seriesGroups[groupIndex]
                    };
                    let paths = (
                        /** @type {any} */
                        null
                    );
                    if (this.isHorizontal) {
                        paths = this.drawStackedBarPaths(__spreadProps(__spreadValues({}, commonPathOpts), {
                            zeroW,
                            barHeight,
                            yDivision
                        }));
                        barWidth = this.series[i][j] / this.invertedYRatio;
                    } else {
                        paths = this.drawStackedColumnPaths(__spreadProps(__spreadValues({}, commonPathOpts), {
                            xDivision,
                            barWidth,
                            zeroH
                        }));
                        barHeight = this.series[i][j] / this.yRatio[translationsIndex];
                    }
                    const barGoalLine = this.barHelpers.drawGoalLine({
                        barXPosition: paths.barXPosition,
                        barYPosition: paths.barYPosition,
                        goalX: paths.goalX,
                        goalY: paths.goalY,
                        barHeight,
                        barWidth
                    });
                    if (barGoalLine) {
                        elGoalsMarkers.add(barGoalLine);
                    }
                    y = paths.y;
                    x = paths.x;
                    xArrValues.push(x);
                    yArrValues.push(y);
                    const pathFill = this.barHelpers.getPathFillColor(
                        series,
                        i,
                        j,
                        realIndex
                    );
                    let classes = "";
                    const flipClass = w.globals.isBarHorizontal ? "apexcharts-flip-x" : "apexcharts-flip-y";
                    if (this.barHelpers.arrBorderRadius[realIndex][j] === "bottom" && w.seriesData.series[realIndex][j] > 0 || this.barHelpers.arrBorderRadius[realIndex][j] === "top" && w.seriesData.series[realIndex][j] < 0) {
                        classes = flipClass;
                    }
                    elSeries = this.renderSeries(__spreadProps(__spreadValues({
                        realIndex,
                        pathFill: pathFill.color
                    }, pathFill.useRangeColor ? {
                        lineFill: pathFill.color
                    } : {}), {
                        j,
                        i,
                        columnGroupIndex,
                        pathFrom: paths.pathFrom,
                        pathTo: paths.pathTo,
                        strokeWidth,
                        elSeries,
                        x,
                        y,
                        series,
                        barHeight,
                        barWidth,
                        elDataLabelsWrap,
                        elGoalsMarkers,
                        type: "bar",
                        visibleSeries: columnGroupIndex,
                        classes
                    }));
                }
                w.globals.seriesXvalues[realIndex] = xArrValues;
                w.globals.seriesYvalues[realIndex] = yArrValues;
                this.groupCtx.prevY.push(this.groupCtx.yArrj);
                this.groupCtx.prevYF.push(this.groupCtx.yArrjF);
                this.groupCtx.prevYVal.push(this.groupCtx.yArrjVal);
                this.groupCtx.prevX.push(this.groupCtx.xArrj);
                this.groupCtx.prevXF.push(this.groupCtx.xArrjF);
                this.groupCtx.prevXVal.push(this.groupCtx.xArrjVal);
                ret.add(elSeries);
            }
            return ret;
        }
        /**
         * @param {number} x
         * @param {number} y
         * @param {number | undefined} xDivision
         * @param {number | undefined} yDivision
         * @param {number | undefined} zeroH
         * @param {number | undefined} zeroW
         * @param {number} translationsIndex
         */
        initialPositions(x, y, xDivision, yDivision, zeroH, zeroW, translationsIndex) {
            const w = this.w;
            let barHeight, barWidth;
            if (this.isHorizontal) {
                yDivision = w.layout.gridHeight / w.globals.dataPoints;
                const userBarHeight = w.config.plotOptions.bar.barHeight;
                if (String(userBarHeight).indexOf("%") === -1) {
                    barHeight = parseInt(userBarHeight, 10);
                } else {
                    barHeight = yDivision * parseInt(userBarHeight, 10) / 100;
                }
                zeroW = w.globals.padHorizontal + (this.isReversed ? w.layout.gridWidth - this.baseLineInvertedY : this.baseLineInvertedY);
                y = (yDivision - barHeight) / 2;
            } else {
                xDivision = w.layout.gridWidth / w.globals.dataPoints;
                barWidth = xDivision;
                const userColumnWidth = w.config.plotOptions.bar.columnWidth;
                if (w.axisFlags.isXNumeric && w.globals.dataPoints > 1) {
                    xDivision = w.globals.minXDiff / this.xRatio;
                    barWidth = xDivision * parseInt(this.barOptions.columnWidth, 10) / 100;
                } else if (String(userColumnWidth).indexOf("%") === -1) {
                    barWidth = parseInt(userColumnWidth, 10);
                } else {
                    barWidth *= parseInt(userColumnWidth, 10) / 100;
                }
                if (this.isReversed) {
                    zeroH = this.baseLineY[translationsIndex];
                } else {
                    zeroH = w.layout.gridHeight - this.baseLineY[translationsIndex];
                }
                x = w.globals.padHorizontal + (xDivision - barWidth) / 2;
            }
            const subDivisions = w.globals.barGroups.length || 1;
            return {
                x,
                y,
                yDivision,
                xDivision,
                barHeight: (barHeight != null ? barHeight : 0) / subDivisions,
                barWidth: (barWidth != null ? barWidth : 0) / subDivisions,
                zeroH,
                zeroW
            };
        }
        /** @param {{indexes: any, barHeight: any, strokeWidth: any, zeroW: any, x: any, y: any, columnGroupIndex: any, seriesGroup: any, yDivision: any, elSeries: any}} opts */
        drawStackedBarPaths({
            indexes,
            barHeight,
            strokeWidth,
            zeroW,
            x,
            y,
            columnGroupIndex,
            seriesGroup,
            yDivision,
            elSeries
        }) {
            var _a, _b, _c, _d, _e;
            const w = this.w;
            const barYPosition = y + columnGroupIndex * barHeight;
            let barXPosition;
            const i = indexes.i;
            const j = indexes.j;
            const realIndex = indexes.realIndex;
            const translationsIndex = indexes.translationsIndex;
            let prevBarW = 0;
            for (let k = 0; k < this.groupCtx.prevXF.length; k++) {
                prevBarW = prevBarW + this.groupCtx.prevXF[k][j];
            }
            let gsi = i;
            if (
                /** @type {Record<string,any>} */
                w.config.series[realIndex].name
            ) {
                gsi = seriesGroup.indexOf(
                    /** @type {Record<string,any>} */
                    w.config.series[realIndex].name
                );
            }
            if (gsi > 0) {
                let bXP = zeroW;
                if (this.groupCtx.prevXVal[gsi - 1][j] < 0) {
                    bXP = /** @type {any} */
                        ((_a = this.series[i]) == null ? void 0 : _a[j]) >= 0 ? this.groupCtx.prevX[gsi - 1][j] + prevBarW - (this.isReversed ? prevBarW : 0) * 2 : this.groupCtx.prevX[gsi - 1][j];
                } else if (this.groupCtx.prevXVal[gsi - 1][j] >= 0) {
                    bXP = /** @type {any} */
                        ((_b = this.series[i]) == null ? void 0 : _b[j]) >= 0 ? this.groupCtx.prevX[gsi - 1][j] : this.groupCtx.prevX[gsi - 1][j] - prevBarW + (this.isReversed ? prevBarW : 0) * 2;
                }
                barXPosition = bXP;
            } else {
                barXPosition = zeroW;
            }
            if (
                /** @type {any} */
                ((_c = this.series[i]) == null ? void 0 : _c[j]) === null
            ) {
                x = barXPosition;
            } else {
                x = barXPosition + /** @type {any} */
                    ((_d = this.series[i]) == null ? void 0 : _d[j]) / this.invertedYRatio - (this.isReversed ? (
                        /** @type {any} */
                        ((_e = this.series[i]) == null ? void 0 : _e[j]) / this.invertedYRatio
                    ) : 0) * 2;
            }
            const paths = this.barHelpers.getBarpaths({
                barYPosition,
                barHeight,
                x1: barXPosition,
                x2: x,
                strokeWidth,
                isReversed: this.isReversed,
                series: this.series,
                realIndex: indexes.realIndex,
                seriesGroup,
                i,
                j,
                w
            });
            this.barHelpers.barBackground({
                j,
                i,
                y1: barYPosition,
                y2: barHeight,
                elSeries
            });
            y = y + yDivision;
            return {
                pathTo: paths.pathTo,
                pathFrom: paths.pathFrom,
                goalX: this.barHelpers.getGoalValues(
                    "x",
                    zeroW,
                    /** @type {any} */
                    null,
                    i,
                    j,
                    translationsIndex
                ),
                barXPosition,
                barYPosition,
                x,
                y
            };
        }
        /** @param {{indexes: any, x: any, y: any, xDivision: any, barWidth: any, zeroH: any, columnGroupIndex: any, seriesGroup: any, elSeries: any}} opts */
        drawStackedColumnPaths({
            indexes,
            x,
            y,
            xDivision,
            barWidth,
            zeroH,
            columnGroupIndex,
            seriesGroup,
            elSeries
        }) {
            var _a, _b, _c, _d, _e, _f, _g, _h, _i;
            const w = this.w;
            const i = indexes.i;
            const j = indexes.j;
            const bc = indexes.bc;
            const realIndex = indexes.realIndex;
            const translationsIndex = indexes.translationsIndex;
            if (w.axisFlags.isXNumeric) {
                let seriesVal = w.seriesData.seriesX[realIndex][j];
                if (!seriesVal) seriesVal = 0;
                x = (seriesVal - w.globals.minX) / this.xRatio - barWidth / 2 * w.globals.barGroups.length;
            }
            const barXPosition = x + columnGroupIndex * barWidth;
            let barYPosition;
            let prevBarH = 0;
            for (let k = 0; k < this.groupCtx.prevYF.length; k++) {
                prevBarH = prevBarH + (!isNaN(this.groupCtx.prevYF[k][j]) ? this.groupCtx.prevYF[k][j] : 0);
            }
            let gsi = i;
            if (seriesGroup) {
                gsi = seriesGroup.indexOf(w.seriesData.seriesNames[realIndex]);
            }
            if (gsi > 0 && !w.axisFlags.isXNumeric || gsi > 0 && w.axisFlags.isXNumeric && w.seriesData.seriesX[realIndex - 1][j] === w.seriesData.seriesX[realIndex][j]) {
                let bYP;
                let prevYValue;
                const p = Math.min(this.yRatio.length + 1, realIndex + 1);
                if (this.groupCtx.prevY[gsi - 1] !== void 0 && this.groupCtx.prevY[gsi - 1].length) {
                    for (let ii = 1; ii < p; ii++) {
                        if (!isNaN((_a = this.groupCtx.prevY[gsi - ii]) == null ? void 0 : _a[j])) {
                            prevYValue = this.groupCtx.prevY[gsi - ii][j];
                            break;
                        }
                    }
                }
                for (let ii = 1; ii < p; ii++) {
                    if (((_b = this.groupCtx.prevYVal[gsi - ii]) == null ? void 0 : _b[j]) < 0) {
                        bYP = /** @type {any} */
                            ((_c = this.series[i]) == null ? void 0 : _c[j]) >= 0 ? prevYValue - prevBarH + (this.isReversed ? prevBarH : 0) * 2 : prevYValue;
                        break;
                    } else if (((_d = this.groupCtx.prevYVal[gsi - ii]) == null ? void 0 : _d[j]) >= 0) {
                        bYP = /** @type {any} */
                            ((_e = this.series[i]) == null ? void 0 : _e[j]) >= 0 ? prevYValue : prevYValue + prevBarH - (this.isReversed ? prevBarH : 0) * 2;
                        break;
                    }
                }
                if (typeof bYP === "undefined") bYP = w.layout.gridHeight;
                if (
                    /**
                     * @param {number} val
                     */
                    ((_f = this.groupCtx.prevYF[0]) == null ? void 0 : _f.every((val) => val === 0)) && this.groupCtx.prevYF.slice(1, gsi).every(
                        (arr) => arr.every((val) => isNaN(val))
                    )
                ) {
                    barYPosition = zeroH;
                } else {
                    barYPosition = bYP;
                }
            } else {
                barYPosition = zeroH;
            }
            if (
                /** @type {any} */
                (_g = this.series[i]) == null ? void 0 : _g[j]
            ) {
                y = barYPosition - /** @type {any} */
                    ((_h = this.series[i]) == null ? void 0 : _h[j]) / this.yRatio[translationsIndex] + (this.isReversed ? (
                        /** @type {any} */
                        ((_i = this.series[i]) == null ? void 0 : _i[j]) / this.yRatio[translationsIndex]
                    ) : 0) * 2;
            } else {
                y = barYPosition;
            }
            const paths = this.barHelpers.getColumnPaths({
                barXPosition,
                barWidth,
                y1: barYPosition,
                y2: y,
                yRatio: this.yRatio[translationsIndex],
                strokeWidth: this.strokeWidth,
                isReversed: this.isReversed,
                series: this.series,
                seriesGroup,
                realIndex: indexes.realIndex,
                i,
                j,
                w
            });
            this.barHelpers.barBackground({
                bc,
                j,
                i,
                x1: barXPosition,
                x2: barWidth,
                elSeries
            });
            return {
                pathTo: paths.pathTo,
                pathFrom: paths.pathFrom,
                goalY: this.barHelpers.getGoalValues(
                    "y",
                    /** @type {any} */
                    null,
                    zeroH,
                    i,
                    j,
                    0
                ),
                barXPosition,
                x: w.axisFlags.isXNumeric ? x : x + xDivision,
                y
            };
        }
    }
    class BoxCandleStick extends Bar {
        /**
         * @param {any[]} series
         * @param {string} ctype
         * @param {number} seriesIndex
         */
        // @ts-ignore -- BoxCandleStick.draw has an extra ctype param compared to Bar.draw
        draw(series, ctype, seriesIndex) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const type = w.globals.comboCharts ? ctype : w.config.chart.type;
            const fill = new Fill(this.w);
            this.candlestickOptions = this.w.config.plotOptions.candlestick;
            this.boxOptions = this.w.config.plotOptions.boxPlot;
            this.isHorizontal = w.config.plotOptions.bar.horizontal;
            this.isOHLC = this.candlestickOptions && this.candlestickOptions.type === "ohlc";
            this.coreUtils = new CoreUtils(this.w);
            series = this.coreUtils.getLogSeries(series);
            this.series = series;
            this.yRatio = this.coreUtils.getLogYRatios(this.yRatio);
            this.barHelpers.initVariables(series);
            const ret = graphics.group({
                class: `apexcharts-${type}-series apexcharts-plot-series`
            });
            for (let i = 0; i < series.length; i++) {
                this.isBoxPlot = w.config.chart.type === "boxPlot" || /** @type {Record<string,any>} */
                    w.config.series[i].type === "boxPlot";
                let x;
                let y;
                const yArrj = [];
                const xArrj = [];
                const realIndex = w.globals.comboCharts ? (
                    /** @type {any} */
                    seriesIndex[i]
                ) : i;
                const {
                    columnGroupIndex
                } = this.barHelpers.getGroupIndex(realIndex);
                const elSeries = graphics.group({
                    class: `apexcharts-series`,
                    seriesName: Utils$1.escapeString(w.seriesData.seriesNames[realIndex]),
                    rel: i + 1,
                    "data:realIndex": realIndex
                });
                Series.addCollapsedClassToSeries(this.w, elSeries, realIndex);
                if (series[i].length > 0) {
                    this.visibleI = this.visibleI + 1;
                }
                let translationsIndex = 0;
                if (this.yRatio.length > 1) {
                    this.yaxisIndex = /** @type {any} */
                        w.globals.seriesYAxisReverseMap[realIndex][0];
                    translationsIndex = realIndex;
                }
                const initPositions = this.barHelpers.initialPositions(realIndex);
                const {
                    y: initY,
                    barHeight,
                    yDivision,
                    // yDivision is the GRIDHEIGHT divided by number of datapoints (bars)
                    zeroW,
                    // zeroW is the baseline where 0 meets x axis
                    x: initX,
                    barWidth,
                    xDivision,
                    // xDivision is the GRIDWIDTH divided by number of datapoints (columns)
                    zeroH
                    // zeroH is the baseline where 0 meets y axis
                } = initPositions;
                y = initY;
                x = initX;
                xArrj.push(x + (barWidth != null ? barWidth : 0) / 2);
                const elDataLabelsWrap = graphics.group({
                    class: "apexcharts-datalabels",
                    "data:realIndex": realIndex
                });
                const elGoalsMarkers = graphics.group({
                    class: "apexcharts-bar-goals-markers"
                });
                for (let j = 0; j < w.globals.dataPoints; j++) {
                    const strokeWidth = this.barHelpers.getStrokeWidth(i, j, realIndex);
                    let paths = (
                        /** @type {any} */
                        null
                    );
                    const pathsParams = {
                        indexes: {
                            i,
                            j,
                            realIndex,
                            translationsIndex
                        },
                        x,
                        y,
                        strokeWidth,
                        elSeries
                    };
                    if (this.isHorizontal) {
                        paths = this.drawHorizontalBoxPaths(__spreadProps(__spreadValues({}, pathsParams), {
                            yDivision,
                            barHeight,
                            zeroW
                        }));
                    } else {
                        paths = this.drawVerticalBoxPaths(__spreadProps(__spreadValues({}, pathsParams), {
                            xDivision,
                            barWidth,
                            zeroH
                        }));
                    }
                    y = paths.y;
                    x = paths.x;
                    const barGoalLine = this.barHelpers.drawGoalLine({
                        barXPosition: paths.barXPosition,
                        barYPosition: paths.barYPosition,
                        goalX: paths.goalX,
                        goalY: paths.goalY,
                        barHeight,
                        barWidth
                    });
                    if (barGoalLine) {
                        elGoalsMarkers.add(barGoalLine);
                    }
                    if (j > 0) {
                        xArrj.push(x + (barWidth != null ? barWidth : 0) / 2);
                    }
                    yArrj.push(y);
                    paths.pathTo.forEach(
                        (pathTo, pi) => {
                            const lineFill = !this.isBoxPlot && this.candlestickOptions.wick.useFillColor ? paths.color[pi] : w.globals.stroke.colors[i];
                            const pathFill = fill.fillPath({
                                seriesNumber: realIndex,
                                dataPointIndex: j,
                                color: paths.color[pi],
                                value: series[i][j]
                            });
                            this.renderSeries({
                                realIndex,
                                pathFill,
                                lineFill,
                                j,
                                i,
                                pathFrom: paths.pathFrom,
                                pathTo,
                                strokeWidth,
                                elSeries,
                                x,
                                y,
                                series,
                                columnGroupIndex,
                                barHeight,
                                barWidth,
                                elDataLabelsWrap,
                                elGoalsMarkers,
                                visibleSeries: this.visibleI,
                                type: w.config.chart.type
                            });
                        }
                    );
                }
                w.globals.seriesXvalues[realIndex] = xArrj;
                w.globals.seriesYvalues[realIndex] = yArrj;
                ret.add(elSeries);
            }
            return ret;
        }
        /** @param {{indexes: any, x: any, xDivision: any, barWidth: any, zeroH: any, strokeWidth: any}} opts */
        drawVerticalBoxPaths({
            indexes,
            x,
            xDivision,
            barWidth,
            zeroH,
            strokeWidth
        }) {
            var _a, _b;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const i = indexes.i;
            const j = indexes.j;
            const {
                colors: candleColors
            } = w.config.plotOptions.candlestick;
            const {
                colors: boxColors
            } = this.boxOptions;
            const realIndex = indexes.realIndex;
            const getColor = (color2) => Array.isArray(color2) ? color2[realIndex] : color2;
            const colorPos = getColor(candleColors.upward);
            const colorNeg = getColor(candleColors.downward);
            const yRatio = this.yRatio[indexes.translationsIndex];
            const ohlc = this.getOHLCValue(realIndex, j);
            let l1 = zeroH;
            let l2 = zeroH;
            let color = ohlc.o < ohlc.c ? [colorPos] : [colorNeg];
            if (this.isBoxPlot) {
                color = [getColor(boxColors.lower), getColor(boxColors.upper)];
            }
            let y1 = Math.min(ohlc.o, ohlc.c);
            let y2 = Math.max(ohlc.o, ohlc.c);
            let m = ohlc.m;
            if (w.axisFlags.isXNumeric) {
                x = (w.seriesData.seriesX[realIndex][j] - w.globals.minX) / this.xRatio - barWidth / 2;
            }
            const barXPosition = x + barWidth * this.visibleI;
            if (typeof /** @type {any} */((_a = this.series[i]) == null ? void 0 : _a[j]) === "undefined" || /** @type {any} */
                ((_b = this.series[i]) == null ? void 0 : _b[j]) === null) {
                y1 = zeroH;
                y2 = zeroH;
            } else {
                y1 = zeroH - y1 / yRatio;
                y2 = zeroH - y2 / yRatio;
                l1 = zeroH - ohlc.h / yRatio;
                l2 = zeroH - ohlc.l / yRatio;
                m = zeroH - ohlc.m / yRatio;
            }
            let pathTo;
            if (this.isOHLC) {
                const centerX = barXPosition + barWidth / 2;
                const openY = zeroH - ohlc.o / yRatio;
                const closeY = zeroH - ohlc.c / yRatio;
                pathTo = [
                    graphics.move(centerX, l1) + graphics.line(centerX, l2) + graphics.move(centerX, openY) + graphics.line(barXPosition, openY) + graphics.move(centerX, closeY) + graphics.line(barXPosition + barWidth, closeY)
                ];
            } else if (this.isBoxPlot) {
                pathTo = [
                    graphics.move(barXPosition, y1) + graphics.line(barXPosition + barWidth / 2, y1) + graphics.line(barXPosition + barWidth / 2, l1) + graphics.line(barXPosition + barWidth / 4, l1) + graphics.line(barXPosition + barWidth - barWidth / 4, l1) + graphics.line(barXPosition + barWidth / 2, l1) + graphics.line(barXPosition + barWidth / 2, y1) + graphics.line(barXPosition + barWidth, y1) + graphics.line(barXPosition + barWidth, m) + graphics.line(barXPosition, m) + graphics.line(barXPosition, y1 + strokeWidth / 2),
                    graphics.move(barXPosition, m) + graphics.line(barXPosition + barWidth, m) + graphics.line(barXPosition + barWidth, y2) + graphics.line(barXPosition + barWidth / 2, y2) + graphics.line(barXPosition + barWidth / 2, l2) + graphics.line(barXPosition + barWidth - barWidth / 4, l2) + graphics.line(barXPosition + barWidth / 4, l2) + graphics.line(barXPosition + barWidth / 2, l2) + graphics.line(barXPosition + barWidth / 2, y2) + graphics.line(barXPosition, y2) + graphics.line(barXPosition, m) + "z"
                ];
            } else {
                pathTo = [
                    graphics.move(barXPosition, y2) + graphics.line(barXPosition + barWidth / 2, y2) + graphics.line(barXPosition + barWidth / 2, l1) + graphics.line(barXPosition + barWidth / 2, y2) + graphics.line(barXPosition + barWidth, y2) + graphics.line(barXPosition + barWidth, y1) + graphics.line(barXPosition + barWidth / 2, y1) + graphics.line(barXPosition + barWidth / 2, l2) + graphics.line(barXPosition + barWidth / 2, y1) + graphics.line(barXPosition, y1) + graphics.line(barXPosition, y2 - strokeWidth / 2)
                ];
            }
            let pathFrom;
            if (w.globals.previousPaths.length > 0) {
                pathFrom = this.getPreviousPath(realIndex, j, pathTo[0]);
            } else {
                pathFrom = graphics.move(barXPosition + barWidth / 2, y1) + graphics.move(barXPosition, y1);
            }
            if (!w.axisFlags.isXNumeric) {
                x = x + xDivision;
            }
            return {
                pathTo,
                pathFrom,
                x,
                y: y2,
                goalY: this.barHelpers.getGoalValues(
                    "y",
                    /** @type {any} */
                    null,
                    zeroH,
                    i,
                    j,
                    indexes.translationsIndex
                ),
                barXPosition,
                color
            };
        }
        /** @param {{indexes: any, y: any, yDivision: any, barHeight: any, zeroW: any, strokeWidth: any}} opts */
        drawHorizontalBoxPaths({
            indexes,
            y,
            yDivision,
            barHeight,
            zeroW,
            strokeWidth
        }) {
            var _a, _b;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const i = indexes.i;
            const j = indexes.j;
            const realIndex = indexes.realIndex;
            const {
                colors: candleColors
            } = w.config.plotOptions.candlestick;
            const {
                colors: boxColors
            } = this.boxOptions;
            const getColor = (color2) => Array.isArray(color2) ? color2[realIndex] : color2;
            const yRatio = this.invertedYRatio;
            const ohlc = this.getOHLCValue(realIndex, j);
            let color = ohlc.o < ohlc.c ? [getColor(candleColors.upward)] : [getColor(candleColors.downward)];
            if (this.isBoxPlot) {
                color = [getColor(boxColors.lower), getColor(boxColors.upper)];
            }
            let l1 = zeroW;
            let l2 = zeroW;
            let x1 = Math.min(ohlc.o, ohlc.c);
            let x2 = Math.max(ohlc.o, ohlc.c);
            let m = ohlc.m;
            if (w.axisFlags.isXNumeric) {
                y = (w.seriesData.seriesX[realIndex][j] - w.globals.minX) / this.invertedXRatio - barHeight / 2;
            }
            const barYPosition = y + barHeight * this.visibleI;
            if (typeof /** @type {any} */((_a = this.series[i]) == null ? void 0 : _a[j]) === "undefined" || /** @type {any} */
                ((_b = this.series[i]) == null ? void 0 : _b[j]) === null) {
                x1 = zeroW;
                x2 = zeroW;
            } else {
                x1 = zeroW + x1 / yRatio;
                x2 = zeroW + x2 / yRatio;
                l1 = zeroW + ohlc.h / yRatio;
                l2 = zeroW + ohlc.l / yRatio;
                m = zeroW + ohlc.m / yRatio;
            }
            const pathTo = [
                graphics.move(x1, barYPosition) + graphics.line(x1, barYPosition + barHeight / 2) + graphics.line(l1, barYPosition + barHeight / 2) + graphics.line(l1, barYPosition + barHeight / 2 - barHeight / 4) + graphics.line(l1, barYPosition + barHeight / 2 + barHeight / 4) + graphics.line(l1, barYPosition + barHeight / 2) + graphics.line(x1, barYPosition + barHeight / 2) + graphics.line(x1, barYPosition + barHeight) + graphics.line(m, barYPosition + barHeight) + graphics.line(m, barYPosition) + graphics.line(x1 + strokeWidth / 2, barYPosition),
                graphics.move(m, barYPosition) + graphics.line(m, barYPosition + barHeight) + graphics.line(x2, barYPosition + barHeight) + graphics.line(x2, barYPosition + barHeight / 2) + graphics.line(l2, barYPosition + barHeight / 2) + graphics.line(l2, barYPosition + barHeight - barHeight / 4) + graphics.line(l2, barYPosition + barHeight / 4) + graphics.line(l2, barYPosition + barHeight / 2) + graphics.line(x2, barYPosition + barHeight / 2) + graphics.line(x2, barYPosition) + graphics.line(m, barYPosition) + "z"
            ];
            let pathFrom;
            if (w.globals.previousPaths.length > 0) {
                pathFrom = this.getPreviousPath(realIndex, j, pathTo[0]);
            } else {
                pathFrom = graphics.move(x1, barYPosition + barHeight / 2) + graphics.move(x1, barYPosition);
            }
            if (!w.axisFlags.isXNumeric) {
                y = y + yDivision;
            }
            return {
                pathTo,
                pathFrom,
                x: x2,
                y,
                goalX: this.barHelpers.getGoalValues(
                    "x",
                    zeroW,
                    /** @type {any} */
                    null,
                    i,
                    j,
                    0
                ),
                barYPosition,
                color
            };
        }
        /**
         * @param {number} i
         * @param {number} j
         */
        getOHLCValue(i, j) {
            const w = this.w;
            const coreUtils = this.coreUtils;
            const getCandleVal = (arr) => arr[i] && arr[i][j] != null ? (
                /** @type {any} */
                coreUtils.getLogValAtSeriesIndex(arr[i][j], i)
            ) : 0;
            const h = getCandleVal(w.candleData.seriesCandleH);
            const o = getCandleVal(w.candleData.seriesCandleO);
            const m = getCandleVal(w.candleData.seriesCandleM);
            const c = getCandleVal(w.candleData.seriesCandleC);
            const l = getCandleVal(w.candleData.seriesCandleL);
            return {
                o: this.isBoxPlot ? h : o,
                h: this.isBoxPlot ? o : h,
                m,
                l: this.isBoxPlot ? c : l,
                c: this.isBoxPlot ? l : c
            };
        }
    }
    class TreemapHelpers {
        /**
         * @param {import('../../../types/internal').ChartStateW} w
         * @param {import('../../../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.ctx = ctx;
            this.w = w;
        }
        checkColorRange() {
            const w = this.w;
            let negRange = false;
            const chartOpts = w.config.plotOptions[w.config.chart.type];
            if (chartOpts.colorScale.ranges.length > 0) {
                chartOpts.colorScale.ranges.map((range) => {
                    if (range.from <= 0) {
                        negRange = true;
                    }
                });
            }
            return negRange;
        }
        /**
         * @param {string} chartType
         * @param {number} i
         * @param {number} j
         * @param {any} negRange
         */
        getShadeColor(chartType, i, j, negRange) {
            const w = this.w;
            let colorShadePercent = 1;
            const shadeIntensity = w.config.plotOptions[chartType].shadeIntensity;
            const colorProps = this.determineColor(chartType, i, j);
            if (
                /** @type {any} */
                w.globals.hasNegs || negRange
            ) {
                if (w.config.plotOptions[chartType].reverseNegativeShade) {
                    if (colorProps.percent < 0) {
                        colorShadePercent = colorProps.percent / 100 * (shadeIntensity * 1.25);
                    } else {
                        colorShadePercent = (1 - colorProps.percent / 100) * (shadeIntensity * 1.25);
                    }
                } else {
                    if (colorProps.percent <= 0) {
                        colorShadePercent = 1 - (1 + colorProps.percent / 100) * shadeIntensity;
                    } else {
                        colorShadePercent = (1 - colorProps.percent / 100) * shadeIntensity;
                    }
                }
            } else {
                colorShadePercent = 1 - colorProps.percent / 100;
                if (chartType === "treemap") {
                    colorShadePercent = (1 - colorProps.percent / 100) * (shadeIntensity * 1.25);
                }
            }
            let color = colorProps.color;
            const utils = new Utils$1();
            if (w.config.plotOptions[chartType].enableShades) {
                if (this.w.config.theme.mode === "dark") {
                    const shadeColor = utils.shadeColor(
                        colorShadePercent * -1,
                        colorProps.color
                    );
                    color = Utils$1.hexToRgba(
                        Utils$1.isColorHex(shadeColor) ? shadeColor : Utils$1.rgb2hex(shadeColor),
                        w.config.fill.opacity
                    );
                } else {
                    const shadeColor = utils.shadeColor(colorShadePercent, colorProps.color);
                    color = Utils$1.hexToRgba(
                        Utils$1.isColorHex(shadeColor) ? shadeColor : Utils$1.rgb2hex(shadeColor),
                        w.config.fill.opacity
                    );
                }
            }
            return {
                color,
                colorProps
            };
        }
        /**
         * @param {string} chartType
         * @param {number} i
         * @param {number} j
         */
        determineColor(chartType, i, j) {
            const w = this.w;
            const val = w.seriesData.series[i][j];
            const chartOpts = w.config.plotOptions[chartType];
            let seriesNumber = chartOpts.colorScale.inverse ? j : i;
            if (chartOpts.distributed && w.config.chart.type === "treemap") {
                seriesNumber = j;
            }
            let color = w.globals.colors[seriesNumber];
            let foreColor = null;
            let min = Math.min(...w.seriesData.series[i]);
            let max = Math.max(...w.seriesData.series[i]);
            if (!chartOpts.distributed && chartType === "heatmap") {
                min = w.globals.minY;
                max = w.globals.maxY;
            }
            if (typeof chartOpts.colorScale.min !== "undefined") {
                min = chartOpts.colorScale.min < w.globals.minY ? chartOpts.colorScale.min : w.globals.minY;
                max = chartOpts.colorScale.max > w.globals.maxY ? chartOpts.colorScale.max : w.globals.maxY;
            }
            const total = Math.abs(max) + Math.abs(min);
            let percent = total === 0 ? 0 : 100 * val / total;
            if (chartOpts.colorScale.ranges.length > 0) {
                const colorRange = chartOpts.colorScale.ranges;
                colorRange.map((range) => {
                    if (val >= range.from && val <= range.to) {
                        color = range.color;
                        foreColor = range.foreColor ? range.foreColor : null;
                        min = range.from;
                        max = range.to;
                        const rTotal = Math.abs(max) + Math.abs(min);
                        percent = rTotal === 0 ? 0 : 100 * val / rTotal;
                    }
                });
            }
            return {
                color,
                foreColor,
                percent
            };
        }
        /** @param {{ text?: any, x?: any, y?: any, i?: any, j?: any, colorProps?: any, fontSize?: any, series?: any }} opts */
        calculateDataLabels({
            text,
            x,
            y,
            i,
            j,
            colorProps,
            fontSize
        }) {
            const w = this.w;
            const dataLabelsConfig = w.config.dataLabels;
            const graphics = new Graphics(this.w);
            const dataLabels = new DataLabels(this.w, this.ctx);
            let elDataLabelsWrap = null;
            if (dataLabelsConfig.enabled) {
                elDataLabelsWrap = graphics.group({
                    class: "apexcharts-data-labels"
                });
                const offX = dataLabelsConfig.offsetX;
                const offY = dataLabelsConfig.offsetY;
                const dataLabelsX = x + offX;
                const dataLabelsY = y + parseFloat(dataLabelsConfig.style.fontSize) / 3 + offY;
                dataLabels.plotDataLabelsText({
                    x: dataLabelsX,
                    y: dataLabelsY,
                    text,
                    i,
                    j,
                    color: colorProps.foreColor,
                    parent: elDataLabelsWrap,
                    fontSize,
                    dataLabelsConfig
                });
            }
            return elDataLabelsWrap;
        }
    }
    class HeatMap {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         * @param {import('../types/internal').XYRatios} xyRatios
         */
        constructor(w, ctx, xyRatios) {
            this.ctx = ctx;
            this.w = w;
            this.xRatio = xyRatios.xRatio;
            this.yRatio = xyRatios.yRatio;
            this.dynamicAnim = this.w.config.chart.animations.dynamicAnimation;
            this.helpers = new TreemapHelpers(w, ctx);
            this.rectRadius = this.w.config.plotOptions.heatmap.radius;
            this.strokeWidth = this.w.config.stroke.show ? this.w.config.stroke.width : 0;
        }
        /**
         * @param {any[]} series
         */
        draw(series) {
            const w = this.w;
            const graphics = new Graphics(this.w, this.ctx);
            const ret = graphics.group({
                class: "apexcharts-heatmap"
            });
            ret.attr("clip-path", `url(#gridRectMask${w.globals.cuid})`);
            const xDivision = w.layout.gridWidth / w.globals.dataPoints;
            const yDivision = w.layout.gridHeight / w.seriesData.series.length;
            let y1 = 0;
            let rev = false;
            this.negRange = this.helpers.checkColorRange();
            const heatSeries = series.slice();
            if (w.config.yaxis[0].reversed) {
                rev = true;
                heatSeries.reverse();
            }
            for (let i = rev ? 0 : heatSeries.length - 1; rev ? i < heatSeries.length : i >= 0; rev ? i++ : i--) {
                const elSeries = graphics.group({
                    class: `apexcharts-series apexcharts-heatmap-series`,
                    seriesName: Utils$1.escapeString(w.seriesData.seriesNames[i]),
                    rel: i + 1,
                    "data:realIndex": i
                });
                Series.addCollapsedClassToSeries(this.w, elSeries, i);
                graphics.setupEventDelegation(elSeries, ".apexcharts-heatmap-rect");
                if (w.config.chart.dropShadow.enabled) {
                    const shadow = w.config.chart.dropShadow;
                    const filters = new Filters(this.w);
                    filters.dropShadow(elSeries, shadow, i);
                }
                let x1 = 0;
                const shadeIntensity = w.config.plotOptions.heatmap.shadeIntensity;
                let j = 0;
                for (let dIndex = 0; dIndex < w.globals.dataPoints; dIndex++) {
                    if (w.seriesData.seriesX.length && !w.globals.allSeriesHasEqualX) {
                        if (w.globals.minX + w.globals.minXDiff * dIndex < w.seriesData.seriesX[i][j]) {
                            x1 = x1 + xDivision;
                            continue;
                        }
                    }
                    if (j >= heatSeries[i].length) break;
                    const heatColor = this.helpers.getShadeColor(
                        w.config.chart.type,
                        i,
                        j,
                        this.negRange
                    );
                    let color = heatColor.color;
                    const heatColorProps = heatColor.colorProps;
                    if (w.config.fill.type === "image") {
                        const fill = new Fill(this.w);
                        color = fill.fillPath({
                            seriesNumber: i,
                            dataPointIndex: j,
                            opacity: (
                                /** @type {any} */
                                w.globals.hasNegs ? heatColorProps.percent < 0 ? 1 - (1 + heatColorProps.percent / 100) : shadeIntensity + heatColorProps.percent / 100 : heatColorProps.percent / 100
                            ),
                            patternID: Utils$1.randomId(),
                            width: w.config.fill.image.width ? w.config.fill.image.width : xDivision,
                            height: w.config.fill.image.height ? w.config.fill.image.height : yDivision
                        });
                    }
                    const radius = this.rectRadius;
                    const rect = graphics.drawRect(x1, y1, xDivision, yDivision, radius);
                    rect.attr({
                        cx: x1,
                        cy: y1
                    });
                    rect.node.classList.add("apexcharts-heatmap-rect");
                    elSeries.add(rect);
                    rect.attr({
                        fill: color,
                        i,
                        index: i,
                        j,
                        val: series[i][j],
                        "stroke-width": this.strokeWidth,
                        stroke: w.config.plotOptions.heatmap.useFillColorAsStroke ? color : w.globals.stroke.colors[0],
                        color
                    });
                    if (w.config.chart.animations.enabled && !w.globals.dataChanged) {
                        let speed = 1;
                        if (!w.globals.resized) {
                            speed = w.config.chart.animations.speed;
                        }
                        this.animateHeatMap(rect, x1, y1, xDivision, yDivision, speed, i, j);
                    }
                    if (w.globals.dataChanged) {
                        let speed = 1;
                        if (this.dynamicAnim.enabled && w.globals.shouldAnimate) {
                            speed = this.dynamicAnim.speed;
                            let colorFrom = w.globals.previousPaths[i] && w.globals.previousPaths[i][j] && w.globals.previousPaths[i][j].color;
                            if (!colorFrom) colorFrom = "rgba(255, 255, 255, 0)";
                            this.animateHeatColor(
                                rect,
                                Utils$1.isColorHex(colorFrom) ? colorFrom : Utils$1.rgb2hex(colorFrom),
                                Utils$1.isColorHex(color) ? color : Utils$1.rgb2hex(color),
                                speed
                            );
                        }
                    }
                    const formatter = w.config.dataLabels.formatter;
                    const formattedText = formatter(w.seriesData.series[i][j], {
                        value: w.seriesData.series[i][j],
                        seriesIndex: i,
                        dataPointIndex: j,
                        w
                    });
                    const dataLabels = this.helpers.calculateDataLabels({
                        text: formattedText,
                        x: x1 + xDivision / 2,
                        y: y1 + yDivision / 2,
                        i,
                        j,
                        colorProps: heatColorProps,
                        series: heatSeries
                    });
                    if (dataLabels !== null) {
                        elSeries.add(dataLabels);
                    }
                    x1 = x1 + xDivision;
                    j++;
                }
                y1 = y1 + yDivision;
                ret.add(elSeries);
            }
            const yAxisScale = (
                /** @type {any[]} */
                w.globals.yAxisScale[0].result.slice()
            );
            if (w.config.yaxis[0].reversed) {
                yAxisScale.unshift("");
            } else {
                yAxisScale.push("");
            }
            w.globals.yAxisScale[0].result = yAxisScale;
            return ret;
        }
        /**
         * @param {any} el
         * @param {number} x
         * @param {number} y
         * @param {number} width
         * @param {number} height
         * @param {number} speed
         * @param {number} [row] - series index (heatmap row)
         * @param {number} [col] - data point index (heatmap column)
         */
        animateHeatMap(el, x, y, width, height, speed, row = 0, col = 0) {
            const w = this.w;
            const animations = new Animations(this.w);
            const animCfg = w.config.chart.animations;
            const gradCfg = animCfg.animateGradually;
            const staggerEnabled = gradCfg && gradCfg.enabled !== false;
            let delay = 0;
            if (staggerEnabled) {
                const seriesCount = (w.seriesData.series || []).length || 1;
                const pointsCount = w.globals.dataPoints || 1;
                const maxDiag = seriesCount + pointsCount - 2;
                const baseDelay = Math.min(
                    gradCfg.delay || 0,
                    speed * 0.5 / Math.max(1, maxDiag)
                );
                delay = computeStagger({
                    style: "diagonal",
                    index: col,
                    row,
                    col,
                    baseDelay
                });
            }
            animations.animateRect(
                el, {
                    x: x + width / 2,
                    y: y + height / 2,
                    width: 0,
                    height: 0
                }, {
                    x,
                    y,
                    width,
                    height
                },
                speed,
                () => {
                    animations.animationCompleted(el);
                },
                delay
            );
        }
        /**
         * @param {any} el
         * @param {string} colorFrom
         * @param {string} colorTo
         * @param {number} speed
         */
        animateHeatColor(el, colorFrom, colorTo, speed) {
            el.attr({
                fill: colorFrom
            }).animate(speed).attr({
                fill: colorTo
            });
        }
    }
    class Helpers {
        /**
         * @param {import('../../../charts/Line').default} lineCtx
         */
        constructor(lineCtx) {
            this.w = lineCtx.w;
            this.lineCtx = lineCtx;
        }
        /**
         * @param {number} i
         * @param {any[]} series
         */
        sameValueSeriesFix(i, series) {
            const w = this.w;
            if (w.config.fill.type === "gradient" || w.config.fill.type[i] === "gradient") {
                const coreUtils = new CoreUtils(this.lineCtx.w);
                if (coreUtils.seriesHaveSameValues(i)) {
                    const gSeries = series[i].slice();
                    gSeries[gSeries.length - 1] = gSeries[gSeries.length - 1] + 1e-6;
                    series[i] = gSeries;
                }
            }
            return series;
        }
        /** @param {{series: any, realIndex: any, x: any, y: any, i: any, j: any, prevY: any}} opts */
        calculatePoints({
            series,
            realIndex,
            x,
            y,
            i,
            j,
            prevY
        }) {
            const w = this.w;
            const ptX = [];
            const ptY = [];
            let xPT1st = this.lineCtx.categoryAxisCorrection + w.config.markers.offsetX;
            if (w.axisFlags.isXNumeric) {
                xPT1st = (w.seriesData.seriesX[realIndex][0] - w.globals.minX) / this.lineCtx.xRatio + w.config.markers.offsetX;
            }
            if (j === 0) {
                ptX.push(xPT1st);
                ptY.push(
                    Utils$1.isNumber(series[i][0]) ? prevY + w.config.markers.offsetY : null
                );
            }
            ptX.push(x + w.config.markers.offsetX);
            ptY.push(
                Utils$1.isNumber(series[i][j + 1]) ? y + w.config.markers.offsetY : null
            );
            return {
                x: ptX,
                y: ptY
            };
        }
        /** @param {{pathFromLine: any, pathFromArea: any, realIndex: any}} opts */
        checkPreviousPaths({
            pathFromLine,
            pathFromArea,
            realIndex
        }) {
            const w = this.w;
            for (let pp = 0; pp < w.globals.previousPaths.length; pp++) {
                const gpp = w.globals.previousPaths[pp];
                if ((gpp.type === "line" || gpp.type === "area") && gpp.paths.length > 0 && parseInt(gpp.realIndex, 10) === parseInt(realIndex, 10)) {
                    if (gpp.type === "line") {
                        this.lineCtx.appendPathFrom = false;
                        pathFromLine = w.globals.previousPaths[pp].paths[0].d;
                    } else if (gpp.type === "area") {
                        this.lineCtx.appendPathFrom = false;
                        pathFromArea = w.globals.previousPaths[pp].paths[0].d;
                        if (w.config.stroke.show && w.globals.previousPaths[pp].paths[1]) {
                            pathFromLine = w.globals.previousPaths[pp].paths[1].d;
                        }
                    }
                }
            }
            return {
                pathFromLine,
                pathFromArea
            };
        }
        /** @param {{i: any, realIndex: any, series: any, prevY: any, lineYPosition: any, translationsIndex: any}} opts */
        determineFirstPrevY({
            i,
            realIndex,
            series,
            prevY,
            lineYPosition,
            translationsIndex
        }) {
            var _a, _b, _c;
            const w = this.w;
            const stackSeries = w.config.chart.stacked && !w.globals.comboCharts || w.config.chart.stacked && w.globals.comboCharts && (!this.w.config.chart.stackOnlyBar || /** @type {any} */
                ((_a = this.w.config.series[realIndex]) == null ? void 0 : _a.type) === "bar" || /** @type {any} */
                ((_b = this.w.config.series[realIndex]) == null ? void 0 : _b.type) === "column");
            if (typeof((_c = series[i]) == null ? void 0 : _c[0]) !== "undefined") {
                if (stackSeries) {
                    if (i > 0) {
                        lineYPosition = this.lineCtx.prevSeriesY[i - 1][0];
                    } else {
                        lineYPosition = this.lineCtx.zeroY;
                    }
                } else {
                    lineYPosition = this.lineCtx.zeroY;
                }
                prevY = lineYPosition - series[i][0] / this.lineCtx.yRatio[translationsIndex] + (this.lineCtx.isReversed ? series[i][0] / this.lineCtx.yRatio[translationsIndex] : 0) * 2;
            } else {
                if (stackSeries && i > 0 && typeof series[i][0] === "undefined") {
                    for (let s = i - 1; s >= 0; s--) {
                        if (series[s][0] !== null && typeof series[s][0] !== "undefined") {
                            lineYPosition = this.lineCtx.prevSeriesY[s][0];
                            prevY = lineYPosition;
                            break;
                        }
                    }
                }
            }
            return {
                prevY,
                lineYPosition
            };
        }
    }
    const tangents = (points) => {
        const m = finiteDifferences(points);
        const n = points.length - 1;
        const ε = 1e-6;
        const tgts = [];
        let a, b, d, s;
        for (let i = 0; i < n; i++) {
            d = slope(points[i], points[i + 1]);
            if (Math.abs(d) < ε) {
                m[i] = m[i + 1] = 0;
            } else {
                a = m[i] / d;
                b = m[i + 1] / d;
                s = a * a + b * b;
                if (s > 9) {
                    s = d * 3 / Math.sqrt(s);
                    m[i] = s * a;
                    m[i + 1] = s * b;
                }
            }
        }
        for (let i = 0; i <= n; i++) {
            s = (points[Math.min(n, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
            tgts.push([s || 0, m[i] * s || 0]);
        }
        return tgts;
    };
    const svgPath = (points) => {
        let p = "";
        for (let i = 0; i < points.length; i++) {
            const point = points[i];
            const n = point.length;
            if (n > 4) {
                p += `C${point[0]}, ${point[1]}`;
                p += `, ${point[2]}, ${point[3]}`;
                p += `, ${point[4]}, ${point[5]}`;
            } else if (n > 2) {
                p += `S${point[0]}, ${point[1]}`;
                p += `, ${point[2]}, ${point[3]}`;
            }
        }
        return p;
    };
    const spline = {
        /**
         * Convert 'points' to bezier
         * @param {any[]} points
         * @returns {any[]}
         */
        points(points) {
            const tgts = tangents(points);
            const p = points[1];
            const p0 = points[0];
            const pts = [];
            const t = tgts[1];
            const t0 = tgts[0];
            pts.push(p0, [
                p0[0] + t0[0],
                p0[1] + t0[1],
                p[0] - t[0],
                p[1] - t[1],
                p[0],
                p[1]
            ]);
            for (let i = 2, n = tgts.length; i < n; i++) {
                const p2 = points[i];
                const t2 = tgts[i];
                pts.push([p2[0] - t2[0], p2[1] - t2[1], p2[0], p2[1]]);
            }
            return pts;
        },
        /**
         * Slice out a segment of 'points'
         * @param {any[]} points
         * @param {Number} start
         * @param {Number} end
         * @returns {any[]}
         */
        slice(points, start, end) {
            const pts = points.slice(start, end);
            if (start) {
                if (end - start > 1 && pts[1].length < 6) {
                    const n = pts[0].length;
                    pts[1] = [
                        pts[0][n - 2] * 2 - pts[0][n - 4],
                        pts[0][n - 1] * 2 - pts[0][n - 3]
                    ].concat(pts[1]);
                }
                pts[0] = pts[0].slice(-2);
            }
            return pts;
        }
    };

    function slope(p0, p1) {
        return (p1[1] - p0[1]) / (p1[0] - p0[0]);
    }

    function finiteDifferences(points) {
        const m = [];
        let p0 = points[0];
        let p1 = points[1];
        let d = m[0] = slope(p0, p1);
        let i = 1;
        for (let n = points.length - 1; i < n; i++) {
            p0 = p1;
            p1 = points[i + 1];
            m[i] = (d + (d = slope(p0, p1))) * 0.5;
        }
        m[i] = d;
        return m;
    }
    class Line {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         * @param {import('../types/internal').XYRatios} xyRatios
         * @param {boolean} isPointsChart
         */
        constructor(w, ctx, xyRatios, isPointsChart) {
            this.ctx = ctx;
            this.w = w;
            this.xyRatios = xyRatios;
            this.xRatio = 0;
            this.yRatio = [];
            this.zRatio = 0;
            this.baseLineY = [];
            this.pointsChart = !(this.w.config.chart.type !== "bubble" && this.w.config.chart.type !== "scatter") || isPointsChart;
            this.scatter = new Scatter(this.w, this.ctx);
            this.noNegatives = this.w.globals.minX === Number.MAX_VALUE;
            this.lineHelpers = new Helpers(this);
            this.markers = new Markers(this.w, this.ctx);
            this.prevSeriesY = [];
            this.categoryAxisCorrection = 0;
            this.yaxisIndex = 0;
            this.xDivision = 0;
            this.zeroY = 0;
            this.areaBottomY = 0;
            this.strokeWidth = 0;
            this.isReversed = false;
            this.appendPathFrom = false;
            this.elSeries = null;
            this.elPointsMain = null;
            this.elDataLabelsWrap = null;
        }
        /**
         * @param {any[]} series
         * @param {string} ctype
         * @param {number} seriesIndex
         * @param {any} seriesRangeEnd
         */
        draw(series, ctype, seriesIndex, seriesRangeEnd) {
            var _a;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const type = w.globals.comboCharts ? ctype : w.config.chart.type;
            const ret = graphics.group({
                class: `apexcharts-${type}-series apexcharts-plot-series`
            });
            const coreUtils = new CoreUtils(this.w);
            this.yRatio = this.xyRatios.yRatio;
            this.zRatio = this.xyRatios.zRatio;
            this.xRatio = this.xyRatios.xRatio;
            this.baseLineY = this.xyRatios.baseLineY;
            series = coreUtils.getLogSeries(series);
            this.yRatio = coreUtils.getLogYRatios(this.yRatio);
            this.prevSeriesY = [];
            const allSeries = [];
            for (let i = 0; i < series.length; i++) {
                series = this.lineHelpers.sameValueSeriesFix(i, series);
                const realIndex = w.globals.comboCharts ? (
                    /** @type {any} */
                    seriesIndex[i]
                ) : i;
                const translationsIndex = this.yRatio.length > 1 ? realIndex : 0;
                this._initSerieVariables(series, i, realIndex);
                const yArrj = [];
                const y2Arrj = [];
                const xArrj = [];
                let x = w.globals.padHorizontal + this.categoryAxisCorrection;
                const y = 1;
                const linePaths = [];
                const areaPaths = [];
                Series.addCollapsedClassToSeries(this.w, this.elSeries, realIndex);
                if (w.axisFlags.isXNumeric && w.seriesData.seriesX.length > 0) {
                    x = (w.seriesData.seriesX[realIndex][0] - w.globals.minX) / this.xRatio;
                }
                xArrj.push(x);
                const pX = x;
                let pY2;
                const prevX = pX;
                let prevY = this.zeroY;
                let prevY2 = this.zeroY;
                const lineYPosition = 0;
                const firstPrevY = this.lineHelpers.determineFirstPrevY({
                    i,
                    realIndex,
                    series,
                    prevY,
                    lineYPosition,
                    translationsIndex
                });
                prevY = firstPrevY.prevY;
                if (w.config.stroke.curve === "monotoneCubic" && series[i][0] === null) {
                    yArrj.push(null);
                } else {
                    yArrj.push(prevY);
                }
                const pY = prevY;
                let firstPrevY2;
                if (type === "rangeArea") {
                    firstPrevY2 = this.lineHelpers.determineFirstPrevY({
                        i,
                        realIndex,
                        series: seriesRangeEnd,
                        prevY: prevY2,
                        lineYPosition,
                        translationsIndex
                    });
                    prevY2 = firstPrevY2.prevY;
                    pY2 = prevY2;
                    y2Arrj.push(yArrj[0] !== null ? prevY2 : null);
                }
                const pathsFrom = this._calculatePathsFrom({
                    type,
                    series,
                    i,
                    realIndex,
                    translationsIndex,
                    prevX,
                    prevY,
                    prevY2
                });
                const rYArrj = [yArrj[0]];
                const rY2Arrj = [y2Arrj[0]];
                const iteratingOpts = {
                    type,
                    series,
                    realIndex,
                    translationsIndex,
                    i,
                    x,
                    y,
                    pX,
                    pY,
                    pathsFrom,
                    linePaths,
                    areaPaths,
                    seriesIndex,
                    lineYPosition,
                    xArrj,
                    yArrj,
                    y2Arrj,
                    seriesRangeEnd
                };
                const paths = this._iterateOverDataPoints(__spreadProps(__spreadValues({}, iteratingOpts), {
                    iterations: type === "rangeArea" ? series[i].length - 1 : void 0,
                    isRangeStart: true
                }));
                if (type === "rangeArea") {
                    const pathsFrom2 = this._calculatePathsFrom({
                        series: seriesRangeEnd,
                        i,
                        realIndex,
                        prevX,
                        prevY: prevY2
                    });
                    const rangePaths = this._iterateOverDataPoints(__spreadProps(__spreadValues({}, iteratingOpts), {
                        series: seriesRangeEnd,
                        xArrj: [x],
                        yArrj: rYArrj,
                        y2Arrj: rY2Arrj,
                        pY: pY2,
                        areaPaths: paths.areaPaths,
                        pathsFrom: pathsFrom2,
                        iterations: seriesRangeEnd[i].length - 1,
                        isRangeStart: false
                    }));
                    const segments = paths.linePaths.length / 2;
                    for (let s = 0; s < segments; s++) {
                        paths.linePaths[s] = rangePaths.linePaths[s + segments] + paths.linePaths[s];
                    }
                    paths.linePaths.splice(segments);
                    paths.pathFromLine = rangePaths.pathFromLine + paths.pathFromLine;
                } else {
                    paths.pathFromArea += "z";
                }
                this._handlePaths({
                    type,
                    realIndex,
                    i,
                    paths
                });
                this.elSeries.add(this.elPointsMain);
                this.elSeries.add(this.elDataLabelsWrap);
                allSeries.push(this.elSeries);
            }
            if (typeof /** @type {Record<string,any>} */((_a = w.config.series[0]) == null ? void 0 : _a.zIndex) !== "undefined") {
                allSeries.sort(
                    (a, b) => Number(a.node.getAttribute("zIndex")) - Number(b.node.getAttribute("zIndex"))
                );
            }
            if (w.config.chart.stacked) {
                for (let s = allSeries.length - 1; s >= 0; s--) {
                    ret.add(allSeries[s]);
                }
            } else {
                for (let s = 0; s < allSeries.length; s++) {
                    ret.add(allSeries[s]);
                }
            }
            return ret;
        }
        /**
         * @param {any[]} series
         * @param {number} i
         * @param {number} realIndex
         */
        _initSerieVariables(series, i, realIndex) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            this.xDivision = w.layout.gridWidth / (w.globals.dataPoints - (w.config.xaxis.tickPlacement === "on" ? 1 : 0));
            this.strokeWidth = Array.isArray(w.config.stroke.width) ? w.config.stroke.width[realIndex] : w.config.stroke.width;
            let translationsIndex = 0;
            if (this.yRatio.length > 1) {
                this.yaxisIndex = w.globals.seriesYAxisReverseMap[realIndex];
                translationsIndex = realIndex;
            }
            this.isReversed = w.config.yaxis[this.yaxisIndex] && w.config.yaxis[this.yaxisIndex].reversed;
            this.zeroY = w.layout.gridHeight - this.baseLineY[translationsIndex] - (this.isReversed ? w.layout.gridHeight : 0) + (this.isReversed ? this.baseLineY[translationsIndex] * 2 : 0);
            this.areaBottomY = this.zeroY;
            if (this.zeroY > w.layout.gridHeight || w.config.plotOptions.area.fillTo === "end") {
                this.areaBottomY = w.layout.gridHeight;
            }
            this.categoryAxisCorrection = this.xDivision / 2;
            const seriesItem = (
                /** @type {Record<string,any>} */
                w.config.series[realIndex]
            );
            this.elSeries = graphics.group({
                class: `apexcharts-series`,
                zIndex: typeof seriesItem.zIndex !== "undefined" ? seriesItem.zIndex : realIndex,
                seriesName: Utils$1.escapeString(w.seriesData.seriesNames[realIndex])
            });
            this.elPointsMain = graphics.group({
                class: "apexcharts-series-markers-wrap",
                "data:realIndex": realIndex
            });
            if (w.globals.hasNullValues) {
                const firstPoint = this.markers.plotChartMarkers({
                    pointsPos: {
                        x: [0],
                        y: [w.layout.gridHeight + w.globals.markers.largestSize]
                    },
                    seriesIndex: i,
                    j: 0,
                    pSize: 0.1,
                    alwaysDrawMarker: true,
                    isVirtualPoint: true
                });
                if (firstPoint !== null) {
                    this.elPointsMain.add(firstPoint);
                }
            }
            this.elDataLabelsWrap = graphics.group({
                class: "apexcharts-datalabels",
                "data:realIndex": realIndex
            });
            const longestSeries = series[i].length === w.globals.dataPoints;
            this.elSeries.attr({
                "data:longestSeries": longestSeries,
                rel: i + 1,
                "data:realIndex": realIndex
            });
            this.appendPathFrom = true;
        }
        /** @param {{ type?: any, series?: any, i?: any, realIndex?: any, translationsIndex?: any, prevX?: any, prevY?: any, prevY2?: any }} opts */
        _calculatePathsFrom({
            type,
            series,
            i,
            realIndex,
            translationsIndex,
            prevX,
            prevY,
            prevY2
        }) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            let linePath, areaPath, pathFromLine, pathFromArea;
            if (series[i][0] === null) {
                for (let s = 0; s < series[i].length; s++) {
                    if (series[i][s] !== null) {
                        prevX = this.xDivision * s;
                        prevY = this.zeroY - series[i][s] / this.yRatio[translationsIndex];
                        linePath = graphics.move(prevX, prevY);
                        areaPath = graphics.move(prevX, this.areaBottomY);
                        break;
                    }
                }
            } else {
                linePath = graphics.move(prevX, prevY);
                if (type === "rangeArea") {
                    linePath = graphics.move(prevX, prevY2) + graphics.line(prevX, prevY);
                }
                areaPath = graphics.move(prevX, this.areaBottomY) + graphics.line(prevX, prevY);
            }
            pathFromLine = graphics.move(0, this.areaBottomY) + graphics.line(0, this.areaBottomY);
            pathFromArea = graphics.move(0, this.areaBottomY) + graphics.line(0, this.areaBottomY);
            if (w.globals.previousPaths.length > 0) {
                const pathFrom = this.lineHelpers.checkPreviousPaths({
                    pathFromLine,
                    pathFromArea,
                    realIndex
                });
                pathFromLine = pathFrom.pathFromLine;
                pathFromArea = pathFrom.pathFromArea;
            }
            return {
                prevX,
                prevY,
                linePath,
                areaPath,
                pathFromLine,
                pathFromArea
            };
        }
        /** @param {{type: any, realIndex: any, i: any, paths: any}} opts */
        _handlePaths({
            type,
            realIndex,
            i,
            paths
        }) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const fill = new Fill(this.w);
            this.prevSeriesY.push(paths.yArrj);
            w.globals.seriesXvalues[realIndex] = paths.xArrj;
            w.globals.seriesYvalues[realIndex] = paths.yArrj;
            const forecast = w.config.forecastDataPoints;
            if (forecast.count > 0 && type !== "rangeArea") {
                const forecastCutoff = w.globals.seriesXvalues[realIndex][w.globals.seriesXvalues[realIndex].length - forecast.count - 1];
                const elForecastMask = graphics.drawRect(
                    forecastCutoff,
                    0,
                    w.layout.gridWidth,
                    w.layout.gridHeight,
                    0
                );
                w.dom.elForecastMask.appendChild(elForecastMask.node);
                const elNonForecastMask = graphics.drawRect(
                    0,
                    0,
                    forecastCutoff,
                    w.layout.gridHeight,
                    0
                );
                w.dom.elNonForecastMask.appendChild(elNonForecastMask.node);
            }
            if (!this.pointsChart) {
                w.globals.delayedElements.push({
                    el: this.elPointsMain.node,
                    index: realIndex
                });
            }
            const defaultRenderedPathOptions = {
                i,
                realIndex,
                animationDelay: i,
                initialSpeed: w.config.chart.animations.speed,
                dataChangeSpeed: w.config.chart.animations.dynamicAnimation.speed,
                className: `apexcharts-${type}`
            };
            if (type === "area") {
                const pathFill = fill.fillPath({
                    seriesNumber: realIndex
                });
                for (let p = 0; p < paths.areaPaths.length; p++) {
                    const renderedPath = graphics.renderPaths(__spreadProps(__spreadValues({}, defaultRenderedPathOptions), {
                        pathFrom: paths.pathFromArea,
                        pathTo: paths.areaPaths[p],
                        stroke: "none",
                        strokeWidth: 0,
                        strokeLineCap: null,
                        fill: pathFill
                    }));
                    this.elSeries.add(renderedPath);
                }
            }
            if (w.config.stroke.show && !this.pointsChart) {
                let lineFill = null;
                if (type === "line") {
                    lineFill = fill.fillPath({
                        seriesNumber: realIndex,
                        i
                    });
                } else {
                    if (w.config.stroke.fill.type === "solid") {
                        lineFill = w.globals.stroke.colors[realIndex];
                    } else {
                        const prevFill = w.config.fill;
                        w.config.fill = w.config.stroke.fill;
                        lineFill = fill.fillPath({
                            seriesNumber: realIndex,
                            i
                        });
                        w.config.fill = prevFill;
                    }
                }
                for (let p = 0; p < paths.linePaths.length; p++) {
                    let pathFill = lineFill;
                    if (type === "rangeArea") {
                        pathFill = fill.fillPath({
                            seriesNumber: realIndex
                        });
                    }
                    const linePathCommonOpts = __spreadProps(__spreadValues({}, defaultRenderedPathOptions), {
                        pathFrom: paths.pathFromLine,
                        pathTo: paths.linePaths[p],
                        stroke: lineFill,
                        strokeWidth: this.strokeWidth,
                        strokeLineCap: w.config.stroke.lineCap,
                        fill: type === "rangeArea" ? pathFill : "none"
                    });
                    const renderedPath = graphics.renderPaths(linePathCommonOpts);
                    this.elSeries.add(renderedPath);
                    renderedPath.attr("fill-rule", `evenodd`);
                    if (forecast.count > 0 && type !== "rangeArea") {
                        const renderedForecastPath = graphics.renderPaths(linePathCommonOpts);
                        renderedForecastPath.node.setAttribute(
                            "stroke-dasharray",
                            forecast.dashArray
                        );
                        if (forecast.strokeWidth) {
                            renderedForecastPath.node.setAttribute(
                                "stroke-width",
                                forecast.strokeWidth
                            );
                        }
                        this.elSeries.add(renderedForecastPath);
                        renderedForecastPath.attr(
                            "clip-path",
                            `url(#forecastMask${w.globals.cuid})`
                        );
                        renderedPath.attr(
                            "clip-path",
                            `url(#nonForecastMask${w.globals.cuid})`
                        );
                    }
                }
            }
        }
        _iterateOverDataPoints({
            type,
            series,
            iterations,
            realIndex,
            translationsIndex,
            i,
            x,
            y,
            pX,
            pY,
            pathsFrom,
            linePaths,
            areaPaths,
            seriesIndex,
            lineYPosition,
            xArrj,
            yArrj,
            y2Arrj,
            isRangeStart,
            seriesRangeEnd
        }) {
            var _a, _b;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const yRatio = this.yRatio;
            let {
                prevY,
                linePath,
                areaPath,
                pathFromLine,
                pathFromArea
            } = pathsFrom;
            const minY = Utils$1.isNumber(w.globals.minYArr[realIndex]) ? w.globals.minYArr[realIndex] : w.globals.minY;
            if (!iterations) {
                iterations = w.globals.dataPoints > 1 ? w.globals.dataPoints - 1 : w.globals.dataPoints;
            }
            const getY = (_y, lineYPos) => {
                return lineYPos - _y / yRatio[translationsIndex] + (this.isReversed ? _y / yRatio[translationsIndex] : 0) * 2;
            };
            let y2 = y;
            const stackSeries = w.config.chart.stacked && !w.globals.comboCharts || w.config.chart.stacked && w.globals.comboCharts && (!this.w.config.chart.stackOnlyBar || /** @type {Record<string,any>} */
                ((_a = this.w.config.series[realIndex]) == null ? void 0 : _a.type) === "bar" || /** @type {Record<string,any>} */
                ((_b = this.w.config.series[realIndex]) == null ? void 0 : _b.type) === "column");
            let curve = w.config.stroke.curve;
            if (Array.isArray(curve)) {
                if (Array.isArray(seriesIndex)) {
                    curve = curve[seriesIndex[i]];
                } else {
                    curve = curve[i];
                }
            }
            let pathState = 0;
            let segmentStartX;
            for (let j = 0; j < iterations; j++) {
                if (series[i].length === 0) break;
                const isNull = typeof series[i][j + 1] === "undefined" || series[i][j + 1] === null;
                if (w.axisFlags.isXNumeric) {
                    let sX = w.seriesData.seriesX[realIndex][j + 1];
                    if (typeof w.seriesData.seriesX[realIndex][j + 1] === "undefined") {
                        sX = w.seriesData.seriesX[realIndex][iterations - 1];
                    }
                    x = (sX - w.globals.minX) / this.xRatio;
                } else {
                    x = x + this.xDivision;
                }
                if (stackSeries) {
                    if (i > 0 && w.globals.collapsedSeries.length < w.config.series.length - 1) {
                        const prevIndex = (pi) => {
                            for (let pii = pi; pii > 0; pii--) {
                                if (w.globals.collapsedSeriesIndices.indexOf(
                                        (seriesIndex == null ? void 0 : seriesIndex[pii]) || pii
                                    ) > -1) {
                                    pii--;
                                } else {
                                    return pii;
                                }
                            }
                            return 0;
                        };
                        lineYPosition = this.prevSeriesY[prevIndex(i - 1)][j + 1];
                    } else {
                        lineYPosition = this.zeroY;
                    }
                } else {
                    lineYPosition = this.zeroY;
                }
                if (isNull) {
                    y = getY(minY, lineYPosition);
                } else {
                    y = getY(series[i][j + 1], lineYPosition);
                    if (type === "rangeArea") {
                        y2 = getY(seriesRangeEnd[i][j + 1], lineYPosition);
                    }
                }
                xArrj.push(series[i][j + 1] === null ? null : x);
                if (isNull && (w.config.stroke.curve === "smooth" || w.config.stroke.curve === "monotoneCubic")) {
                    yArrj.push(null);
                    y2Arrj.push(null);
                } else {
                    yArrj.push(y);
                    y2Arrj.push(y2);
                }
                const pointsPos = this.lineHelpers.calculatePoints({
                    series,
                    x,
                    y,
                    realIndex,
                    i,
                    j,
                    prevY
                });
                const calculatedPaths = this._createPaths({
                    type,
                    series,
                    i,
                    j,
                    x,
                    y,
                    y2,
                    xArrj,
                    yArrj,
                    y2Arrj,
                    pX,
                    pY,
                    pathState,
                    segmentStartX,
                    linePath,
                    areaPath,
                    linePaths,
                    areaPaths,
                    curve,
                    isRangeStart
                });
                areaPaths = calculatedPaths.areaPaths;
                linePaths = calculatedPaths.linePaths;
                pX = calculatedPaths.pX;
                pY = calculatedPaths.pY;
                pathState = calculatedPaths.pathState;
                segmentStartX = calculatedPaths.segmentStartX;
                areaPath = calculatedPaths.areaPath;
                linePath = calculatedPaths.linePath;
                if (this.appendPathFrom && !w.globals.hasNullValues && !(curve === "monotoneCubic" && type === "rangeArea")) {
                    pathFromLine += graphics.line(x, this.areaBottomY);
                    pathFromArea += graphics.line(x, this.areaBottomY);
                }
                this.handleNullDataPoints(series, pointsPos, i, j, realIndex);
                this._handleMarkersAndLabels({
                    type,
                    pointsPos,
                    i,
                    j,
                    realIndex,
                    isRangeStart
                });
            }
            return {
                yArrj,
                xArrj,
                pathFromArea,
                areaPaths,
                pathFromLine,
                linePaths,
                linePath,
                areaPath
            };
        }
        /** @param {{type: any, pointsPos: any, isRangeStart: any, i: any, j: any, realIndex: any}} opts */
        _handleMarkersAndLabels({
            type,
            pointsPos,
            isRangeStart,
            i,
            j,
            realIndex
        }) {
            const w = this.w;
            const dataLabels = new DataLabels(this.w, this.ctx);
            if (!this.pointsChart) {
                const useProgressive = !w.globals.dataChanged && !w.globals.resized;
                if (!useProgressive && w.seriesData.series[i].length > 1) {
                    this.elPointsMain.node.classList.add("apexcharts-element-hidden");
                }
                const elPointsWrap = this.markers.plotChartMarkers({
                    pointsPos,
                    seriesIndex: realIndex,
                    j: j + 1
                });
                if (elPointsWrap !== null) {
                    this.elPointsMain.add(elPointsWrap);
                }
            } else {
                this.scatter.draw(this.elSeries, j, {
                    realIndex,
                    pointsPos,
                    zRatio: this.zRatio,
                    elParent: this.elPointsMain
                });
            }
            const drawnLabels = dataLabels.drawDataLabel({
                type,
                isRangeStart,
                pos: pointsPos,
                i: realIndex,
                j: j + 1
            });
            if (drawnLabels !== null) {
                this.elDataLabelsWrap.add(drawnLabels);
            }
        }
        /** @param {{type: any, series: any, i: any, j: any, x: any, y: any, xArrj: any, yArrj: any, y2: any, y2Arrj: any, pX: any, pY: any, pathState: any, segmentStartX: any, linePath: any, areaPath: any, linePaths: any, areaPaths: any, curve: any, isRangeStart: any}} opts */
        _createPaths({
            type,
            series,
            i,
            j,
            x,
            y,
            xArrj,
            yArrj,
            y2,
            y2Arrj,
            pX,
            pY,
            pathState,
            segmentStartX,
            linePath,
            areaPath,
            linePaths,
            areaPaths,
            curve,
            isRangeStart
        }) {
            const graphics = new Graphics(this.w);
            const areaBottomY = this.areaBottomY;
            const rangeArea = type === "rangeArea";
            const isLowerRangeAreaPath = type === "rangeArea" && isRangeStart;
            switch (curve) {
                case "monotoneCubic": {
                    const yAj = isRangeStart ? yArrj : y2Arrj;
                    const getSmoothInputs = (xArr, yArr) => {
                        return xArr.map((_, i2) => {
                            return [_, yArr[i2]];
                        }).filter((_) => _[1] !== null);
                    };
                    const getSegmentLengths = (yArr) => {
                        const segLens = [];
                        let count = 0;
                        yArr.forEach((_) => {
                            if (_ !== null) {
                                count++;
                            } else if (count > 0) {
                                segLens.push(count);
                                count = 0;
                            }
                        });
                        if (count > 0) {
                            segLens.push(count);
                        }
                        return segLens;
                    };
                    const getSegments = (yArr, points) => {
                        const segLens = getSegmentLengths(yArr);
                        const segments = [];
                        for (let i2 = 0, len = 0; i2 < segLens.length; len += segLens[i2++]) {
                            segments[i2] = spline.slice(points, len, len + segLens[i2]);
                        }
                        return segments;
                    };
                    switch (pathState) {
                        case 0:
                            if (yAj[j + 1] === null) {
                                break;
                            }
                            pathState = 1;
                            // falls through
                        case 1:
                            if (!(rangeArea ? xArrj.length === series[i].length : j === series[i].length - 2)) {
                                break;
                            }
                            // falls through
                        case 2: {
                            const _xAj = isRangeStart ? xArrj : xArrj.slice().reverse();
                            const _yAj = isRangeStart ? yAj : yAj.slice().reverse();
                            const smoothInputs = getSmoothInputs(_xAj, _yAj);
                            const points = smoothInputs.length > 1 ? spline.points(smoothInputs) : smoothInputs;
                            let smoothInputsLower = [];
                            if (rangeArea) {
                                if (isLowerRangeAreaPath) {
                                    areaPaths = smoothInputs;
                                } else {
                                    smoothInputsLower = areaPaths.reverse();
                                }
                            }
                            let segmentCount = 0;
                            let smoothInputsIndex = 0;
                            getSegments(_yAj, points).forEach((_) => {
                                segmentCount++;
                                const svgPoints = svgPath(_);
                                const _start = smoothInputsIndex;
                                smoothInputsIndex += _.length;
                                const _end = smoothInputsIndex - 1;
                                if (isLowerRangeAreaPath) {
                                    linePath = graphics.move(
                                        smoothInputs[_start][0],
                                        smoothInputs[_start][1]
                                    ) + svgPoints;
                                } else if (rangeArea) {
                                    linePath = graphics.move(
                                        smoothInputsLower[_start][0],
                                        smoothInputsLower[_start][1]
                                    ) + graphics.line(
                                        smoothInputs[_start][0],
                                        smoothInputs[_start][1]
                                    ) + svgPoints + graphics.line(
                                        smoothInputsLower[_end][0],
                                        smoothInputsLower[_end][1]
                                    );
                                } else {
                                    linePath = graphics.move(
                                        smoothInputs[_start][0],
                                        smoothInputs[_start][1]
                                    ) + svgPoints;
                                    areaPath = linePath + graphics.line(smoothInputs[_end][0], areaBottomY) + graphics.line(smoothInputs[_start][0], areaBottomY) + "z";
                                    areaPaths.push(areaPath);
                                }
                                linePaths.push(linePath);
                            });
                            if (rangeArea && segmentCount > 1 && !isLowerRangeAreaPath) {
                                const upperLinePaths = linePaths.slice(segmentCount).reverse();
                                linePaths.splice(segmentCount);
                                upperLinePaths.forEach(
                                    (u) => linePaths.push(u)
                                );
                            }
                            pathState = 0;
                            break;
                        }
                    }
                    break;
                }
                case "smooth": {
                    const length = (x - pX) * 0.35;
                    if (series[i][j] === null) {
                        pathState = 0;
                    } else {
                        switch (pathState) {
                            case 0:
                                segmentStartX = pX;
                                if (isLowerRangeAreaPath) {
                                    linePath = graphics.move(pX, y2Arrj[j]) + graphics.line(pX, pY);
                                } else {
                                    linePath = graphics.move(pX, pY);
                                }
                                areaPath = graphics.move(pX, pY);
                                if (series[i][j + 1] === null || typeof series[i][j + 1] === "undefined") {
                                    linePaths.push(linePath);
                                    areaPaths.push(areaPath);
                                    break;
                                }
                                pathState = 1;
                                if (j < series[i].length - 2) {
                                    const p = graphics.curve(pX + length, pY, x - length, y, x, y);
                                    linePath += p;
                                    areaPath += p;
                                    break;
                                }
                                // falls through
                            case 1:
                                if (series[i][j + 1] === null) {
                                    if (isLowerRangeAreaPath) {
                                        linePath += graphics.line(pX, y2);
                                    } else {
                                        linePath += graphics.move(pX, pY);
                                    }
                                    areaPath += graphics.line(pX, areaBottomY) + graphics.line(segmentStartX, areaBottomY) + "z";
                                    linePaths.push(linePath);
                                    areaPaths.push(areaPath);
                                    pathState = -1;
                                } else {
                                    const p = graphics.curve(pX + length, pY, x - length, y, x, y);
                                    linePath += p;
                                    areaPath += p;
                                    if (j >= series[i].length - 2) {
                                        if (isLowerRangeAreaPath) {
                                            linePath += graphics.curve(x, y, x, y, x, y2) + graphics.move(x, y2);
                                        }
                                        areaPath += graphics.curve(x, y, x, y, x, areaBottomY) + graphics.line(segmentStartX, areaBottomY) + "z";
                                        linePaths.push(linePath);
                                        areaPaths.push(areaPath);
                                        pathState = -1;
                                    }
                                }
                                break;
                        }
                    }
                    pX = x;
                    pY = y;
                    break;
                }
                default: {
                    const pathToPoint = (curve2, x2, y3) => {
                        let path = "";
                        switch (curve2) {
                            case "stepline":
                                path = graphics.line(x2, null, "H") + graphics.line(null, y3, "V");
                                break;
                            case "linestep":
                                path = graphics.line(null, y3, "V") + graphics.line(x2, null, "H");
                                break;
                            case "straight":
                                path = graphics.line(x2, y3);
                                break;
                        }
                        return path;
                    };
                    if (series[i][j] === null) {
                        pathState = 0;
                    } else {
                        switch (pathState) {
                            case 0:
                                segmentStartX = pX;
                                if (isLowerRangeAreaPath) {
                                    linePath = graphics.move(pX, y2Arrj[j]) + graphics.line(pX, pY);
                                } else {
                                    linePath = graphics.move(pX, pY);
                                }
                                areaPath = graphics.move(pX, pY);
                                if (series[i][j + 1] === null || typeof series[i][j + 1] === "undefined") {
                                    linePaths.push(linePath);
                                    areaPaths.push(areaPath);
                                    break;
                                }
                                pathState = 1;
                                if (j < series[i].length - 2) {
                                    const p = pathToPoint(curve, x, y);
                                    linePath += p;
                                    areaPath += p;
                                    break;
                                }
                                // falls through
                            case 1:
                                if (series[i][j + 1] === null) {
                                    if (isLowerRangeAreaPath) {
                                        linePath += graphics.line(pX, y2);
                                    } else {
                                        linePath += graphics.move(pX, pY);
                                    }
                                    areaPath += graphics.line(pX, areaBottomY) + graphics.line(segmentStartX, areaBottomY) + "z";
                                    linePaths.push(linePath);
                                    areaPaths.push(areaPath);
                                    pathState = -1;
                                } else {
                                    const p = pathToPoint(curve, x, y);
                                    linePath += p;
                                    areaPath += p;
                                    if (j >= series[i].length - 2) {
                                        if (isLowerRangeAreaPath) {
                                            linePath += graphics.line(x, y2);
                                        }
                                        areaPath += graphics.line(x, areaBottomY) + graphics.line(segmentStartX, areaBottomY) + "z";
                                        linePaths.push(linePath);
                                        areaPaths.push(areaPath);
                                        pathState = -1;
                                    }
                                }
                                break;
                        }
                    }
                    pX = x;
                    pY = y;
                    break;
                }
            }
            return {
                linePaths,
                areaPaths,
                pX,
                pY,
                pathState,
                segmentStartX,
                linePath,
                areaPath
            };
        }
        /**
         * @param {any[]} series
         * @param {any} pointsPos
         * @param {number} i
         * @param {number} j
         * @param {number} realIndex
         */
        handleNullDataPoints(series, pointsPos, i, j, realIndex) {
            const w = this.w;
            if (series[i][j] === null && w.config.markers.showNullDataPoints || series[i].length === 1) {
                let pSize = this.strokeWidth - w.config.markers.strokeWidth / 2;
                if (!(pSize > 0)) {
                    pSize = 0;
                }
                const elPointsWrap = this.markers.plotChartMarkers({
                    pointsPos,
                    seriesIndex: realIndex,
                    j: j + 1,
                    pSize,
                    alwaysDrawMarker: true
                });
                if (elPointsWrap !== null) {
                    this.elPointsMain.add(elPointsWrap);
                }
            }
        }
    }
    class CircularChartsHelpers {
        /**
         * @param {import('../../../types/internal').ChartStateW} w
         */
        constructor(w) {
            this.w = w;
        }
        /**
         * @param {number} x
         * @param {number} y
         * @param {number} i
         * @param {string | number} text
         */
        drawYAxisTexts(x, y, i, text) {
            const w = this.w;
            const yaxisConfig = w.config.yaxis[0];
            const formatter = w.formatters.yLabelFormatters[0];
            const graphics = new Graphics(this.w);
            const yaxisLabel = graphics.drawText({
                x: x + yaxisConfig.labels.offsetX,
                y: y + yaxisConfig.labels.offsetY,
                text: formatter(text, i),
                textAnchor: "middle",
                fontSize: yaxisConfig.labels.style.fontSize,
                fontFamily: yaxisConfig.labels.style.fontFamily,
                foreColor: Array.isArray(yaxisConfig.labels.style.colors) ? yaxisConfig.labels.style.colors[i] : yaxisConfig.labels.style.colors
            });
            return yaxisLabel;
        }
    }
    class Pie {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.ctx = ctx;
            this.w = w;
            this.chartType = this.w.config.chart.type;
            this.initialAnim = this.w.config.chart.animations.enabled;
            this.dynamicAnim = this.initialAnim && this.w.config.chart.animations.dynamicAnimation.enabled;
            this.animBeginArr = [0];
            this.animDur = 0;
            this.donutDataLabels = this.w.config.plotOptions.pie.donut.labels;
            this.lineColorArr = w.globals.stroke.colors !== void 0 ? w.globals.stroke.colors : w.globals.colors;
            this.defaultSize = Math.min(w.layout.gridWidth, w.layout.gridHeight);
            this.centerY = this.defaultSize / 2;
            this.centerX = w.layout.gridWidth / 2;
            if (w.config.chart.type === "radialBar") {
                this.fullAngle = 360;
            } else {
                this.fullAngle = Math.abs(
                    w.config.plotOptions.pie.endAngle - w.config.plotOptions.pie.startAngle
                );
            }
            this.initialAngle = w.config.plotOptions.pie.startAngle % this.fullAngle;
            w.globals.radialSize = this.defaultSize / 2.05 - w.config.stroke.width - (!w.config.chart.sparkline.enabled ? w.config.chart.dropShadow.blur : 0);
            this.donutSize = w.globals.radialSize * parseInt(w.config.plotOptions.pie.donut.size, 10) / 100;
            const scaleSize = w.config.plotOptions.pie.customScale;
            const halfW = w.layout.gridWidth / 2;
            const halfH = w.layout.gridHeight / 2;
            this.translateX = halfW - halfW * scaleSize;
            this.translateY = halfH - halfH * scaleSize;
            this.dataLabelsGroup = new Graphics(this.w).group({
                class: "apexcharts-datalabels-group",
                transform: `translate(${this.translateX}, ${this.translateY}) scale(${scaleSize})`
            });
            this.maxY = 0;
            this.sliceLabels = [];
            this.sliceSizes = [];
            this.prevSectorAngleArr = [];
        }
        /**
         * @param {any[]} series
         */
        draw(series) {
            var _a;
            const self2 = this;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const elPie = graphics.group({
                class: "apexcharts-pie"
            });
            if (w.globals.noData) return elPie;
            let total = 0;
            for (let k = 0; k < series.length; k++) {
                total += Utils$1.negToZero(series[k]);
            }
            const sectorAngleArr = [];
            const elSeries = graphics.group();
            if (total === 0) {
                total = 1e-5;
            }
            series.forEach((m) => {
                this.maxY = Math.max(this.maxY, m);
            });
            if (w.config.yaxis[0].max) {
                this.maxY = w.config.yaxis[0].max;
            }
            if (w.config.grid.position === "back" && this.chartType === "polarArea") {
                this.drawPolarElements(elPie);
            }
            for (let i = 0; i < series.length; i++) {
                const angle = this.fullAngle * Utils$1.negToZero(series[i]) / total;
                sectorAngleArr.push(angle);
                if (this.chartType === "polarArea") {
                    sectorAngleArr[i] = this.fullAngle / series.length;
                    this.sliceSizes.push(w.globals.radialSize * series[i] / this.maxY);
                } else {
                    this.sliceSizes.push(w.globals.radialSize);
                }
            }
            const morphActive = ((_a = this.ctx.morphTypeChange) == null ? void 0 : _a.isActive()) === true;
            if (w.globals.dataChanged && !morphActive) {
                let prevTotal = 0;
                for (let k = 0; k < w.globals.previousPaths.length; k++) {
                    prevTotal += Utils$1.negToZero(w.globals.previousPaths[k]);
                }
                let previousAngle;
                for (let i = 0; i < w.globals.previousPaths.length; i++) {
                    previousAngle = this.fullAngle * Utils$1.negToZero(w.globals.previousPaths[i]) / prevTotal;
                    this.prevSectorAngleArr.push(previousAngle);
                }
            }
            if (this.donutSize < 0) {
                this.donutSize = 0;
            }
            if (this.chartType === "donut") {
                const circle = graphics.drawCircle(this.donutSize);
                circle.attr({
                    cx: this.centerX,
                    cy: this.centerY,
                    fill: w.config.plotOptions.pie.donut.background ? w.config.plotOptions.pie.donut.background : "transparent"
                });
                elSeries.add(circle);
            }
            const elG = self2.drawArcs(sectorAngleArr, series);
            this.sliceLabels.forEach((s) => {
                elG.add(s);
            });
            elSeries.attr({
                transform: `translate(${this.translateX}, ${this.translateY}) scale(${w.config.plotOptions.pie.customScale})`
            });
            elSeries.add(elG);
            elPie.add(elSeries);
            if (this.donutDataLabels.show) {
                const shouldFadeInLabels = this.initialAnim && !w.globals.resized && !w.globals.dataChanged && this.animDur > 0;
                const dataLabels = this.renderInnerDataLabels(
                    this.dataLabelsGroup,
                    this.donutDataLabels, {
                        hollowSize: this.donutSize,
                        centerX: this.centerX,
                        centerY: this.centerY,
                        opacity: shouldFadeInLabels ? 0 : this.donutDataLabels.show
                    }
                );
                if (shouldFadeInLabels) {
                    const labelsNode = this.dataLabelsGroup.node;
                    labelsNode.style.transition = "opacity 280ms ease-out";
                    setTimeout(() => {
                        labelsNode.style.opacity = "1";
                    }, this.animDur);
                }
                elPie.add(dataLabels);
            }
            if (w.config.grid.position === "front" && this.chartType === "polarArea") {
                this.drawPolarElements(elPie);
            }
            return elPie;
        }
        // core function for drawing pie arcs
        /**
         * @param {any[]} sectorAngleArr
         * @param {any[]} series
         */
        drawArcs(sectorAngleArr, series) {
            var _a;
            const w = this.w;
            const filters = new Filters(this.w);
            const graphics = new Graphics(this.w);
            const fill = new Fill(this.w);
            const g = graphics.group({
                class: "apexcharts-slices"
            });
            let startAngle = this.initialAngle;
            let prevStartAngle = this.initialAngle;
            let endAngle = this.initialAngle;
            let prevEndAngle = this.initialAngle;
            this.strokeWidth = w.config.stroke.show ? w.config.stroke.width : 0;
            const morphActive = ((_a = this.ctx.morphTypeChange) == null ? void 0 : _a.isActive()) === true;
            for (let i = 0; i < sectorAngleArr.length; i++) {
                const elPieArc = graphics.group({
                    class: `apexcharts-series apexcharts-pie-series`,
                    seriesName: Utils$1.escapeString(w.seriesData.seriesNames[i]),
                    rel: i + 1,
                    "data:realIndex": i
                });
                g.add(elPieArc);
                startAngle = endAngle;
                prevStartAngle = prevEndAngle;
                endAngle = startAngle + sectorAngleArr[i];
                prevEndAngle = prevStartAngle + this.prevSectorAngleArr[i];
                const angle = endAngle < startAngle ? this.fullAngle + endAngle - startAngle : endAngle - startAngle;
                const pathFill = fill.fillPath({
                    seriesNumber: i,
                    size: this.sliceSizes[i],
                    value: series[i]
                });
                const morphFrom = morphActive ? this.ctx.morphTypeChange.getInitialPathFor(i, 0) : null;
                const path = morphFrom || this.getChangedPath(prevStartAngle, prevEndAngle);
                const elPath = graphics.drawPath({
                    d: path,
                    stroke: Array.isArray(this.lineColorArr) ? this.lineColorArr[i] : this.lineColorArr,
                    strokeWidth: 0,
                    fill: pathFill,
                    fillOpacity: w.config.fill.opacity,
                    classes: `apexcharts-pie-area apexcharts-${this.chartType.toLowerCase()}-slice-${i}`
                });
                elPath.attr({
                    index: 0,
                    j: i
                });
                filters.setSelectionFilter(elPath, 0, i);
                if (w.config.chart.dropShadow.enabled) {
                    const shadow = w.config.chart.dropShadow;
                    filters.dropShadow(elPath, shadow, i);
                }
                this.addListeners(elPath, this.donutDataLabels);
                let labelPosition = {
                    x: 0,
                    y: 0
                };
                const midAngle = (startAngle + angle / 2) % this.fullAngle;
                let arcCenter = {
                    x: this.centerX,
                    y: this.centerY
                };
                if (this.chartType === "pie" || this.chartType === "polarArea") {
                    labelPosition = Utils$1.polarToCartesian(
                        this.centerX,
                        this.centerY,
                        w.globals.radialSize / 1.25 + w.config.plotOptions.pie.dataLabels.offset,
                        midAngle
                    );
                    arcCenter = Utils$1.polarToCartesian(
                        this.centerX,
                        this.centerY,
                        w.globals.radialSize / 2,
                        midAngle
                    );
                } else if (this.chartType === "donut") {
                    labelPosition = Utils$1.polarToCartesian(
                        this.centerX,
                        this.centerY,
                        (w.globals.radialSize + this.donutSize) / 2 + w.config.plotOptions.pie.dataLabels.offset,
                        midAngle
                    );
                    arcCenter = Utils$1.polarToCartesian(
                        this.centerX,
                        this.centerY,
                        (w.globals.radialSize + this.donutSize) / 2,
                        midAngle
                    );
                }
                Graphics.setAttrs(elPath.node, {
                    "data:angle": angle,
                    "data:startAngle": startAngle,
                    "data:strokeWidth": this.strokeWidth,
                    "data:value": series[i],
                    "data:cx": arcCenter.x,
                    "data:cy": arcCenter.y
                });
                elPieArc.add(elPath);
                let dur = 0;
                if (this.initialAnim && !w.globals.resized && !w.globals.dataChanged) {
                    dur = angle / this.fullAngle * w.config.chart.animations.speed;
                    if (dur === 0) dur = 1;
                    this.animDur = dur + this.animDur;
                    this.animBeginArr.push(this.animDur);
                } else {
                    this.animBeginArr.push(0);
                }
                if (morphActive && morphFrom) {
                    const targetD = this.getPiePath({
                        me: this,
                        startAngle,
                        angle,
                        size: this.sliceSizes[i]
                    });
                    const morphSpeed = this.ctx.morphTypeChange.getSpeed();
                    elPath.node.setAttribute("data:pathOrig", targetD);
                    elPath.animate(morphSpeed).plot(targetD, "polygons").attr({
                        "stroke-width": this.strokeWidth
                    });
                } else if (this.dynamicAnim && w.globals.dataChanged) {
                    this.animatePaths(elPath, {
                        size: this.sliceSizes[i],
                        endAngle,
                        startAngle,
                        prevStartAngle,
                        prevEndAngle,
                        animateStartingPos: true,
                        i,
                        animBeginArr: this.animBeginArr,
                        shouldSetPrevPaths: true,
                        dur: w.config.chart.animations.dynamicAnimation.speed
                    });
                } else {
                    this.animatePaths(elPath, {
                        size: this.sliceSizes[i],
                        endAngle,
                        startAngle,
                        i,
                        totalItems: sectorAngleArr.length - 1,
                        animBeginArr: this.animBeginArr,
                        dur
                    });
                }
                if (w.config.plotOptions.pie.expandOnClick && this.chartType !== "polarArea") {
                    elPath.node.addEventListener("mouseup", this.pieClicked.bind(this, i));
                }
                if (typeof w.interact.selectedDataPoints[0] !== "undefined" && w.interact.selectedDataPoints[0].indexOf(i) > -1) {
                    if (this.initialAnim && !w.globals.resized && !w.globals.dataChanged && this.animDur > 0) {
                        const _this = this;
                        const _i = i;
                        setTimeout(() => _this.pieClicked(_i), this.animDur);
                    } else {
                        this.pieClicked(i);
                    }
                }
                if (w.config.dataLabels.enabled) {
                    const xPos = labelPosition.x;
                    const yPos = labelPosition.y;
                    let text = 100 * angle / this.fullAngle + "%";
                    if (angle !== 0 && w.config.plotOptions.pie.dataLabels.minAngleToShowLabel < sectorAngleArr[i]) {
                        const formatter = w.config.dataLabels.formatter;
                        if (formatter !== void 0) {
                            text = formatter(w.globals.seriesPercent[i][0], {
                                seriesIndex: i,
                                w
                            });
                        }
                        const foreColor = w.globals.dataLabels.style.colors[i];
                        const elPieLabelWrap = graphics.group({
                            class: `apexcharts-datalabels`
                        });
                        const elPieLabel = graphics.drawText({
                            x: xPos,
                            y: yPos,
                            text,
                            textAnchor: "middle",
                            fontSize: w.config.dataLabels.style.fontSize,
                            fontFamily: w.config.dataLabels.style.fontFamily,
                            fontWeight: w.config.dataLabels.style.fontWeight,
                            foreColor
                        });
                        elPieLabelWrap.add(elPieLabel);
                        if (w.config.dataLabels.dropShadow.enabled) {
                            const textShadow = w.config.dataLabels.dropShadow;
                            filters.dropShadow(elPieLabel, textShadow);
                        }
                        elPieLabel.node.classList.add("apexcharts-pie-label");
                        if (w.config.chart.animations.animate && w.globals.resized === false) {
                            elPieLabel.node.classList.add("apexcharts-pie-label-delay");
                            elPieLabel.node.style.animationDelay = w.config.chart.animations.speed / 940 + "s";
                        }
                        this.sliceLabels.push(elPieLabelWrap);
                    }
                }
            }
            return g;
        }
        /**
         * @param {any} elPath
         * @param {Record<string, any>} dataLabels
         */
        addListeners(elPath, dataLabels) {
            const graphics = new Graphics(this.w);
            elPath.node.addEventListener(
                "mouseenter",
                graphics.pathMouseEnter.bind(this, elPath)
            );
            elPath.node.addEventListener(
                "mouseleave",
                graphics.pathMouseLeave.bind(this, elPath)
            );
            elPath.node.addEventListener(
                "mouseleave",
                this.revertDataLabelsInner.bind(this)
            );
            elPath.node.addEventListener(
                "mousedown",
                graphics.pathMouseDown.bind(this, elPath)
            );
            if (!this.donutDataLabels.total.showAlways) {
                elPath.node.addEventListener(
                    "mouseenter",
                    this.printDataLabelsInner.bind(this, elPath.node, dataLabels)
                );
                elPath.node.addEventListener(
                    "mousedown",
                    this.printDataLabelsInner.bind(this, elPath.node, dataLabels)
                );
            }
        }
        // This function can be used for other circle charts too
        /**
         * @param {any} el
         * @param {Record<string, any>} opts
         */
        animatePaths(el, opts) {
            const w = this.w;
            const me = this;
            let angle = opts.endAngle < opts.startAngle ? this.fullAngle + opts.endAngle - opts.startAngle : opts.endAngle - opts.startAngle;
            let prevAngle = angle;
            let fromStartAngle = opts.startAngle;
            const toStartAngle = opts.startAngle;
            if (opts.prevStartAngle !== void 0 && opts.prevEndAngle !== void 0) {
                fromStartAngle = opts.prevEndAngle;
                prevAngle = opts.prevEndAngle < opts.prevStartAngle ? this.fullAngle + opts.prevEndAngle - opts.prevStartAngle : opts.prevEndAngle - opts.prevStartAngle;
            }
            if (opts.i === w.config.series.length - 1) {
                if (angle + toStartAngle > this.fullAngle) {
                    opts.endAngle = opts.endAngle - (angle + toStartAngle);
                } else if (angle + toStartAngle < this.fullAngle) {
                    opts.endAngle = opts.endAngle + (this.fullAngle - (angle + toStartAngle));
                }
            }
            if (angle === this.fullAngle) angle = this.fullAngle - 0.01;
            me.animateArc(el, fromStartAngle, toStartAngle, angle, prevAngle, opts);
        }
        /**
         * @param {any} el
         * @param {number} fromStartAngle
         * @param {number} toStartAngle
         * @param {number} angle
         * @param {number} prevAngle
         * @param {Record<string, any>} opts
         */
        animateArc(el, fromStartAngle, toStartAngle, angle, prevAngle, opts) {
            const me = this;
            const w = this.w;
            const animations = new Animations(this.w);
            const size = opts.size;
            let path;
            if (isNaN(fromStartAngle) || isNaN(prevAngle)) {
                fromStartAngle = toStartAngle;
                prevAngle = angle;
                opts.dur = 0;
            }
            let currAngle = angle;
            let startAngle = toStartAngle;
            const fromAngle = fromStartAngle < toStartAngle ? this.fullAngle + fromStartAngle - toStartAngle : fromStartAngle - toStartAngle;
            if (w.globals.dataChanged && opts.shouldSetPrevPaths) {
                if (opts.prevEndAngle) {
                    path = me.getPiePath({
                        me,
                        startAngle: opts.prevStartAngle,
                        angle: opts.prevEndAngle < opts.prevStartAngle ? this.fullAngle + opts.prevEndAngle - opts.prevStartAngle : opts.prevEndAngle - opts.prevStartAngle,
                        size
                    });
                    el.attr({
                        d: path
                    });
                }
            }
            if (opts.dur !== 0) {
                el.animate(opts.dur, opts.animBeginArr[opts.i]).after(
                    /** @this {any} */
                    function() {
                        if (me.chartType === "pie" || me.chartType === "donut" || me.chartType === "polarArea") {
                            this.animate(
                                w.config.chart.animations.dynamicAnimation.speed
                            ).attr({
                                "stroke-width": me.strokeWidth
                            });
                        }
                        if (opts.i === w.config.series.length - 1) {
                            animations.animationCompleted(el);
                        }
                    }
                ).during((pos) => {
                    currAngle = fromAngle + (angle - fromAngle) * pos;
                    if (opts.animateStartingPos) {
                        currAngle = prevAngle + (angle - prevAngle) * pos;
                        startAngle = fromStartAngle - prevAngle + (toStartAngle - (fromStartAngle - prevAngle)) * pos;
                    }
                    path = me.getPiePath({
                        me,
                        startAngle,
                        angle: currAngle,
                        size
                    });
                    el.node.setAttribute("data:pathOrig", path);
                    el.attr({
                        d: path
                    });
                });
            } else {
                path = me.getPiePath({
                    me,
                    startAngle,
                    angle,
                    size
                });
                if (!opts.isTrack) {
                    w.globals.animationEnded = true;
                }
                el.node.setAttribute("data:pathOrig", path);
                el.attr({
                    d: path,
                    "stroke-width": me.strokeWidth
                });
            }
        }
        /**
         * @param {number} i
         */
        pieClicked(i) {
            const w = this.w;
            const me = this;
            const size = me.sliceSizes[i] + (w.config.plotOptions.pie.expandOnClick ? 4 : 0);
            const elPath = w.dom.Paper.findOne(
                `.apexcharts-${me.chartType.toLowerCase()}-slice-${i}`
            );
            if (elPath.attr("data:pieClicked") === "true") {
                elPath.attr({
                    "data:pieClicked": "false"
                });
                this.revertDataLabelsInner();
                const origPath = elPath.attr("data:pathOrig");
                elPath.attr({
                    d: origPath
                });
                return;
            } else {
                const allEls = w.dom.baseEl.getElementsByClassName("apexcharts-pie-area");
                Array.prototype.forEach.call(allEls, (pieSlice) => {
                    pieSlice.setAttribute("data:pieClicked", "false");
                    const origPath = pieSlice.getAttribute("data:pathOrig");
                    if (origPath) {
                        pieSlice.setAttribute("d", origPath);
                    }
                });
                w.interact.capturedDataPointIndex = i;
                elPath.attr("data:pieClicked", "true");
            }
            const startAngle = parseInt(elPath.attr("data:startAngle"), 10);
            const angle = parseInt(elPath.attr("data:angle"), 10);
            const path = me.getPiePath({
                me,
                startAngle,
                angle,
                size
            });
            if (angle === 360) return;
            elPath.plot(path);
        }
        /**
         * @param {number} prevStartAngle
         * @param {number} prevEndAngle
         */
        getChangedPath(prevStartAngle, prevEndAngle) {
            let path = "";
            if (this.dynamicAnim && this.w.globals.dataChanged) {
                path = this.getPiePath({
                    me: this,
                    startAngle: prevStartAngle,
                    angle: prevEndAngle - prevStartAngle,
                    // @ts-ignore — size is set dynamically during draw()
                    size: this.size
                });
            }
            return path;
        }
        /** @param {{me: any, startAngle: any, angle: any, size: any}} opts */
        getPiePath({
            me,
            startAngle,
            angle,
            size
        }) {
            let path;
            const graphics = new Graphics(this.w);
            const startDeg = startAngle;
            const startRadians = Math.PI * (startDeg - 90) / 180;
            let endDeg = angle + startAngle;
            if (Math.ceil(endDeg) >= this.fullAngle + this.w.config.plotOptions.pie.startAngle % this.fullAngle) {
                endDeg = this.fullAngle + this.w.config.plotOptions.pie.startAngle % this.fullAngle - 0.01;
            }
            if (Math.ceil(endDeg) > this.fullAngle) endDeg -= this.fullAngle;
            const endRadians = Math.PI * (endDeg - 90) / 180;
            const x1 = me.centerX + size * Math.cos(startRadians);
            const y1 = me.centerY + size * Math.sin(startRadians);
            const x2 = me.centerX + size * Math.cos(endRadians);
            const y2 = me.centerY + size * Math.sin(endRadians);
            const startInner = Utils$1.polarToCartesian(
                me.centerX,
                me.centerY,
                me.donutSize,
                endDeg
            );
            const endInner = Utils$1.polarToCartesian(
                me.centerX,
                me.centerY,
                me.donutSize,
                startDeg
            );
            const largeArc = angle > 180 ? 1 : 0;
            const pathBeginning = ["M", x1, y1, "A", size, size, 0, largeArc, 1, x2, y2];
            if (me.chartType === "donut") {
                path = [
                    ...pathBeginning,
                    "L",
                    startInner.x,
                    startInner.y,
                    "A",
                    me.donutSize,
                    me.donutSize,
                    0,
                    largeArc,
                    0,
                    endInner.x,
                    endInner.y,
                    "L",
                    x1,
                    y1,
                    "z"
                ].join(" ");
            } else if (me.chartType === "pie" || me.chartType === "polarArea") {
                path = [...pathBeginning, "L", me.centerX, me.centerY, "L", x1, y1].join(
                    " "
                );
            } else {
                path = [...pathBeginning].join(" ");
            }
            return graphics.roundPathCorners(path, this.strokeWidth * 2);
        }
        /**
         * @param {any} parent
         */
        drawPolarElements(parent) {
            const w = this.w;
            const scale = new Scales(this.w);
            const graphics = new Graphics(this.w);
            const helpers = new CircularChartsHelpers(this.w);
            const gCircles = graphics.group();
            const gYAxis = graphics.group();
            const yScale = scale.niceScale(0, Math.ceil(this.maxY), 0);
            const yTexts = yScale.result.reverse();
            const len = yScale.result.length;
            this.maxY = yScale.niceMax;
            let circleSize = w.globals.radialSize;
            const diff = circleSize / (len - 1);
            for (let i = 0; i < len - 1; i++) {
                const circle = graphics.drawCircle(circleSize);
                circle.attr({
                    cx: this.centerX,
                    cy: this.centerY,
                    fill: "none",
                    "stroke-width": w.config.plotOptions.polarArea.rings.strokeWidth,
                    stroke: w.config.plotOptions.polarArea.rings.strokeColor
                });
                if (w.config.yaxis[0].show) {
                    const yLabel = helpers.drawYAxisTexts(
                        this.centerX,
                        this.centerY - circleSize + parseInt(w.config.yaxis[0].labels.style.fontSize, 10) / 2,
                        i,
                        yTexts[i]
                    );
                    gYAxis.add(yLabel);
                }
                gCircles.add(circle);
                circleSize = circleSize - diff;
            }
            this.drawSpokes(parent);
            parent.add(gCircles);
            parent.add(gYAxis);
        }
        /**
         * @param {any} dataLabelsGroup
         * @param {Record<string, any>} dataLabelsConfig
         * @param {Record<string, any>} opts
         */
        renderInnerDataLabels(dataLabelsGroup, dataLabelsConfig, opts) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const showTotal = dataLabelsConfig.total.show;
            dataLabelsGroup.node.innerHTML = "";
            dataLabelsGroup.node.style.opacity = opts.opacity;
            const x = opts.centerX;
            const y = !this.donutDataLabels.total.label ? opts.centerY - opts.centerY / 6 : opts.centerY;
            let labelColor, valueColor;
            if (dataLabelsConfig.name.color === void 0) {
                labelColor = w.globals.colors[0];
            } else {
                labelColor = dataLabelsConfig.name.color;
            }
            let labelFontSize = dataLabelsConfig.name.fontSize;
            let labelFontFamily = dataLabelsConfig.name.fontFamily;
            let labelFontWeight = dataLabelsConfig.name.fontWeight;
            if (dataLabelsConfig.value.color === void 0) {
                valueColor = w.config.chart.foreColor;
            } else {
                valueColor = dataLabelsConfig.value.color;
            }
            const lbFormatter = dataLabelsConfig.value.formatter;
            let val = "";
            let name2 = "";
            if (showTotal) {
                labelColor = dataLabelsConfig.total.color;
                labelFontSize = dataLabelsConfig.total.fontSize;
                labelFontFamily = dataLabelsConfig.total.fontFamily;
                labelFontWeight = dataLabelsConfig.total.fontWeight;
                name2 = !this.donutDataLabels.total.label ? "" : dataLabelsConfig.total.label;
                val = dataLabelsConfig.total.formatter(w);
            } else {
                if (w.seriesData.series.length === 1) {
                    val = lbFormatter(w.seriesData.series[0], w);
                    name2 = w.seriesData.seriesNames[0];
                }
            }
            if (name2) {
                name2 = dataLabelsConfig.name.formatter(
                    name2,
                    dataLabelsConfig.total.show,
                    w
                );
            }
            if (dataLabelsConfig.name.show) {
                const elLabel = graphics.drawText({
                    x,
                    y: y + parseFloat(dataLabelsConfig.name.offsetY),
                    text: name2,
                    textAnchor: "middle",
                    foreColor: labelColor,
                    fontSize: labelFontSize,
                    fontWeight: labelFontWeight,
                    fontFamily: labelFontFamily
                });
                elLabel.node.classList.add("apexcharts-datalabel-label");
                dataLabelsGroup.add(elLabel);
            }
            if (dataLabelsConfig.value.show) {
                const valOffset = dataLabelsConfig.name.show ? parseFloat(dataLabelsConfig.value.offsetY) + 16 : dataLabelsConfig.value.offsetY;
                const elValue = graphics.drawText({
                    x,
                    y: y + valOffset,
                    text: val,
                    textAnchor: "middle",
                    foreColor: valueColor,
                    fontWeight: dataLabelsConfig.value.fontWeight,
                    fontSize: dataLabelsConfig.value.fontSize,
                    fontFamily: dataLabelsConfig.value.fontFamily
                });
                elValue.node.classList.add("apexcharts-datalabel-value");
                dataLabelsGroup.add(elValue);
            }
            return dataLabelsGroup;
        }
        /**
         *
         * @param {string} name - The name of the series
         * @param {string} val - The value of that series
         * @param {any} el - Optional el (indicates which series was hovered/clicked). If this param is not present, means we need to show total
         * @param {Record<string, any>} labelsConfig
         */
        printInnerLabels(labelsConfig, name2, val, el) {
            const w = this.w;
            let labelColor;
            if (el) {
                if (labelsConfig.name.color === void 0) {
                    labelColor = w.globals.colors[parseInt(el.parentNode.getAttribute("rel"), 10) - 1];
                } else {
                    labelColor = labelsConfig.name.color;
                }
            } else {
                if (w.seriesData.series.length > 1 && labelsConfig.total.show) {
                    labelColor = labelsConfig.total.color;
                }
            }
            const elLabel = w.dom.baseEl.querySelector(".apexcharts-datalabel-label");
            const elValue = w.dom.baseEl.querySelector(".apexcharts-datalabel-value");
            const lbFormatter = labelsConfig.value.formatter;
            val = lbFormatter(val, w);
            if (!el && typeof labelsConfig.total.formatter === "function") {
                val = labelsConfig.total.formatter(w);
            }
            const isTotal = name2 === labelsConfig.total.label;
            name2 = !this.donutDataLabels.total.label ? "" : labelsConfig.name.formatter(name2, isTotal, w);
            if (elLabel !== null) {
                elLabel.textContent = name2;
            }
            if (elValue !== null) {
                elValue.textContent = val;
            }
            if (elLabel !== null) {
                const elLabelEl = (
                    /** @type {HTMLElement} */
                    elLabel
                );
                elLabelEl.style.fill = labelColor;
            }
        }
        /**
         * @param {any} el
         * @param {Record<string, any>} dataLabelsConfig
         */
        printDataLabelsInner(el, dataLabelsConfig) {
            const w = this.w;
            const val = el.getAttribute("data:value");
            const name2 = w.seriesData.seriesNames[parseInt(el.parentNode.getAttribute("rel"), 10) - 1];
            if (w.seriesData.series.length > 1) {
                this.printInnerLabels(dataLabelsConfig, name2, val, el);
            }
            const dataLabelsGroup = w.dom.baseEl.querySelector(
                ".apexcharts-datalabels-group"
            );
            if (dataLabelsGroup !== null) {
                const dataLabelsGroupEl = (
                    /** @type {HTMLElement} */
                    dataLabelsGroup
                );
                dataLabelsGroupEl.style.opacity = "1";
            }
        }
        /**
         * @param {any} parent
         */
        drawSpokes(parent) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const spokeConfig = w.config.plotOptions.polarArea.spokes;
            if (spokeConfig.strokeWidth === 0) return;
            const spokes = [];
            const angleDivision = 360 / w.seriesData.series.length;
            for (let i = 0; i < w.seriesData.series.length; i++) {
                spokes.push(
                    Utils$1.polarToCartesian(
                        this.centerX,
                        this.centerY,
                        w.globals.radialSize,
                        w.config.plotOptions.pie.startAngle + angleDivision * i
                    )
                );
            }
            spokes.forEach((p, i) => {
                const line = graphics.drawLine(
                    p.x,
                    p.y,
                    this.centerX,
                    this.centerY,
                    Array.isArray(spokeConfig.connectorColors) ? spokeConfig.connectorColors[i] : spokeConfig.connectorColors
                );
                parent.add(line);
            });
        }
        revertDataLabelsInner() {
            const w = this.w;
            if (this.donutDataLabels.show) {
                const dataLabelsGroup = w.dom.Paper.findOne(
                    `.apexcharts-datalabels-group`
                );
                const dataLabels = this.renderInnerDataLabels(
                    dataLabelsGroup,
                    this.donutDataLabels, {
                        hollowSize: this.donutSize,
                        centerX: this.centerX,
                        centerY: this.centerY,
                        opacity: this.donutDataLabels.show
                    }
                );
                const elPie = w.dom.Paper.findOne(
                    ".apexcharts-radialbar, .apexcharts-pie"
                );
                elPie.add(dataLabels);
            }
        }
    }
    class Radar {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.ctx = ctx;
            this.w = w;
            this.chartType = this.w.config.chart.type;
            this.initialAnim = this.w.config.chart.animations.enabled;
            this.dynamicAnim = this.initialAnim && this.w.config.chart.animations.dynamicAnimation.enabled;
            this.animDur = 0;
            this.graphics = new Graphics(this.w);
            this.lineColorArr = w.globals.stroke.colors !== void 0 ? w.globals.stroke.colors : w.globals.colors;
            this.defaultSize = w.globals.svgHeight < w.globals.svgWidth ? w.layout.gridHeight : w.layout.gridWidth;
            this.isLog = w.config.yaxis[0].logarithmic;
            this.logBase = w.config.yaxis[0].logBase;
            this.coreUtils = new CoreUtils(this.w);
            this.maxValue = this.isLog ? this.coreUtils.getLogVal(this.logBase, w.globals.maxY, 0) : w.globals.maxY;
            this.minValue = this.isLog ? this.coreUtils.getLogVal(this.logBase, this.w.globals.minY, 0) : w.globals.minY;
            this.polygons = w.config.plotOptions.radar.polygons;
            this.strokeWidth = w.config.stroke.show ? w.config.stroke.width : 0;
            this.size = this.defaultSize / 2.1 - this.strokeWidth - w.config.chart.dropShadow.blur;
            if (w.config.xaxis.labels.show) {
                this.size = this.size - w.layout.xAxisLabelsWidth / 1.75;
            }
            if (w.config.plotOptions.radar.size !== void 0) {
                this.size = w.config.plotOptions.radar.size;
            }
            this.dataRadiusOfPercent = /** @type {any} */ [];
            this.dataRadius = /** @type {any} */ [];
            this.angleArr = /** @type {any} */ [];
            this.dataPointsLen = 0;
            this.disAngle = 0;
            this.yaxisLabelsTextsPos = [];
        }
        /**
         * @param {any[]} series
         */
        draw(series) {
            const w = this.w;
            const fill = new Fill(this.w);
            const allSeries = [];
            const dataLabels = new DataLabels(this.w, this.ctx);
            if (series.length) {
                this.dataPointsLen = series[w.globals.maxValsInArrayIndex].length;
            }
            this.disAngle = Math.PI * 2 / this.dataPointsLen;
            const halfW = w.layout.gridWidth / 2;
            const halfH = w.layout.gridHeight / 2;
            const translateX = halfW + w.config.plotOptions.radar.offsetX;
            const translateY = halfH + w.config.plotOptions.radar.offsetY;
            const ret = this.graphics.group({
                class: "apexcharts-radar-series apexcharts-plot-series",
                transform: `translate(${translateX || 0}, ${translateY || 0})`
            });
            let dataPointsPos = [];
            let elPointsMain = null;
            let elDataPointsMain = null;
            this.yaxisLabels = this.graphics.group({
                class: "apexcharts-yaxis"
            });
            series.forEach((s, i) => {
                const longestSeries = s.length === w.globals.dataPoints;
                const elSeries = this.graphics.group().attr({
                    class: `apexcharts-series`,
                    "data:longestSeries": longestSeries,
                    seriesName: Utils$1.escapeString(w.seriesData.seriesNames[i]),
                    rel: i + 1,
                    "data:realIndex": i
                });
                this.dataRadiusOfPercent[i] = [];
                this.dataRadius[i] = [];
                this.angleArr[i] = [];
                s.forEach((dv, j) => {
                    const range = Math.abs(this.maxValue - this.minValue);
                    dv = dv - this.minValue;
                    if (this.isLog) {
                        dv = this.coreUtils.getLogVal(this.logBase, dv, 0);
                    }
                    this.dataRadiusOfPercent[i][j] = dv / range;
                    this.dataRadius[i][j] = this.dataRadiusOfPercent[i][j] * this.size;
                    this.angleArr[i][j] = j * this.disAngle;
                });
                dataPointsPos = this.getDataPointsPos(
                    this.dataRadius[i],
                    this.angleArr[i]
                );
                const paths = this.createPaths(dataPointsPos, {
                    x: 0,
                    y: 0
                });
                elPointsMain = this.graphics.group({
                    class: "apexcharts-series-markers-wrap apexcharts-element-hidden"
                });
                elDataPointsMain = this.graphics.group({
                    class: `apexcharts-datalabels`,
                    "data:realIndex": i
                });
                w.globals.delayedElements.push({
                    el: elPointsMain.node,
                    index: i
                });
                const defaultRenderedPathOptions = {
                    i,
                    realIndex: i,
                    animationDelay: i,
                    initialSpeed: w.config.chart.animations.speed,
                    dataChangeSpeed: w.config.chart.animations.dynamicAnimation.speed,
                    className: `apexcharts-radar`,
                    shouldClipToGrid: false,
                    bindEventsOnPaths: false,
                    stroke: w.globals.stroke.colors[i],
                    strokeLineCap: w.config.stroke.lineCap
                };
                let pathFrom = null;
                if (w.globals.previousPaths.length > 0) {
                    pathFrom = this.getPreviousPath(i);
                }
                for (let p = 0; p < paths.linePathsTo.length; p++) {
                    const renderedLinePath = this.graphics.renderPaths(__spreadProps(__spreadValues({}, defaultRenderedPathOptions), {
                        pathFrom: pathFrom === null ? paths.linePathsFrom[p] : pathFrom,
                        pathTo: paths.linePathsTo[p],
                        strokeWidth: Array.isArray(this.strokeWidth) ? this.strokeWidth[i] : this.strokeWidth,
                        fill: "none",
                        drawShadow: false
                    }));
                    elSeries.add(renderedLinePath);
                    const pathFill = fill.fillPath({
                        seriesNumber: i
                    });
                    const renderedAreaPath = this.graphics.renderPaths(__spreadProps(__spreadValues({}, defaultRenderedPathOptions), {
                        pathFrom: pathFrom === null ? paths.areaPathsFrom[p] : pathFrom,
                        pathTo: paths.areaPathsTo[p],
                        strokeWidth: 0,
                        fill: pathFill,
                        drawShadow: false,
                        // Radial mask: the area fill blooms outward from the radar's center
                        // (in this group's local coords) instead of the default L→R rect wipe.
                        drawMask: {
                            type: "radial",
                            cx: 0,
                            cy: 0,
                            r: this.size
                        }
                    }));
                    if (w.config.chart.dropShadow.enabled) {
                        const filters = new Filters(this.w);
                        const shadow = w.config.chart.dropShadow;
                        filters.dropShadow(
                            renderedAreaPath,
                            Object.assign({}, shadow, {
                                noUserSpaceOnUse: true
                            }),
                            i
                        );
                    }
                    elSeries.add(renderedAreaPath);
                }
                s.forEach((sj, j) => {
                    const markers = new Markers(this.w, this.ctx);
                    const opts = markers.getMarkerConfig({
                        cssClass: "apexcharts-marker",
                        seriesIndex: i,
                        dataPointIndex: j
                    });
                    const point = this.graphics.drawMarker(
                        dataPointsPos[j].x,
                        dataPointsPos[j].y,
                        opts
                    );
                    point.attr("rel", j);
                    point.attr("j", j);
                    point.attr("index", i);
                    point.node.setAttribute("default-marker-size", opts.pSize);
                    const elPointsWrap = this.graphics.group({
                        class: "apexcharts-series-markers"
                    });
                    if (elPointsWrap) {
                        elPointsWrap.add(point);
                    }
                    elPointsMain.add(elPointsWrap);
                    elSeries.add(elPointsMain);
                    const dataLabelsConfig = w.config.dataLabels;
                    if (dataLabelsConfig.enabled) {
                        const text = dataLabelsConfig.formatter(w.seriesData.series[i][j], {
                            seriesIndex: i,
                            dataPointIndex: j,
                            w
                        });
                        dataLabels.plotDataLabelsText({
                            x: dataPointsPos[j].x,
                            y: dataPointsPos[j].y,
                            text,
                            textAnchor: "middle",
                            i,
                            j: i,
                            parent: elDataPointsMain,
                            offsetCorrection: false,
                            dataLabelsConfig: __spreadValues({}, dataLabelsConfig)
                        });
                    }
                    elSeries.add(elDataPointsMain);
                });
                allSeries.push(elSeries);
            });
            this.drawPolygons({
                parent: ret
            });
            if (w.config.xaxis.labels.show) {
                const xaxisTexts = this.drawXAxisTexts();
                ret.add(xaxisTexts);
            }
            allSeries.forEach((elS) => {
                ret.add(elS);
            });
            ret.add(this.yaxisLabels);
            return ret;
        }
        /**
         * @param {Record<string, any>} opts
         */
        drawPolygons(opts) {
            const w = this.w;
            const {
                parent
            } = opts;
            const helpers = new CircularChartsHelpers(this.w);
            const yaxisTexts = w.globals.yAxisScale[0].result.reverse();
            const layers = yaxisTexts.length;
            const radiusSizes = [];
            const layerDis = this.size / (layers - 1);
            for (let i = 0; i < layers; i++) {
                radiusSizes[i] = layerDis * i;
            }
            radiusSizes.reverse();
            const polygonStrings = [];
            const lines = [];
            radiusSizes.forEach((radiusSize, r) => {
                const polygon = Utils$1.getPolygonPos(radiusSize, this.dataPointsLen);
                let string = "";
                polygon.forEach((p, i) => {
                    if (r === 0) {
                        const line = this.graphics.drawLine(
                            p.x,
                            p.y,
                            0,
                            0,
                            Array.isArray(this.polygons.connectorColors) ? this.polygons.connectorColors[i] : this.polygons.connectorColors
                        );
                        lines.push(line);
                    }
                    if (i === 0) {
                        this.yaxisLabelsTextsPos.push({
                            x: p.x,
                            y: p.y
                        });
                    }
                    string += p.x + "," + p.y + " ";
                });
                polygonStrings.push(string);
            });
            polygonStrings.forEach((p, i) => {
                const strokeColors = this.polygons.strokeColors;
                const strokeWidth = this.polygons.strokeWidth;
                const polygon = this.graphics.drawPolygon(
                    p,
                    Array.isArray(strokeColors) ? strokeColors[i] : strokeColors,
                    Array.isArray(strokeWidth) ? strokeWidth[i] : strokeWidth,
                    w.globals.radarPolygons.fill.colors[i]
                );
                parent.add(polygon);
            });
            lines.forEach((l) => {
                parent.add(l);
            });
            if (w.config.yaxis[0].show) {
                this.yaxisLabelsTextsPos.forEach(
                    (p, i) => {
                        const yText = helpers.drawYAxisTexts(p.x, p.y, i, yaxisTexts[i]);
                        this.yaxisLabels.add(yText);
                    }
                );
            }
        }
        drawXAxisTexts() {
            const w = this.w;
            const xaxisLabelsConfig = w.config.xaxis.labels;
            const elXAxisWrap = this.graphics.group({
                class: "apexcharts-xaxis"
            });
            const polygonPos = Utils$1.getPolygonPos(this.size, this.dataPointsLen);
            w.labelData.labels.forEach((label, i) => {
                const formatter = w.config.xaxis.labels.formatter;
                const dataLabels = new DataLabels(this.w, this.ctx);
                if (polygonPos[i]) {
                    const textPos = this.getTextPos(polygonPos[i], this.size);
                    const text = formatter(label, {
                        seriesIndex: -1,
                        dataPointIndex: i,
                        w
                    });
                    const dataLabelText = dataLabels.plotDataLabelsText({
                        x: textPos.newX,
                        y: textPos.newY,
                        text,
                        textAnchor: textPos.textAnchor,
                        i,
                        j: i,
                        parent: elXAxisWrap,
                        className: "apexcharts-xaxis-label",
                        color: Array.isArray(xaxisLabelsConfig.style.colors) && xaxisLabelsConfig.style.colors[i] ? xaxisLabelsConfig.style.colors[i] : "#a8a8a8",
                        dataLabelsConfig: __spreadValues({
                            textAnchor: textPos.textAnchor,
                            dropShadow: {
                                enabled: false
                            }
                        }, xaxisLabelsConfig),
                        offsetCorrection: false
                    });
                    dataLabelText.on("click", (e) => {
                        if (typeof w.config.chart.events.xAxisLabelClick === "function") {
                            const opts = Object.assign({}, w, {
                                labelIndex: i
                            });
                            w.config.chart.events.xAxisLabelClick(e, this.ctx, opts);
                        }
                    });
                }
            });
            return elXAxisWrap;
        }
        /**
         * @param {Array<Record<string, any>>} pos
         * @param {Record<string, any>} origin
         */
        createPaths(pos, origin) {
            const linePathsTo = [];
            let linePathsFrom = [];
            const areaPathsTo = [];
            let areaPathsFrom = [];
            if (pos.length) {
                linePathsFrom = [this.graphics.move(origin.x, origin.y)];
                areaPathsFrom = [this.graphics.move(origin.x, origin.y)];
                let linePathTo = this.graphics.move(pos[0].x, pos[0].y);
                let areaPathTo = this.graphics.move(pos[0].x, pos[0].y);
                pos.forEach((p, i) => {
                    linePathTo += this.graphics.line(p.x, p.y);
                    areaPathTo += this.graphics.line(p.x, p.y);
                    if (i === pos.length - 1) {
                        linePathTo += "Z";
                        areaPathTo += "Z";
                    }
                });
                linePathsTo.push(linePathTo);
                areaPathsTo.push(areaPathTo);
            }
            return {
                linePathsFrom,
                linePathsTo,
                areaPathsFrom,
                areaPathsTo
            };
        }
        /**
         * @param {Record<string, any>} pos
         * @param {number} polygonSize
         */
        getTextPos(pos, polygonSize) {
            const limit = 10;
            let textAnchor = "middle";
            let newX = pos.x;
            let newY = pos.y;
            if (Math.abs(pos.x) >= limit) {
                if (pos.x > 0) {
                    textAnchor = "start";
                    newX += 10;
                } else if (pos.x < 0) {
                    textAnchor = "end";
                    newX -= 10;
                }
            } else {
                textAnchor = "middle";
            }
            if (Math.abs(pos.y) >= polygonSize - limit) {
                if (pos.y < 0) {
                    newY -= 10;
                } else if (pos.y > 0) {
                    newY += 10;
                }
            }
            return {
                textAnchor,
                newX,
                newY
            };
        }
        /**
         * @param {number} realIndex
         */
        getPreviousPath(realIndex) {
            const w = this.w;
            let pathFrom = null;
            for (let pp = 0; pp < w.globals.previousPaths.length; pp++) {
                const gpp = w.globals.previousPaths[pp];
                if (gpp.paths.length > 0 && parseInt(gpp.realIndex, 10) === parseInt(String(realIndex), 10)) {
                    if (typeof w.globals.previousPaths[pp].paths[0] !== "undefined") {
                        pathFrom = w.globals.previousPaths[pp].paths[0].d;
                    }
                }
            }
            return pathFrom;
        }
        /**
         * @param {any[]} dataRadiusArr
         * @param {any[]} angleArr
         */
        getDataPointsPos(dataRadiusArr, angleArr, dataPointsLen = this.dataPointsLen) {
            dataRadiusArr = dataRadiusArr || [];
            angleArr = angleArr || [];
            const dataPointsPosArray = [];
            for (let j = 0; j < dataPointsLen; j++) {
                const curPointPos = {};
                curPointPos.x = dataRadiusArr[j] * Math.sin(angleArr[j]);
                curPointPos.y = -dataRadiusArr[j] * Math.cos(angleArr[j]);
                dataPointsPosArray.push(curPointPos);
            }
            return dataPointsPosArray;
        }
    }
    class Radial extends Pie {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            super(w, ctx);
            this.ctx = ctx;
            this.w = w;
            this.animBeginArr = [0];
            this.animDur = 0;
            this.startAngle = w.config.plotOptions.radialBar.startAngle;
            this.endAngle = w.config.plotOptions.radialBar.endAngle;
            this.totalAngle = Math.abs(
                w.config.plotOptions.radialBar.endAngle - w.config.plotOptions.radialBar.startAngle
            );
            this.trackStartAngle = w.config.plotOptions.radialBar.track.startAngle;
            this.trackEndAngle = w.config.plotOptions.radialBar.track.endAngle;
            this.barLabels = this.w.config.plotOptions.radialBar.barLabels;
            this.donutDataLabels = this.w.config.plotOptions.radialBar.dataLabels;
            this.radialDataLabels = this.donutDataLabels;
            if (!this.trackStartAngle) this.trackStartAngle = this.startAngle;
            if (!this.trackEndAngle) this.trackEndAngle = this.endAngle;
            if (this.endAngle === 360) this.endAngle = 359.99;
            this.margin = parseInt(w.config.plotOptions.radialBar.track.margin, 10);
            this.onBarLabelClick = this.onBarLabelClick.bind(this);
        }
        /**
         * @param {any[]} series
         */
        draw(series) {
            var _a;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const ret = graphics.group({
                class: "apexcharts-radialbar"
            });
            if (w.globals.noData) return ret;
            const elSeries = graphics.group();
            const centerY = this.defaultSize / 2;
            const centerX = w.layout.gridWidth / 2;
            let size = this.defaultSize / 2.05;
            if (!w.config.chart.sparkline.enabled) {
                size = size - w.config.stroke.width - w.config.chart.dropShadow.blur;
            }
            const colorArr = w.globals.fill.colors;
            const rb = w.config.plotOptions.radialBar;
            const hasBands = Array.isArray(rb.bands) && rb.bands.length > 0;
            const hideTrack = hasBands && rb.bandsStyle && rb.bandsStyle.hideTrackWhenPresent;
            const isNeedleShape = rb.shape === "needle";
            if (rb.track.show && !hideTrack) {
                const elTracks = this.drawTracks({
                    size,
                    centerX,
                    centerY,
                    colorArr,
                    series
                });
                elSeries.add(elTracks);
            }
            if (hasBands) {
                const elBands = this.drawBands({
                    size,
                    centerX,
                    centerY,
                    series
                });
                elSeries.add(elBands);
            }
            const elG = this.drawArcs({
                size,
                centerX,
                centerY,
                colorArr,
                series,
                // When `needle.showValueArc` is true, render both the filled value-arc
                // and the needle on top — required for gauges that want a progress
                // ring with a pointer indicator (default still hides the arc when in
                // needle shape, preserving prior behavior).
                skipValueArc: isNeedleShape && !((_a = rb.needle) == null ? void 0 : _a.showValueArc)
            });
            if (rb.ticks && rb.ticks.show) {
                const elTicks = this.drawTicks({
                    size,
                    centerX,
                    centerY,
                    series
                });
                const isInitialMount = this.initialAnim && !w.globals.dataChanged && !w.globals.resized;
                if (isInitialMount && Environment.isBrowser() && w.globals.shouldAnimate) {
                    const ticksNode = elTicks.node;
                    ticksNode.style.opacity = "0";
                    ticksNode.style.transition = "opacity 280ms ease-out";
                    const sweepDur = w.config.chart.animations.speed || 800;
                    setTimeout(() => {
                        ticksNode.style.opacity = "1";
                    }, sweepDur);
                }
                elSeries.add(elTicks);
            }
            if (isNeedleShape) {
                const elNeedle = this.drawNeedle({
                    size,
                    centerX,
                    centerY,
                    series
                });
                elSeries.add(elNeedle);
            }
            let totalAngle = 360;
            if (w.config.plotOptions.radialBar.startAngle < 0) {
                totalAngle = this.totalAngle;
            }
            const angleRatio = (360 - totalAngle) / 360;
            w.globals.radialSize = size - size * angleRatio;
            if (this.radialDataLabels.value.show) {
                const offset = Math.max(
                    this.radialDataLabels.value.offsetY,
                    this.radialDataLabels.name.offsetY
                );
                w.globals.radialSize += offset * angleRatio;
            }
            elSeries.add(elG.g);
            if (w.config.plotOptions.radialBar.hollow.position === "front") {
                elG.g.add(elG.elHollow);
                if (elG.dataLabels) {
                    elG.g.add(elG.dataLabels);
                }
            }
            ret.add(elSeries);
            return ret;
        }
        /**
         * @param {Record<string, any>} opts
         */
        drawTracks(opts) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const g = graphics.group({
                class: "apexcharts-tracks"
            });
            const filters = new Filters(this.w);
            const fill = new Fill(this.w);
            const strokeWidth = this.getStrokeWidth(opts);
            opts.size = opts.size - strokeWidth / 2;
            for (let i = 0; i < opts.series.length; i++) {
                const elRadialBarTrack = graphics.group({
                    class: "apexcharts-radialbar-track apexcharts-track"
                });
                g.add(elRadialBarTrack);
                elRadialBarTrack.attr({
                    rel: i + 1
                });
                opts.size = opts.size - strokeWidth - this.margin;
                const trackConfig = w.config.plotOptions.radialBar.track;
                const pathFill = fill.fillPath({
                    seriesNumber: 0,
                    size: opts.size,
                    fillColors: Array.isArray(trackConfig.background) ? trackConfig.background[i] : trackConfig.background,
                    solid: true
                });
                const startAngle = this.trackStartAngle;
                let endAngle = this.trackEndAngle;
                if (Math.abs(endAngle) + Math.abs(startAngle) >= 360)
                    endAngle = 360 - Math.abs(this.startAngle) - 0.1;
                const elPath = graphics.drawPath({
                    d: "",
                    stroke: pathFill,
                    strokeWidth: strokeWidth * parseInt(trackConfig.strokeWidth, 10) / 100,
                    fill: "none",
                    strokeOpacity: trackConfig.opacity,
                    classes: "apexcharts-radialbar-area"
                });
                if (trackConfig.dropShadow.enabled) {
                    const shadow = trackConfig.dropShadow;
                    filters.dropShadow(elPath, shadow);
                }
                elRadialBarTrack.add(elPath);
                elPath.attr("id", "apexcharts-radialbarTrack-" + i);
                this.animatePaths(elPath, {
                    centerX: opts.centerX,
                    centerY: opts.centerY,
                    endAngle,
                    startAngle,
                    size: opts.size,
                    i,
                    totalItems: 2,
                    animBeginArr: 0,
                    dur: 0,
                    isTrack: true
                });
            }
            return g;
        }
        /**
         * @param {Record<string, any>} opts
         */
        drawArcs(opts) {
            var _a;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const fill = new Fill(this.w);
            const filters = new Filters(this.w);
            const g = graphics.group();
            const strokeWidth = this.getStrokeWidth(opts);
            opts.size = opts.size - strokeWidth / 2;
            let hollowFillID = w.config.plotOptions.radialBar.hollow.background;
            const hollowSize = opts.size - strokeWidth * opts.series.length - this.margin * opts.series.length - strokeWidth * parseInt(w.config.plotOptions.radialBar.track.strokeWidth, 10) / 100 / 2;
            const hollowRadius = hollowSize - w.config.plotOptions.radialBar.hollow.margin;
            if (w.config.plotOptions.radialBar.hollow.image !== void 0) {
                hollowFillID = this.drawHollowImage(opts, g, hollowSize, hollowFillID);
            }
            const elHollow = this.drawHollow({
                size: hollowRadius,
                centerX: opts.centerX,
                centerY: opts.centerY,
                fill: hollowFillID ? hollowFillID : "transparent"
            });
            if (w.config.plotOptions.radialBar.hollow.dropShadow.enabled) {
                const shadow = w.config.plotOptions.radialBar.hollow.dropShadow;
                filters.dropShadow(elHollow, shadow);
            }
            let shown = 1;
            if (!this.radialDataLabels.total.show && w.seriesData.series.length > 1) {
                shown = 0;
            }
            let dataLabels = null;
            if (this.radialDataLabels.show) {
                const dataLabelsGroup = w.dom.Paper.findOne(
                    `.apexcharts-datalabels-group`
                );
                dataLabels = this.renderInnerDataLabels(
                    dataLabelsGroup,
                    this.radialDataLabels, {
                        hollowSize,
                        centerX: opts.centerX,
                        centerY: opts.centerY,
                        opacity: shown
                    }
                );
            }
            if (w.config.plotOptions.radialBar.hollow.position === "back") {
                g.add(elHollow);
                if (dataLabels) {
                    g.add(dataLabels);
                }
            }
            let reverseLoop = false;
            if (w.config.plotOptions.radialBar.inverseOrder) {
                reverseLoop = true;
            }
            const morphActive = ((_a = this.ctx.morphTypeChange) == null ? void 0 : _a.isActive()) === true;
            for (let i = reverseLoop ? opts.series.length - 1 : 0; reverseLoop ? i >= 0 : i < opts.series.length; reverseLoop ? i-- : i++) {
                const elRadialBarArc = graphics.group({
                    class: `apexcharts-series apexcharts-radial-series`,
                    seriesName: Utils$1.escapeString(w.seriesData.seriesNames[i])
                });
                g.add(elRadialBarArc);
                elRadialBarArc.attr({
                    rel: i + 1,
                    "data:realIndex": i
                });
                Series.addCollapsedClassToSeries(this.w, elRadialBarArc, i);
                opts.size = opts.size - strokeWidth - this.margin;
                const pathFill = fill.fillPath({
                    seriesNumber: i,
                    size: opts.size,
                    value: opts.series[i]
                });
                const startAngle = this.startAngle;
                let prevStartAngle;
                const rb = w.config.plotOptions.radialBar;
                const domainMin = typeof rb.min === "number" ? rb.min : 0;
                const domainMax = typeof rb.max === "number" ? rb.max : 100;
                const domainSpan = domainMax === domainMin ? 1 : domainMax - domainMin;
                const valueToFraction = (v) => {
                    const clamped = Math.min(Math.max(v, domainMin), domainMax);
                    return Math.max(0, (clamped - domainMin) / domainSpan);
                };
                const dataValue = valueToFraction(Utils$1.negToZero(opts.series[i]));
                let endAngle = Math.round(this.totalAngle * dataValue) + this.startAngle;
                let prevEndAngle;
                if (w.globals.dataChanged) {
                    prevStartAngle = this.startAngle;
                    prevEndAngle = Math.round(
                        this.totalAngle * valueToFraction(Utils$1.negToZero(w.globals.previousPaths[i]))
                    ) + prevStartAngle;
                }
                const currFullAngle = Math.abs(endAngle) + Math.abs(startAngle);
                if (currFullAngle > 360) {
                    endAngle = endAngle - 0.01;
                }
                const prevFullAngle = Math.abs(prevEndAngle) + Math.abs(prevStartAngle);
                if (prevFullAngle > 360) {
                    prevEndAngle = prevEndAngle - 0.01;
                }
                const angle = endAngle - startAngle;
                const dashArray = Array.isArray(w.config.stroke.dashArray) ? w.config.stroke.dashArray[i] : w.config.stroke.dashArray;
                const morphFrom = morphActive ? this.ctx.morphTypeChange.getInitialPathFor(i, 0) : null;
                const morphFromType = morphActive ? this.ctx.morphTypeChange.getFromType() : null;
                const morphFromFilled = !!morphFrom && (morphFromType === "bar" || morphFromType === "funnel" || morphFromType === "pyramid" || morphFromType === "pie" || morphFromType === "donut" || morphFromType === "polarArea");
                const elPath = graphics.drawPath({
                    d: morphFrom || "",
                    stroke: morphFromFilled ? "transparent" : opts.skipValueArc ? "transparent" : pathFill,
                    strokeWidth: morphFromFilled ? 0 : opts.skipValueArc ? 0 : strokeWidth,
                    fill: morphFromFilled ? pathFill : "none",
                    fillOpacity: w.config.fill.opacity,
                    classes: "apexcharts-radialbar-area apexcharts-radialbar-slice-" + i,
                    strokeDashArray: dashArray
                });
                const radialMidAngle = startAngle + angle / 2;
                const radialArcCenter = Utils$1.polarToCartesian(
                    opts.centerX,
                    opts.centerY,
                    opts.size,
                    radialMidAngle
                );
                Graphics.setAttrs(elPath.node, {
                    "data:angle": angle,
                    "data:value": opts.series[i],
                    "data:cx": radialArcCenter.x,
                    "data:cy": radialArcCenter.y
                });
                if (w.config.chart.dropShadow.enabled) {
                    const shadow = w.config.chart.dropShadow;
                    filters.dropShadow(elPath, shadow, i);
                }
                filters.setSelectionFilter(elPath, 0, i);
                this.addListeners(elPath, this.radialDataLabels);
                elRadialBarArc.add(elPath);
                elPath.attr({
                    index: 0,
                    j: i
                });
                if (this.barLabels.enabled) {
                    const barStartCords = Utils$1.polarToCartesian(
                        opts.centerX,
                        opts.centerY,
                        opts.size,
                        startAngle
                    );
                    const text = this.barLabels.formatter(w.seriesData.seriesNames[i], {
                        seriesIndex: i,
                        w
                    });
                    const classes = ["apexcharts-radialbar-label"];
                    if (!this.barLabels.onClick) {
                        classes.push("apexcharts-no-click");
                    }
                    let textColor = this.barLabels.useSeriesColors ? w.globals.colors[i] : w.config.chart.foreColor;
                    if (!textColor) {
                        textColor = w.config.chart.foreColor;
                    }
                    const x = barStartCords.x + this.barLabels.offsetX;
                    const y = barStartCords.y + this.barLabels.offsetY;
                    const elText = graphics.drawText({
                        x,
                        y,
                        text,
                        textAnchor: "end",
                        dominantBaseline: "middle",
                        fontFamily: this.barLabels.fontFamily,
                        fontWeight: this.barLabels.fontWeight,
                        fontSize: this.barLabels.fontSize,
                        foreColor: textColor,
                        cssClass: classes.join(" ")
                    });
                    elText.on("click", this.onBarLabelClick);
                    elText.attr({
                        rel: i + 1
                    });
                    if (startAngle !== 0) {
                        elText.attr({
                            "transform-origin": `${x} ${y}`,
                            transform: `rotate(${startAngle} 0 0)`
                        });
                    }
                    elRadialBarArc.add(elText);
                }
                let dur = 0;
                if (this.initialAnim && !w.globals.resized && !w.globals.dataChanged) {
                    dur = w.config.chart.animations.speed;
                }
                if (w.globals.dataChanged) {
                    dur = w.config.chart.animations.dynamicAnimation.speed;
                }
                this.animDur = dur / (opts.series.length * 1.2) + this.animDur;
                this.animBeginArr.push(this.animDur);
                if (morphActive && morphFrom) {
                    const morphSpeed = this.ctx.morphTypeChange.getSpeed();
                    const actualArcD = this.getPiePath({
                        me: this,
                        startAngle,
                        angle,
                        size: opts.size
                    });
                    if (morphFromFilled) {
                        const targetD = this.ctx.morphTypeChange.buildRingSegmentPath(
                            opts.centerX,
                            opts.centerY,
                            opts.size,
                            strokeWidth,
                            startAngle,
                            startAngle + angle
                        );
                        elPath.animate(morphSpeed).plot(targetD, "polygons").after(
                            /** @this {any} */
                            function() {
                                this.attr({
                                    d: actualArcD,
                                    fill: "none",
                                    stroke: opts.skipValueArc ? "transparent" : pathFill,
                                    "stroke-width": opts.skipValueArc ? 0 : strokeWidth
                                });
                            }
                        );
                    } else {
                        elPath.animate(morphSpeed).plot(actualArcD, "polygons").attr({
                            "stroke-width": strokeWidth
                        });
                    }
                } else {
                    this.animatePaths(elPath, {
                        centerX: opts.centerX,
                        centerY: opts.centerY,
                        endAngle,
                        startAngle,
                        prevEndAngle,
                        prevStartAngle,
                        size: opts.size,
                        i,
                        totalItems: 2,
                        animBeginArr: this.animBeginArr,
                        dur,
                        shouldSetPrevPaths: true
                    });
                }
            }
            return {
                g,
                elHollow,
                dataLabels
            };
        }
        /**
         * Map a domain value (between `min` and `max`) to the corresponding angle
         * in the gauge's `startAngle`..`endAngle` range. Values outside the
         * domain are clamped.
         *
         * @param {number} value
         * @returns {number}
         */
        _angleAtValue(value) {
            const rb = this.w.config.plotOptions.radialBar;
            const min = typeof rb.min === "number" ? rb.min : 0;
            const max = typeof rb.max === "number" ? rb.max : 100;
            const safeMax = max === min ? min + 1 : max;
            const clamped = Math.max(min, Math.min(safeMax, Number(value)));
            const t = (clamped - min) / (safeMax - min);
            return this.startAngle + t * (this.endAngle - this.startAngle);
        }
        /**
         * Build an SVG arc path from `startAngle` to `endAngle` at radius `r`
         * around `(cx, cy)`. Angles are in degrees, with 0° at the top.
         * Used by drawBands; mirrors the `M ... A ... ` form used elsewhere.
         *
         * @param {number} cx
         * @param {number} cy
         * @param {number} r
         * @param {number} startAngle
         * @param {number} endAngle
         * @returns {string}
         */
        _describeArc(cx, cy, r, startAngle, endAngle) {
            const start = Utils$1.polarToCartesian(cx, cy, r, endAngle);
            const end = Utils$1.polarToCartesian(cx, cy, r, startAngle);
            const sweep = endAngle - startAngle;
            const largeArc = Math.abs(sweep) > 180 ? 1 : 0;
            return `M ${start.x} ${start.y} A ${r} ${r} 0 ${largeArc} 0 ${end.x} ${end.y}`;
        }
        /**
         * Draw threshold bands as colored arc segments along the gauge arc.
         * Bands sit behind the value-arc and tick marks. Used for gauges that
         * indicate ranges like 0-30 critical / 30-70 warning / 70-100 healthy.
         *
         * @param {Record<string, any>} opts
         */
        drawBands(opts) {
            const w = this.w;
            const graphics = new Graphics(this.w);
            const rb = w.config.plotOptions.radialBar;
            const bands = rb.bands || [];
            const g = graphics.group({
                class: "apexcharts-gauge-bands"
            });
            const strokeWidth = this.getStrokeWidth(opts);
            const radius = opts.size - strokeWidth / 2 - strokeWidth - this.margin;
            const bandStroke = strokeWidth * parseInt(rb.bandsStyle.strokeWidth, 10) / 100;
            const min = typeof rb.min === "number" ? rb.min : 0;
            const max = typeof rb.max === "number" ? rb.max : 100;
            const gapDeg = max === min ? 0 : (rb.bandsStyle.gap || 0) * ((this.endAngle - this.startAngle) / (max - min));
            for (let b = 0; b < bands.length; b++) {
                const band = bands[b];
                if (band.from === void 0 || band.to === void 0) continue;
                const a1 = this._angleAtValue(band.from);
                const a2 = this._angleAtValue(band.to);
                const startA = Math.min(a1, a2) + gapDeg / 2;
                const endA = Math.max(a1, a2) - gapDeg / 2;
                if (endA - startA <= 0) continue;
                const elBand = graphics.drawPath({
                    d: this._describeArc(opts.centerX, opts.centerY, radius, startA, endA),
                    stroke: band.color || "#ccc",
                    strokeWidth: bandStroke,
                    fill: "none",
                    strokeLinecap: rb.bandsStyle.linecap || "butt",
                    classes: "apexcharts-gauge-band"
                });
                elBand.node.setAttribute("data-band-index", String(b));
                g.add(elBand);
            }
            return g;
        }
        /**
         * Draw tick marks (major + minor) along the gauge arc, with optional
         * value labels at each major tick.
         *
         * @param {Record<string, any>} opts
         */
        drawTicks(opts) {
            var _a, _b, _c, _d;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const rb = w.config.plotOptions.radialBar;
            const ticks = rb.ticks;
            const g = graphics.group({
                class: "apexcharts-gauge-ticks"
            });
            const strokeWidth = this.getStrokeWidth(opts);
            const radius = opts.size - strokeWidth / 2 - strokeWidth - this.margin;
            const min = typeof rb.min === "number" ? rb.min : 0;
            const max = typeof rb.max === "number" ? rb.max : 100;
            const majorCount = Math.max(2, (_b = (_a = ticks.major) == null ? void 0 : _a.count) != null ? _b : 11);
            const minorCount = Math.max(0, (_d = (_c = ticks.minor) == null ? void 0 : _c.count) != null ? _d : 0);
            const drawTickAt = (value, cfg, isMajor) => {
                var _a2, _b2, _c2;
                const angle = this._angleAtValue(value);
                const length = (_a2 = cfg.length) != null ? _a2 : 8;
                const inner = cfg.placement === "inside" ? radius - length : radius;
                const outer = cfg.placement === "inside" ? radius : radius + length;
                const p1 = Utils$1.polarToCartesian(
                    opts.centerX,
                    opts.centerY,
                    inner,
                    angle
                );
                const p2 = Utils$1.polarToCartesian(
                    opts.centerX,
                    opts.centerY,
                    outer,
                    angle
                );
                const line = graphics.drawLine(
                    p1.x,
                    p1.y,
                    p2.x,
                    p2.y,
                    cfg.color || (isMajor ? "#666" : "#999"),
                    0,
                    cfg.width || (isMajor ? 2 : 1)
                );
                g.add(line);
                if (isMajor && ((_b2 = ticks.labels) == null ? void 0 : _b2.show)) {
                    const labelRadius = (cfg.placement === "inside" ? inner : outer) + (cfg.placement === "inside" ? -1 : 1) * ((_c2 = ticks.labels.offset) != null ? _c2 : 6);
                    const labelPos = Utils$1.polarToCartesian(
                        opts.centerX,
                        opts.centerY,
                        labelRadius,
                        angle
                    );
                    const labelText = typeof ticks.labels.formatter === "function" ? ticks.labels.formatter(value) : String(value);
                    const elText = graphics.drawText({
                        x: labelPos.x,
                        y: labelPos.y,
                        text: labelText,
                        textAnchor: "middle",
                        dominantBaseline: "middle",
                        fontFamily: ticks.labels.fontFamily,
                        fontSize: ticks.labels.fontSize,
                        fontWeight: ticks.labels.fontWeight,
                        foreColor: ticks.labels.color,
                        cssClass: "apexcharts-gauge-tick-label"
                    });
                    g.add(elText);
                }
            };
            for (let m = 0; m < majorCount; m++) {
                const t = m / (majorCount - 1);
                const value = min + t * (max - min);
                drawTickAt(value, ticks.major || {}, true);
                if (m < majorCount - 1 && minorCount > 0) {
                    for (let n = 1; n <= minorCount; n++) {
                        const tMinor = (m + n / (minorCount + 1)) / (majorCount - 1);
                        const minorValue = min + tMinor * (max - min);
                        drawTickAt(minorValue, ticks.minor || {}, false);
                    }
                }
            }
            return g;
        }
        /**
         * Draw a rotating needle pointing at the current series value. Only
         * called when `plotOptions.radialBar.shape === 'needle'`. The needle is
         * a tapered polygon inside a `<g>` whose rotation transform is animated
         * from `startAngle` to the value's angle.
         *
         * Renders a single needle for the first series value (gauge use case).
         * Additional series are ignored — drilled-down multi-series gauges are
         * out of scope for this iteration.
         *
         * @param {Record<string, any>} opts
         */
        drawNeedle(opts) {
            var _a, _b, _c, _d, _e;
            const w = this.w;
            const graphics = new Graphics(this.w);
            const rb = w.config.plotOptions.radialBar;
            const cfg = rb.needle || {};
            const g = graphics.group({
                class: "apexcharts-gauge-needle"
            });
            if (!opts.series || opts.series.length === 0) return g;
            const strokeWidth = this.getStrokeWidth(opts);
            const arcRadius = opts.size - strokeWidth / 2 - strokeWidth - this.margin;
            const length = typeof cfg.length === "string" && cfg.length.endsWith("%") ? arcRadius * parseInt(cfg.length, 10) / 100 : Number(cfg.length || arcRadius * 0.85);
            const baseW = (_a = cfg.baseWidth) != null ? _a : 4;
            const tipW = (_b = cfg.tipWidth) != null ? _b : 1;
            const color = cfg.color || "#333";
            const cx = opts.centerX;
            const needleOffsetY = Number((_c = cfg.offsetY) != null ? _c : 0);
            const cy = opts.centerY + needleOffsetY;
            const path = `M ${cx + baseW / 2} ${cy} A ${baseW / 2} ${baseW / 2} 0 0 1 ${cx - baseW / 2} ${cy} L ${cx - tipW / 2} ${cy - length} L ${cx + tipW / 2} ${cy - length} Z`;
            const elNeedle = graphics.drawPath({
                d: path,
                stroke: color,
                strokeWidth: 0,
                fill: color,
                classes: "apexcharts-gauge-needle-shape"
            });
            g.add(elNeedle);
            const value = Number(opts.series[0]);
            const targetAngle = this._angleAtValue(value);
            const isInitialMount = this.initialAnim && !w.globals.dataChanged && !w.globals.resized;
            const ctx = (
                /** @type {any} */
                this.ctx
            );
            const fromAngle = typeof ctx._lastNeedleAngle === "number" ? ctx._lastNeedleAngle : this.startAngle;
            ctx._lastNeedleAngle = targetAngle;
            const shouldAnimate = Environment.isBrowser() && w.globals.shouldAnimate && (isInitialMount || w.globals.dataChanged);
            if (shouldAnimate && fromAngle !== targetAngle) {
                const node = g.node;
                node.setAttribute("transform-origin", `${cx} ${cy}`);
                node.setAttribute("transform", `rotate(${fromAngle})`);
                const speed = ((_d = cfg.animation) == null ? void 0 : _d.duration) && Number(cfg.animation.duration) || cfg.animationSpeed && Number(cfg.animationSpeed) || ((_e = w.config.chart.animations.dynamicAnimation) == null ? void 0 : _e.speed) || w.config.chart.animations.speed || 800;
                const c1 = 1.70158;
                const c3 = c1 + 1;
                const easeOutBack2 = (t) => 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
                const easeOutCubic2 = (t) => 1 - Math.pow(1 - t, 3);
                const ease = isInitialMount ? easeOutBack2 : easeOutCubic2;
                const startAt = performance.now();
                const step = (now) => {
                    const t = Math.max(0, Math.min(1, (now - startAt) / speed));
                    const angle = fromAngle + (targetAngle - fromAngle) * ease(t);
                    node.setAttribute("transform", `rotate(${angle})`);
                    if (t < 1) BrowserAPIs.requestAnimationFrame(step);
                };
                BrowserAPIs.requestAnimationFrame(step);
            } else {
                g.attr({
                    "transform-origin": `${cx} ${cy}`,
                    transform: `rotate(${targetAngle})`
                });
            }
            return g;
        }
        /**
         * @param {Record<string, any>} opts
         */
        drawHollow(opts) {
            var _a;
            const graphics = new Graphics(this.w);
            const hollow = this.w.config.plotOptions.radialBar.hollow;
            const circle = graphics.drawCircle(opts.size * 2);
            const attrs = {
                class: "apexcharts-radialbar-hollow",
                cx: opts.centerX,
                cy: opts.centerY,
                r: opts.size,
                fill: opts.fill
            };
            if (hollow.stroke || hollow.strokeDasharray) {
                attrs.stroke = hollow.stroke || "transparent";
                attrs["stroke-width"] = (_a = hollow.strokeWidth) != null ? _a : 1;
                if (hollow.strokeDasharray) {
                    attrs["stroke-dasharray"] = hollow.strokeDasharray;
                }
            }
            circle.attr(attrs);
            return circle;
        }
        /**
         * @param {Record<string, any>} opts
         * @param {any} g
         * @param {number} hollowSize
         * @param {string} hollowFillID
         */
        drawHollowImage(opts, g, hollowSize, hollowFillID) {
            const w = this.w;
            const fill = new Fill(this.w);
            const randID = Utils$1.randomId();
            const hollowFillImg = w.config.plotOptions.radialBar.hollow.image;
            if (w.config.plotOptions.radialBar.hollow.imageClipped) {
                fill.clippedImgArea({
                    width: hollowSize,
                    height: hollowSize,
                    image: hollowFillImg,
                    patternID: `pattern${w.globals.cuid}${randID}`
                });
                hollowFillID = `url(#pattern${w.globals.cuid}${randID})`;
            } else {
                const imgWidth = w.config.plotOptions.radialBar.hollow.imageWidth;
                const imgHeight = w.config.plotOptions.radialBar.hollow.imageHeight;
                if (imgWidth === void 0 && imgHeight === void 0) {
                    const image = w.dom.Paper.image(
                        hollowFillImg,
                        /** @this {any} */
                        function(loader) {
                            this.move(
                                opts.centerX - loader.width / 2 + w.config.plotOptions.radialBar.hollow.imageOffsetX,
                                opts.centerY - loader.height / 2 + w.config.plotOptions.radialBar.hollow.imageOffsetY
                            );
                        }
                    );
                    g.add(image);
                } else {
                    const image = w.dom.Paper.image(
                        hollowFillImg,
                        /** @this {any} */
                        function() {
                            this.move(
                                opts.centerX - imgWidth / 2 + w.config.plotOptions.radialBar.hollow.imageOffsetX,
                                opts.centerY - imgHeight / 2 + w.config.plotOptions.radialBar.hollow.imageOffsetY
                            );
                            this.size(imgWidth, imgHeight);
                        }
                    );
                    g.add(image);
                }
            }
            return hollowFillID;
        }
        /**
         * @param {Record<string, any>} opts
         */
        getStrokeWidth(opts) {
            const w = this.w;
            return opts.size * (100 - parseInt(w.config.plotOptions.radialBar.hollow.size, 10)) / 100 / (opts.series.length + 1) - this.margin;
        }
        /**
         * @param {Event} e
         */
        onBarLabelClick(e) {
            var _a;
            const target = (
                /** @type {Element} */
                e.target
            );
            const seriesIndex = parseInt((_a = target.getAttribute("rel")) != null ? _a : "", 10) - 1;
            const legendClick = this.barLabels.onClick;
            const w = this.w;
            if (legendClick) {
                legendClick(w.seriesData.seriesNames[seriesIndex], {
                    w,
                    seriesIndex
                });
            }
        }
    }
    class RangeBar extends Bar {
        /**
         * @param {any[]} series
         * @param {number} seriesIndex
         */
        draw(series, seriesIndex) {
            var _a, _b, _c, _d, _e, _f, _g, _h, _i;
            const w = this.w;
            const graphics = new Graphics(this.w);
            this.rangeBarOptions = this.w.config.plotOptions.rangeBar;
            this.series = series;
            this.seriesRangeStart = w.rangeData.seriesRangeStart;
            this.seriesRangeEnd = w.rangeData.seriesRangeEnd;
            this.barHelpers.initVariables(series);
            const ret = graphics.group({
                class: "apexcharts-rangebar-series apexcharts-plot-series"
            });
            for (let i = 0; i < series.length; i++) {
                let x, y;
                const realIndex = w.globals.comboCharts ? (
                    /** @type {any} */
                    seriesIndex[i]
                ) : i;
                const {
                    columnGroupIndex
                } = this.barHelpers.getGroupIndex(realIndex);
                const elSeries = graphics.group({
                    class: `apexcharts-series`,
                    seriesName: Utils$1.escapeString(w.seriesData.seriesNames[realIndex]),
                    rel: i + 1,
                    "data:realIndex": realIndex
                });
                Series.addCollapsedClassToSeries(this.w, elSeries, realIndex);
                if (series[i].length > 0) {
                    this.visibleI = this.visibleI + 1;
                }
                let translationsIndex = 0;
                if (this.yRatio.length > 1) {
                    this.yaxisIndex = /** @type {any} */
                        w.globals.seriesYAxisReverseMap[realIndex][0];
                    translationsIndex = realIndex;
                }
                const initPositions = this.barHelpers.initialPositions(realIndex);
                const {
                    y: initY,
                    zeroW,
                    // zeroW is the baseline where 0 meets x axis
                    x: initX,
                    zeroH
                    // zeroH is the baseline where 0 meets y axis
                } = initPositions;
                let barWidth = (_a = initPositions.barWidth) != null ? _a : 0;
                let barHeight = (_b = initPositions.barHeight) != null ? _b : 0;
                const yDivision = (_c = initPositions.yDivision) != null ? _c : 0;
                const xDivision = (_d = initPositions.xDivision) != null ? _d : 0;
                y = initY;
                x = initX;
                const elDataLabelsWrap = graphics.group({
                    class: "apexcharts-datalabels",
                    "data:realIndex": realIndex
                });
                const elGoalsMarkers = graphics.group({
                    class: "apexcharts-rangebar-goals-markers"
                });
                for (let j = 0; j < w.globals.dataPoints; j++) {
                    const strokeWidth = this.barHelpers.getStrokeWidth(i, j, realIndex);
                    const y1 = this.seriesRangeStart[i][j];
                    const y2 = this.seriesRangeEnd[i][j];
                    let paths = (
                        /** @type {any} */
                        null
                    );
                    let barXPosition = null;
                    let barYPosition = null;
                    const params = {
                        x,
                        y,
                        strokeWidth,
                        elSeries
                    };
                    let seriesLen = this.seriesLen;
                    if (w.config.plotOptions.bar.rangeBarGroupRows) {
                        seriesLen = 1;
                    }
                    if (typeof /** @type {Record<string,any>} */((_e = w.config.series[i].data) == null ? void 0 : _e[j]) === "undefined") {
                        break;
                    }
                    if (this.isHorizontal) {
                        barYPosition = y + barHeight * /** @type {any} */
                            this.visibleI;
                        const srty = (yDivision - barHeight * seriesLen) / 2;
                        if (
                            /** @type {Record<string,any>} */
                            (_g = (_f = w.config.series[i].data) == null ? void 0 : _f[j]) == null ? void 0 : _g.x
                        ) {
                            const positions = this.detectOverlappingBars({
                                i,
                                j,
                                barYPosition,
                                srty,
                                barHeight,
                                yDivision,
                                initPositions
                            });
                            barHeight = positions.barHeight;
                            barYPosition = positions.barYPosition;
                        }
                        paths = this.drawRangeBarPaths(__spreadValues({
                            indexes: {
                                i,
                                j,
                                realIndex
                            },
                            barHeight,
                            barYPosition,
                            zeroW,
                            yDivision,
                            y1,
                            y2
                        }, params));
                        barWidth = paths.barWidth;
                    } else {
                        if (w.axisFlags.isXNumeric) {
                            x = (w.seriesData.seriesX[i][j] - w.globals.minX) / this.xRatio - barWidth / 2;
                        }
                        barXPosition = x + barWidth * /** @type {any} */
                            this.visibleI;
                        const srtx = (xDivision - barWidth * seriesLen) / 2;
                        if (
                            /** @type {Record<string,any>} */
                            (_i = (_h = w.config.series[i].data) == null ? void 0 : _h[j]) == null ? void 0 : _i.x
                        ) {
                            const positions = this.detectOverlappingBars({
                                i,
                                j,
                                barXPosition,
                                srtx,
                                barWidth,
                                xDivision,
                                initPositions
                            });
                            barWidth = positions.barWidth;
                            barXPosition = positions.barXPosition;
                        }
                        paths = this.drawRangeColumnPaths(__spreadValues({
                            indexes: {
                                i,
                                j,
                                realIndex,
                                translationsIndex
                            },
                            barWidth,
                            barXPosition,
                            zeroH,
                            xDivision
                        }, params));
                        barHeight = paths.barHeight;
                    }
                    const barGoalLine = this.barHelpers.drawGoalLine({
                        barXPosition: paths.barXPosition,
                        barYPosition,
                        goalX: paths.goalX,
                        goalY: paths.goalY,
                        barHeight,
                        barWidth
                    });
                    if (barGoalLine) {
                        elGoalsMarkers.add(barGoalLine);
                    }
                    y = paths.y;
                    x = paths.x;
                    const pathFill = this.barHelpers.getPathFillColor(
                        series,
                        i,
                        j,
                        realIndex
                    );
                    this.renderSeries({
                        realIndex,
                        pathFill: pathFill.color,
                        lineFill: pathFill.useRangeColor ? pathFill.color : w.globals.stroke.colors[realIndex],
                        j,
                        i,
                        x,
                        y,
                        y1,
                        y2,
                        pathFrom: paths.pathFrom,
                        pathTo: paths.pathTo,
                        strokeWidth,
                        elSeries,
                        series,
                        barHeight,
                        barWidth,
                        barXPosition,
                        barYPosition,
                        columnGroupIndex,
                        elDataLabelsWrap,
                        elGoalsMarkers,
                        visibleSeries: this.visibleI,
                        type: "rangebar"
                    });
                }
                ret.add(elSeries);
            }
            return ret;
        }
        /** @param {{ i?: any, j?: any, barYPosition?: any, barXPosition?: any, srty?: any, srtx?: any, barHeight?: any, barWidth?: any, yDivision?: any, xDivision?: any, initPositions?: any }} opts */
        detectOverlappingBars({
            i,
            j,
            barYPosition,
            barXPosition,
            srty,
            srtx,
            barHeight,
            barWidth,
            yDivision,
            xDivision,
            initPositions
        }) {
            var _a, _b, _c, _d;
            const w = this.w;
            let overlaps = [];
            const rangeName = (
                /** @type {Record<string,any>} */
                (_b = (_a = w.config.series[i].data) == null ? void 0 : _a[j]) == null ? void 0 : _b.rangeName
            );
            const x = (
                /** @type {Record<string,any>} */
                (_d = (_c = w.config.series[i].data) == null ? void 0 : _c[j]) == null ? void 0 : _d.x
            );
            const labelX = Array.isArray(x) ? x.join(" ") : x;
            const rowIndex = w.labelData.labels.map((_) => Array.isArray(_) ? _.join(" ") : _).indexOf(labelX);
            const overlappedIndex = w.rangeData.seriesRange[i].findIndex(
                (tx) => {
                    var _a2;
                    return tx.x === labelX && ((_a2 = tx.overlaps) == null ? void 0 : _a2.size) > 0;
                }
            );
            if (this.isHorizontal) {
                if (w.config.plotOptions.bar.rangeBarGroupRows) {
                    barYPosition = srty + yDivision * rowIndex;
                } else {
                    barYPosition = srty + barHeight * this.visibleI + yDivision * rowIndex;
                }
                if (overlappedIndex > -1 && !w.config.plotOptions.bar.rangeBarOverlap) {
                    overlaps = Array.from(
                        /** @type {any} */
                        w.rangeData.seriesRange[i][overlappedIndex].overlaps
                    );
                    if (overlaps.indexOf(rangeName) > -1) {
                        barHeight = initPositions.barHeight / overlaps.length;
                        barYPosition = barHeight * this.visibleI + yDivision * (100 - parseInt(this.barOptions.barHeight, 10)) / 100 / 2 + barHeight * (this.visibleI + overlaps.indexOf(rangeName)) + yDivision * rowIndex;
                    }
                }
            } else {
                if (rowIndex > -1 && !w.labelData.timescaleLabels.length) {
                    if (w.config.plotOptions.bar.rangeBarGroupRows) {
                        barXPosition = srtx + xDivision * rowIndex;
                    } else {
                        barXPosition = srtx + barWidth * this.visibleI + xDivision * rowIndex;
                    }
                }
                if (overlappedIndex > -1 && !w.config.plotOptions.bar.rangeBarOverlap) {
                    overlaps = Array.from(
                        /** @type {any} */
                        w.rangeData.seriesRange[i][overlappedIndex].overlaps
                    );
                    if (overlaps.indexOf(rangeName) > -1) {
                        barWidth = initPositions.barWidth / overlaps.length;
                        barXPosition = barWidth * this.visibleI + xDivision * (100 - parseInt(this.barOptions.barWidth, 10)) / 100 / 2 + barWidth * (this.visibleI + overlaps.indexOf(rangeName)) + xDivision * rowIndex;
                    }
                }
            }
            return {
                barYPosition,
                barXPosition,
                barHeight,
                barWidth
            };
        }
        /** @param {{indexes: any, x: any, xDivision: any, barWidth: any, barXPosition: any, zeroH: any}} opts */
        drawRangeColumnPaths({
            indexes,
            x,
            xDivision,
            barWidth,
            barXPosition,
            zeroH
        }) {
            var _a, _b;
            const w = this.w;
            const {
                i,
                j,
                realIndex,
                translationsIndex
            } = indexes;
            const yRatio = this.yRatio[translationsIndex];
            const range = this.getRangeValue(realIndex, j);
            let y1 = Math.min(range.start, range.end);
            let y2 = Math.max(range.start, range.end);
            if (typeof /** @type {any} */((_a = this.series[i]) == null ? void 0 : _a[j]) === "undefined" || /** @type {any} */
                ((_b = this.series[i]) == null ? void 0 : _b[j]) === null) {
                y1 = zeroH;
            } else {
                y1 = zeroH - y1 / yRatio;
                y2 = zeroH - y2 / yRatio;
            }
            const barHeight = Math.abs(y2 - y1);
            const paths = this.barHelpers.getColumnPaths({
                barXPosition,
                barWidth,
                y1,
                y2,
                strokeWidth: this.strokeWidth,
                series: this.seriesRangeEnd,
                realIndex,
                i: realIndex,
                j,
                w
            });
            if (!w.axisFlags.isXNumeric) {
                x = x + xDivision;
            } else {
                const xForNumericXAxis = this.getBarXForNumericXAxis({
                    x,
                    j,
                    realIndex,
                    barWidth
                });
                x = xForNumericXAxis.x;
                barXPosition = xForNumericXAxis.barXPosition;
            }
            return {
                pathTo: paths.pathTo,
                pathFrom: paths.pathFrom,
                barHeight,
                x,
                y: range.start < 0 && range.end < 0 ? y1 : y2,
                goalY: this.barHelpers.getGoalValues(
                    "y",
                    /** @type {any} */
                    null,
                    zeroH,
                    i,
                    j,
                    translationsIndex
                ),
                barXPosition
            };
        }
        /**
         * @param {number} val
         */
        preventBarOverflow(val) {
            const w = this.w;
            if (val < 0) {
                val = 0;
            }
            if (val > w.layout.gridWidth) {
                val = w.layout.gridWidth;
            }
            return val;
        }
        /** @param {{indexes: any, y: any, y1: any, y2: any, yDivision: any, barHeight: any, barYPosition: any, zeroW: any}} opts */
        drawRangeBarPaths({
            indexes,
            y,
            y1,
            y2,
            yDivision,
            barHeight,
            barYPosition,
            zeroW
        }) {
            const w = this.w;
            const {
                realIndex,
                j
            } = indexes;
            const x1 = this.preventBarOverflow(zeroW + y1 / this.invertedYRatio);
            const x2 = this.preventBarOverflow(zeroW + y2 / this.invertedYRatio);
            const range = this.getRangeValue(realIndex, j);
            const barWidth = Math.abs(x2 - x1);
            const paths = this.barHelpers.getBarpaths({
                barYPosition,
                barHeight,
                x1,
                x2,
                strokeWidth: this.strokeWidth,
                series: this.seriesRangeEnd,
                i: realIndex,
                realIndex,
                j,
                w
            });
            if (!w.axisFlags.isXNumeric) {
                y = y + yDivision;
            }
            return {
                pathTo: paths.pathTo,
                pathFrom: paths.pathFrom,
                barWidth,
                x: range.start < 0 && range.end < 0 ? x1 : x2,
                goalX: this.barHelpers.getGoalValues(
                    "x",
                    zeroW,
                    /** @type {any} */
                    null,
                    realIndex,
                    j,
                    0
                ),
                y
            };
        }
        /**
         * @param {number} i
         * @param {number} j
         */
        getRangeValue(i, j) {
            const w = this.w;
            return {
                start: w.rangeData.seriesRangeStart[i][j],
                end: w.rangeData.seriesRangeEnd[i][j]
            };
        }
    }

    function normalize(data, area) {
        let sum = 0;
        for (let i = 0; i < data.length; i++) {
            sum += data[i];
        }
        const multiplier = area / sum;
        const result = new Array(data.length);
        for (let i = 0; i < data.length; i++) {
            result[i] = data[i] * multiplier;
        }
        return result;
    }

    function calculateRatio(rowMin, rowMax, rowSum, length) {
        const lengthSq = length * length;
        const sumSq = rowSum * rowSum;
        return Math.max(
            lengthSq * rowMax / sumSq,
            sumSq / (lengthSq * rowMin)
        );
    }

    function improvesRatio(rowLen, rowMin, rowMax, rowSum, nextNode, length) {
        if (rowLen === 0) return true;
        const currentRatio = calculateRatio(rowMin, rowMax, rowSum, length);
        const newRatio = calculateRatio(
            Math.min(rowMin, nextNode),
            Math.max(rowMax, nextNode),
            rowSum + nextNode,
            length
        );
        return currentRatio >= newRatio;
    }

    function emitCoordinates(coords, row, rowLen, rowSum, xoffset, yoffset, width, height) {
        if (width >= height) {
            const areaWidth = rowSum / height;
            let subY = yoffset;
            for (let i = 0; i < rowLen; i++) {
                const h = row[i] / areaWidth;
                coords.push([xoffset, subY, xoffset + areaWidth, subY + h]);
                subY += h;
            }
        } else {
            const areaHeight = rowSum / width;
            let subX = xoffset;
            for (let i = 0; i < rowLen; i++) {
                const w = row[i] / areaHeight;
                coords.push([subX, yoffset, subX + w, yoffset + areaHeight]);
                subX += w;
            }
        }
    }

    function squarify(data, xoffset, yoffset, width, height) {
        const coords = [];
        const n = data.length;
        if (n === 0) return coords;
        const row = new Array(n);
        let rowLen = 0;
        let rowSum = 0;
        let rowMin = Infinity;
        let rowMax = -Infinity;
        let i = 0;
        while (i < n) {
            const length = Math.min(width, height);
            const val = data[i];
            if (improvesRatio(rowLen, rowMin, rowMax, rowSum, val, length)) {
                row[rowLen] = val;
                rowLen++;
                rowSum += val;
                if (val < rowMin) rowMin = val;
                if (val > rowMax) rowMax = val;
                i++;
            } else {
                emitCoordinates(coords, row, rowLen, rowSum, xoffset, yoffset, width, height);
                if (width >= height) {
                    const areaWidth = rowSum / height;
                    xoffset += areaWidth;
                    width -= areaWidth;
                } else {
                    const areaHeight = rowSum / width;
                    yoffset += areaHeight;
                    height -= areaHeight;
                }
                rowLen = 0;
                rowSum = 0;
                rowMin = Infinity;
                rowMax = -Infinity;
            }
        }
        if (rowLen > 0) {
            emitCoordinates(coords, row, rowLen, rowSum, xoffset, yoffset, width, height);
        }
        return coords;
    }

    function generate(data, width, height) {
        const n = data.length;
        const sums = new Array(n);
        for (let i = 0; i < n; i++) {
            let s = 0;
            const series = data[i];
            for (let j = 0; j < series.length; j++) {
                s += series[j];
            }
            sums[i] = s;
        }
        const seriesRects = squarify(
            normalize(sums, width * height),
            0,
            0,
            width,
            height
        );
        const results = new Array(n);
        for (let i = 0; i < n; i++) {
            const rect = seriesRects[i];
            const rx = rect[0];
            const ry = rect[1];
            const rw = rect[2] - rx;
            const rh = rect[3] - ry;
            results[i] = squarify(
                normalize(data[i], rw * rh),
                rx,
                ry,
                rw,
                rh
            );
        }
        return results;
    }
    const TreemapSquared = {
        generate
    };
    class TreemapChart {
        /**
         * @param {import('../types/internal').ChartStateW} w
         * @param {import('../types/internal').ChartContext} ctx
         */
        constructor(w, ctx) {
            this.ctx = ctx;
            this.w = w;
            this.strokeWidth = this.w.config.stroke.width;
            this.helpers = new TreemapHelpers(w, ctx);
            this.dynamicAnim = this.w.config.chart.animations.dynamicAnimation;
            this.labels = [];
        }
        /**
         * @param {any[]} series
         */
        draw(series) {
            const w = this.w;
            const graphics = new Graphics(this.w, this.ctx);
            const fill = new Fill(this.w);
            const ret = graphics.group({
                class: "apexcharts-treemap"
            });
            if (w.globals.noData) return ret;
            const ser = [];
            series.forEach((s) => {
                const d = s.map((v) => {
                    return Math.abs(v);
                });
                ser.push(d);
            });
            this.negRange = this.helpers.checkColorRange();
            w.config.series.forEach((s, i) => {
                s.data.forEach((l) => {
                    if (!Array.isArray(this.labels[i])) this.labels[i] = [];
                    this.labels[i].push(l.x);
                });
            });
            const nodes = TreemapSquared.generate(
                ser,
                w.layout.gridWidth,
                w.layout.gridHeight
            );
            nodes.forEach((node, i) => {
                var _a;
                const elSeries = graphics.group({
                    class: `apexcharts-series apexcharts-treemap-series`,
                    seriesName: Utils$1.escapeString(w.seriesData.seriesNames[i]),
                    rel: i + 1,
                    "data:realIndex": i
                });
                graphics.setupEventDelegation(elSeries, ".apexcharts-treemap-rect");
                if (w.config.chart.dropShadow.enabled) {
                    const shadow = w.config.chart.dropShadow;
                    const filters = new Filters(this.w);
                    filters.dropShadow(ret, shadow, i);
                }
                const elDataLabelWrap = graphics.group({
                    class: "apexcharts-data-labels"
                });
                const bounds = {
                    xMin: Infinity,
                    yMin: Infinity,
                    xMax: -Infinity,
                    yMax: -Infinity
                };
                const animCfg = w.config.chart.animations;
                const gradCfg = animCfg.animateGradually;
                const cascadeEnabled = gradCfg && gradCfg.enabled !== false;
                const cascadeDelays = new Array(node.length).fill(0);
                if (cascadeEnabled) {
                    const tileCount = node.length || 1;
                    const baseDelay = Math.min(
                        gradCfg.delay || 0,
                        animCfg.speed * 0.5 / tileCount
                    );
                    const ranked = node.map(
                        /** @param {number[]} r @param {number} j */
                        (r, j) => ({
                            j,
                            area: (r[2] - r[0]) * (r[3] - r[1])
                        })
                    ).sort(
                        /** @param {{j: number, area: number}} a @param {{j: number, area: number}} b */
                        (a, b) => b.area - a.area
                    );
                    ranked.forEach(
                        /** @param {{j: number, area: number}} item @param {number} rank */
                        (item, rank) => {
                            cascadeDelays[item.j] = rank * baseDelay;
                        }
                    );
                }
                node.forEach((r, j) => {
                    const x1 = r[0];
                    const y1 = r[1];
                    const x2 = r[2];
                    const y2 = r[3];
                    bounds.xMin = Math.min(bounds.xMin, x1);
                    bounds.yMin = Math.min(bounds.yMin, y1);
                    bounds.xMax = Math.max(bounds.xMax, x2);
                    bounds.yMax = Math.max(bounds.yMax, y2);
                    const colorProps = this.helpers.getShadeColor(
                        w.config.chart.type,
                        i,
                        j,
                        this.negRange
                    );
                    const color = colorProps.color;
                    const pathFill = fill.fillPath({
                        color,
                        seriesNumber: i,
                        dataPointIndex: j
                    });
                    const elRect = graphics.drawRect(
                        x1,
                        y1,
                        x2 - x1,
                        y2 - y1,
                        w.config.plotOptions.treemap.borderRadius,
                        "#fff",
                        1,
                        this.strokeWidth,
                        w.config.plotOptions.treemap.useFillColorAsStroke ? color : w.globals.stroke.colors[i]
                    );
                    elRect.attr({
                        cx: x1,
                        cy: y1,
                        index: i,
                        i,
                        j,
                        width: x2 - x1,
                        height: y2 - y1,
                        fill: pathFill
                    });
                    elRect.node.classList.add("apexcharts-treemap-rect");
                    let fromRect = {
                        x: x1 + (x2 - x1) / 2,
                        y: y1 + (y2 - y1) / 2,
                        width: 0,
                        height: 0
                    };
                    const toRect = {
                        x: x1,
                        y: y1,
                        width: x2 - x1,
                        height: y2 - y1
                    };
                    if (w.config.chart.animations.enabled && !w.globals.dataChanged) {
                        let speed = 1;
                        if (!w.globals.resized) {
                            speed = w.config.chart.animations.speed;
                        }
                        this.animateTreemap(
                            elRect,
                            fromRect,
                            toRect,
                            speed,
                            cascadeDelays[j] || 0
                        );
                    }
                    if (w.globals.dataChanged) {
                        let speed = 1;
                        if (this.dynamicAnim.enabled && w.globals.shouldAnimate) {
                            speed = this.dynamicAnim.speed;
                            if (w.globals.previousPaths[i] && /** @type {Record<string,any>} */
                                w.globals.previousPaths[i][j] && /** @type {Record<string,any>} */
                                w.globals.previousPaths[i][j].rect) {
                                fromRect = /** @type {Record<string,any>} */
                                    w.globals.previousPaths[i][j].rect;
                            }
                            this.animateTreemap(elRect, fromRect, toRect, speed);
                        }
                    }
                    let fontSize = this.getFontSize(r);
                    let formattedText = w.config.dataLabels.formatter(this.labels[i][j], {
                        value: w.seriesData.series[i][j],
                        seriesIndex: i,
                        dataPointIndex: j,
                        w
                    });
                    if (w.config.plotOptions.treemap.dataLabels.format === "truncate") {
                        fontSize = parseInt(String(w.config.dataLabels.style.fontSize), 10);
                        formattedText = this.truncateLabels(
                            String(formattedText),
                            fontSize,
                            x1,
                            y1,
                            x2,
                            y2
                        );
                    }
                    let dataLabels = null;
                    if (w.seriesData.series[i][j]) {
                        dataLabels = this.helpers.calculateDataLabels({
                            text: formattedText,
                            x: (x1 + x2) / 2,
                            y: (y1 + y2) / 2 + this.strokeWidth / 2 + fontSize / 3,
                            i,
                            j,
                            colorProps,
                            fontSize,
                            series
                        });
                    }
                    if (w.config.dataLabels.enabled && dataLabels) {
                        this.rotateToFitLabel(
                            dataLabels,
                            fontSize,
                            formattedText,
                            x1,
                            y1,
                            x2,
                            y2
                        );
                    }
                    elSeries.add(elRect);
                    if (dataLabels !== null) {
                        elSeries.add(dataLabels);
                    }
                });
                const seriesTitle = w.config.plotOptions.treemap.seriesTitle;
                if (w.config.series.length > 1 && seriesTitle && seriesTitle.show) {
                    const sName = (
                        /** @type {Record<string,any>} */
                        w.config.series[i].name || ""
                    );
                    if (sName && bounds.xMin < Infinity && bounds.yMin < Infinity) {
                        const {
                            offsetX,
                            offsetY,
                            borderColor,
                            borderWidth,
                            borderRadius,
                            style
                        } = seriesTitle;
                        const textColor = style.color || w.config.chart.foreColor;
                        const padding = {
                            left: style.padding.left,
                            right: style.padding.right,
                            top: style.padding.top,
                            bottom: style.padding.bottom
                        };
                        const textSize = graphics.getTextRects(
                            sName,
                            style.fontSize,
                            style.fontFamily
                        );
                        const labelRectWidth = textSize.width + padding.left + padding.right;
                        const labelRectHeight = textSize.height + padding.top + padding.bottom;
                        const labelX = bounds.xMin + (offsetX || 0);
                        const labelY = bounds.yMin + (offsetY || 0);
                        const elLabelRect = graphics.drawRect(
                            labelX,
                            labelY,
                            labelRectWidth,
                            labelRectHeight,
                            borderRadius,
                            style.background,
                            1,
                            borderWidth,
                            borderColor
                        );
                        const elLabelText = graphics.drawText({
                            x: labelX + padding.left,
                            y: labelY + padding.top + ((_a = textSize == null ? void 0 : textSize.height) != null ? _a : 0) * 0.75,
                            text: sName,
                            fontSize: style.fontSize,
                            fontFamily: style.fontFamily,
                            fontWeight: style.fontWeight,
                            foreColor: textColor,
                            cssClass: style.cssClass || ""
                        });
                        elSeries.add(elLabelRect);
                        elSeries.add(elLabelText);
                    }
                }
                elSeries.add(elDataLabelWrap);
                ret.add(elSeries);
            });
            return ret;
        }
        // This calculates a font-size based upon
        // average label length and the size of the box
        /**
         * @param {number[]} coordinates
         */
        getFontSize(coordinates) {
            const w = this.w;

            function totalLabelLength(arr) {
                let i, total = 0;
                if (Array.isArray(arr[0])) {
                    for (i = 0; i < arr.length; i++) {
                        total += totalLabelLength(arr[i]);
                    }
                } else {
                    for (i = 0; i < arr.length; i++) {
                        total += arr[i].length;
                    }
                }
                return total;
            }

            function countLabels(arr) {
                let i, total = 0;
                if (Array.isArray(arr[0])) {
                    for (i = 0; i < arr.length; i++) {
                        total += countLabels(arr[i]);
                    }
                } else {
                    for (i = 0; i < arr.length; i++) {
                        total += 1;
                    }
                }
                return total;
            }
            const averagelabelsize = totalLabelLength(this.labels) / countLabels(this.labels);

            function fontSize(width, height) {
                const area = width * height;
                const arearoot = Math.pow(area, 0.5);
                return Math.min(
                    arearoot / averagelabelsize,
                    parseInt(w.config.dataLabels.style.fontSize, 10)
                );
            }
            return fontSize(
                coordinates[2] - coordinates[0],
                coordinates[3] - coordinates[1]
            );
        }
        /**
         * @param {any} elText
         * @param {string | number} fontSize
         * @param {string} text
         * @param {number} x1
         * @param {number} y1
         * @param {number} x2
         * @param {number} y2
         */
        rotateToFitLabel(elText, fontSize, text, x1, y1, x2, y2) {
            const graphics = new Graphics(this.w);
            const textRect = graphics.getTextRects(text, String(fontSize));
            if (textRect.width + this.w.config.stroke.width + 5 > x2 - x1 && textRect.width <= y2 - y1) {
                const labelRotatingCenter = graphics.rotateAroundCenter(elText.node);
                elText.node.setAttribute(
                    "transform",
                    `rotate(-90 ${labelRotatingCenter.x} ${labelRotatingCenter.y}) translate(${textRect.height / 3})`
                );
            }
        }
        // This is an alternative label formatting method that uses a
        // consistent font size, and trims the edge of long labels
        /**
         * @param {string} text
         * @param {number} fontSize
         * @param {number} x1
         * @param {number} y1
         * @param {number} x2
         * @param {number} y2
         */
        truncateLabels(text, fontSize, x1, y1, x2, y2) {
            const graphics = new Graphics(this.w);
            const textRect = graphics.getTextRects(text, String(fontSize));
            const labelMaxWidth = textRect.width + this.w.config.stroke.width + 5 > x2 - x1 && y2 - y1 > x2 - x1 ? y2 - y1 : x2 - x1;
            const truncatedText = graphics.getTextBasedOnMaxWidth({
                text,
                maxWidth: labelMaxWidth,
                fontSize
            });
            if (text.length !== truncatedText.length && labelMaxWidth / fontSize < 5) {
                return "";
            } else {
                return truncatedText;
            }
        }
        /**
         * @param {any} el
         * @param {Record<string, any>} fromRect
         * @param {Record<string, any>} toRect
         * @param {number} speed
         * @param {number} [delay] - per-tile cascade delay in ms
         */
        animateTreemap(el, fromRect, toRect, speed, delay = 0) {
            const animations = new Animations(this.w);
            animations.animateRect(
                el,
                fromRect,
                toRect,
                speed,
                () => {
                    animations.animationCompleted(el);
                },
                delay
            );
        }
    }
    ApexCharts.use({
        line: Line,
        area: Line,
        scatter: Line,
        bubble: Line,
        rangeArea: Line,
        bar: Bar,
        column: Bar,
        barStacked: BarStacked,
        rangeBar: RangeBar,
        candlestick: BoxCandleStick,
        boxPlot: BoxCandleStick,
        pie: Pie,
        donut: Pie,
        polarArea: Pie,
        radialBar: Radial,
        radar: Radar,
        heatmap: HeatMap,
        treemap: TreemapChart
    });
    return ApexCharts;
}));
/**!
 * Sortable 1.15.7
 * @author	RubaXa   <trash@rubaxa.org>
 * @author	owenm    <owen23355@gmail.com>
 * @license MIT
 */
(function(global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
        typeof define === 'function' && define.amd ? define(factory) :
        (global = global || self, global.Sortable = factory());
}(this, (function() {
    'use strict';

    function _arrayLikeToArray(r, a) {
        (null == a || a > r.length) && (a = r.length);
        for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
        return n;
    }

    function _arrayWithoutHoles(r) {
        if (Array.isArray(r)) return _arrayLikeToArray(r);
    }

    function _defineProperty(e, r, t) {
        return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
            value: t,
            enumerable: !0,
            configurable: !0,
            writable: !0
        }) : e[r] = t, e;
    }

    function _extends() {
        return _extends = Object.assign ? Object.assign.bind() : function(n) {
            for (var e = 1; e < arguments.length; e++) {
                var t = arguments[e];
                for (var r in t)({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
            }
            return n;
        }, _extends.apply(null, arguments);
    }

    function _iterableToArray(r) {
        if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
    }

    function _nonIterableSpread() {
        throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
    }

    function ownKeys(e, r) {
        var t = Object.keys(e);
        if (Object.getOwnPropertySymbols) {
            var o = Object.getOwnPropertySymbols(e);
            r && (o = o.filter(function(r) {
                return Object.getOwnPropertyDescriptor(e, r).enumerable;
            })), t.push.apply(t, o);
        }
        return t;
    }

    function _objectSpread2(e) {
        for (var r = 1; r < arguments.length; r++) {
            var t = null != arguments[r] ? arguments[r] : {};
            r % 2 ? ownKeys(Object(t), !0).forEach(function(r) {
                _defineProperty(e, r, t[r]);
            }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r) {
                Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
            });
        }
        return e;
    }

    function _objectWithoutProperties(e, t) {
        if (null == e) return {};
        var o,
            r,
            i = _objectWithoutPropertiesLoose(e, t);
        if (Object.getOwnPropertySymbols) {
            var n = Object.getOwnPropertySymbols(e);
            for (r = 0; r < n.length; r++) o = n[r], -1 === t.indexOf(o) && {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
        }
        return i;
    }

    function _objectWithoutPropertiesLoose(r, e) {
        if (null == r) return {};
        var t = {};
        for (var n in r)
            if ({}.hasOwnProperty.call(r, n)) {
                if (-1 !== e.indexOf(n)) continue;
                t[n] = r[n];
            }
        return t;
    }

    function _toConsumableArray(r) {
        return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
    }

    function _toPrimitive(t, r) {
        if ("object" != typeof t || !t) return t;
        var e = t[Symbol.toPrimitive];
        if (void 0 !== e) {
            var i = e.call(t, r || "default");
            if ("object" != typeof i) return i;
            throw new TypeError("@@toPrimitive must return a primitive value.");
        }
        return ("string" === r ? String : Number)(t);
    }

    function _toPropertyKey(t) {
        var i = _toPrimitive(t, "string");
        return "symbol" == typeof i ? i : i + "";
    }

    function _typeof(o) {
        "@babel/helpers - typeof";

        return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
            return typeof o;
        } : function(o) {
            return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
        }, _typeof(o);
    }

    function _unsupportedIterableToArray(r, a) {
        if (r) {
            if ("string" == typeof r) return _arrayLikeToArray(r, a);
            var t = {}.toString.call(r).slice(8, -1);
            return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
        }
    }

    var version = "1.15.7";

    function userAgent(pattern) {
        if (typeof window !== 'undefined' && window.navigator) {
            return !! /*@__PURE__*/ navigator.userAgent.match(pattern);
        }
    }
    var IE11OrLess = userAgent(/(?:Trident.*rv[ :]?11\.|msie|iemobile|Windows Phone)/i);
    var Edge = userAgent(/Edge/i);
    var FireFox = userAgent(/firefox/i);
    var Safari = userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i);
    var IOS = userAgent(/iP(ad|od|hone)/i);
    var ChromeForAndroid = userAgent(/chrome/i) && userAgent(/android/i);

    var captureMode = {
        capture: false,
        passive: false
    };

    function on(el, event, fn) {
        el.addEventListener(event, fn, !IE11OrLess && captureMode);
    }

    function off(el, event, fn) {
        el.removeEventListener(event, fn, !IE11OrLess && captureMode);
    }

    function matches( /**HTMLElement*/ el, /**String*/ selector) {
        if (!selector) return;
        selector[0] === '>' && (selector = selector.substring(1));
        if (el) {
            try {
                if (el.matches) {
                    return el.matches(selector);
                } else if (el.msMatchesSelector) {
                    return el.msMatchesSelector(selector);
                } else if (el.webkitMatchesSelector) {
                    return el.webkitMatchesSelector(selector);
                }
            } catch (_) {
                return false;
            }
        }
        return false;
    }

    function getParentOrHost(el) {
        return el.host && el !== document && el.host.nodeType && el.host !== el ? el.host : el.parentNode;
    }

    function closest( /**HTMLElement*/ el, /**String*/ selector, /**HTMLElement*/ ctx, includeCTX) {
        if (el) {
            ctx = ctx || document;
            do {
                if (selector != null && (selector[0] === '>' ? el.parentNode === ctx && matches(el, selector) : matches(el, selector)) || includeCTX && el === ctx) {
                    return el;
                }
                if (el === ctx) break;
                /* jshint boss:true */
            } while (el = getParentOrHost(el));
        }
        return null;
    }
    var R_SPACE = /\s+/g;

    function toggleClass(el, name, state) {
        if (el && name) {
            if (el.classList) {
                el.classList[state ? 'add' : 'remove'](name);
            } else {
                var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
                el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
            }
        }
    }

    function css(el, prop, val) {
        var style = el && el.style;
        if (style) {
            if (val === void 0) {
                if (document.defaultView && document.defaultView.getComputedStyle) {
                    val = document.defaultView.getComputedStyle(el, '');
                } else if (el.currentStyle) {
                    val = el.currentStyle;
                }
                return prop === void 0 ? val : val[prop];
            } else {
                if (!(prop in style) && prop.indexOf('webkit') === -1) {
                    prop = '-webkit-' + prop;
                }
                style[prop] = val + (typeof val === 'string' ? '' : 'px');
            }
        }
    }

    function matrix(el, selfOnly) {
        var appliedTransforms = '';
        if (typeof el === 'string') {
            appliedTransforms = el;
        } else {
            do {
                var transform = css(el, 'transform');
                if (transform && transform !== 'none') {
                    appliedTransforms = transform + ' ' + appliedTransforms;
                }
                /* jshint boss:true */
            } while (!selfOnly && (el = el.parentNode));
        }
        var matrixFn = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix;
        /*jshint -W056 */
        return matrixFn && new matrixFn(appliedTransforms);
    }

    function find(ctx, tagName, iterator) {
        if (ctx) {
            var list = ctx.getElementsByTagName(tagName),
                i = 0,
                n = list.length;
            if (iterator) {
                for (; i < n; i++) {
                    iterator(list[i], i);
                }
            }
            return list;
        }
        return [];
    }

    function getWindowScrollingElement() {
        var scrollingElement = document.scrollingElement;
        if (scrollingElement) {
            return scrollingElement;
        } else {
            return document.documentElement;
        }
    }

    /**
     * Returns the "bounding client rect" of given element
     * @param  {HTMLElement} el                       The element whose boundingClientRect is wanted
     * @param  {[Boolean]} relativeToContainingBlock  Whether the rect should be relative to the containing block of (including) the container
     * @param  {[Boolean]} relativeToNonStaticParent  Whether the rect should be relative to the relative parent of (including) the contaienr
     * @param  {[Boolean]} undoScale                  Whether the container's scale() should be undone
     * @param  {[HTMLElement]} container              The parent the element will be placed in
     * @return {Object}                               The boundingClientRect of el, with specified adjustments
     */
    function getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) {
        if (!el.getBoundingClientRect && el !== window) return;
        var elRect, top, left, bottom, right, height, width;
        if (el !== window && el.parentNode && el !== getWindowScrollingElement()) {
            elRect = el.getBoundingClientRect();
            top = elRect.top;
            left = elRect.left;
            bottom = elRect.bottom;
            right = elRect.right;
            height = elRect.height;
            width = elRect.width;
        } else {
            top = 0;
            left = 0;
            bottom = window.innerHeight;
            right = window.innerWidth;
            height = window.innerHeight;
            width = window.innerWidth;
        }
        if ((relativeToContainingBlock || relativeToNonStaticParent) && el !== window) {
            // Adjust for translate()
            container = container || el.parentNode;

            // solves #1123 (see: https://stackoverflow.com/a/37953806/6088312)
            // Not needed on <= IE11
            if (!IE11OrLess) {
                do {
                    if (container && container.getBoundingClientRect && (css(container, 'transform') !== 'none' || relativeToNonStaticParent && css(container, 'position') !== 'static')) {
                        var containerRect = container.getBoundingClientRect();

                        // Set relative to edges of padding box of container
                        top -= containerRect.top + parseInt(css(container, 'border-top-width'));
                        left -= containerRect.left + parseInt(css(container, 'border-left-width'));
                        bottom = top + elRect.height;
                        right = left + elRect.width;
                        break;
                    }
                    /* jshint boss:true */
                } while (container = container.parentNode);
            }
        }
        if (undoScale && el !== window) {
            // Adjust for scale()
            var elMatrix = matrix(container || el),
                scaleX = elMatrix && elMatrix.a,
                scaleY = elMatrix && elMatrix.d;
            if (elMatrix) {
                top /= scaleY;
                left /= scaleX;
                width /= scaleX;
                height /= scaleY;
                bottom = top + height;
                right = left + width;
            }
        }
        return {
            top: top,
            left: left,
            bottom: bottom,
            right: right,
            width: width,
            height: height
        };
    }

    /**
     * Checks if a side of an element is scrolled past a side of its parents
     * @param  {HTMLElement}  el           The element who's side being scrolled out of view is in question
     * @param  {String}       elSide       Side of the element in question ('top', 'left', 'right', 'bottom')
     * @param  {String}       parentSide   Side of the parent in question ('top', 'left', 'right', 'bottom')
     * @return {HTMLElement}               The parent scroll element that the el's side is scrolled past, or null if there is no such element
     */
    function isScrolledPast(el, elSide, parentSide) {
        var parent = getParentAutoScrollElement(el, true),
            elSideVal = getRect(el)[elSide];

        /* jshint boss:true */
        while (parent) {
            var parentSideVal = getRect(parent)[parentSide],
                visible = void 0;
            if (parentSide === 'top' || parentSide === 'left') {
                visible = elSideVal >= parentSideVal;
            } else {
                visible = elSideVal <= parentSideVal;
            }
            if (!visible) return parent;
            if (parent === getWindowScrollingElement()) break;
            parent = getParentAutoScrollElement(parent, false);
        }
        return false;
    }

    /**
     * Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible)
     * and non-draggable elements
     * @param  {HTMLElement} el       The parent element
     * @param  {Number} childNum      The index of the child
     * @param  {Object} options       Parent Sortable's options
     * @return {HTMLElement}          The child at index childNum, or null if not found
     */
    function getChild(el, childNum, options, includeDragEl) {
        var currentChild = 0,
            i = 0,
            children = el.children;
        while (i < children.length) {
            if (children[i].style.display !== 'none' && children[i] !== Sortable.ghost && (includeDragEl || children[i] !== Sortable.dragged) && closest(children[i], options.draggable, el, false)) {
                if (currentChild === childNum) {
                    return children[i];
                }
                currentChild++;
            }
            i++;
        }
        return null;
    }

    /**
     * Gets the last child in the el, ignoring ghostEl or invisible elements (clones)
     * @param  {HTMLElement} el       Parent element
     * @param  {selector} selector    Any other elements that should be ignored
     * @return {HTMLElement}          The last child, ignoring ghostEl
     */
    function lastChild(el, selector) {
        var last = el.lastElementChild;
        while (last && (last === Sortable.ghost || css(last, 'display') === 'none' || selector && !matches(last, selector))) {
            last = last.previousElementSibling;
        }
        return last || null;
    }

    /**
     * Returns the index of an element within its parent for a selected set of
     * elements
     * @param  {HTMLElement} el
     * @param  {selector} selector
     * @return {number}
     */
    function index(el, selector) {
        var index = 0;
        if (!el || !el.parentNode) {
            return -1;
        }

        /* jshint boss:true */
        while (el = el.previousElementSibling) {
            if (el.nodeName.toUpperCase() !== 'TEMPLATE' && el !== Sortable.clone && (!selector || matches(el, selector))) {
                index++;
            }
        }
        return index;
    }

    /**
     * Returns the scroll offset of the given element, added with all the scroll offsets of parent elements.
     * The value is returned in real pixels.
     * @param  {HTMLElement} el
     * @return {Array}             Offsets in the format of [left, top]
     */
    function getRelativeScrollOffset(el) {
        var offsetLeft = 0,
            offsetTop = 0,
            winScroller = getWindowScrollingElement();
        if (el) {
            do {
                var elMatrix = matrix(el),
                    scaleX = elMatrix.a,
                    scaleY = elMatrix.d;
                offsetLeft += el.scrollLeft * scaleX;
                offsetTop += el.scrollTop * scaleY;
            } while (el !== winScroller && (el = el.parentNode));
        }
        return [offsetLeft, offsetTop];
    }

    /**
     * Returns the index of the object within the given array
     * @param  {Array} arr   Array that may or may not hold the object
     * @param  {Object} obj  An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find
     * @return {Number}      The index of the object in the array, or -1
     */
    function indexOfObject(arr, obj) {
        for (var i in arr) {
            if (!arr.hasOwnProperty(i)) continue;
            for (var key in obj) {
                if (obj.hasOwnProperty(key) && obj[key] === arr[i][key]) return Number(i);
            }
        }
        return -1;
    }

    function getParentAutoScrollElement(el, includeSelf) {
        // skip to window
        if (!el || !el.getBoundingClientRect) return getWindowScrollingElement();
        var elem = el;
        var gotSelf = false;
        do {
            // we don't need to get elem css if it isn't even overflowing in the first place (performance)
            if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) {
                var elemCSS = css(elem);
                if (elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') || elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')) {
                    if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement();
                    if (gotSelf || includeSelf) return elem;
                    gotSelf = true;
                }
            }
            /* jshint boss:true */
        } while (elem = elem.parentNode);
        return getWindowScrollingElement();
    }

    function extend(dst, src) {
        if (dst && src) {
            for (var key in src) {
                if (src.hasOwnProperty(key)) {
                    dst[key] = src[key];
                }
            }
        }
        return dst;
    }

    function isRectEqual(rect1, rect2) {
        return Math.round(rect1.top) === Math.round(rect2.top) && Math.round(rect1.left) === Math.round(rect2.left) && Math.round(rect1.height) === Math.round(rect2.height) && Math.round(rect1.width) === Math.round(rect2.width);
    }
    var _throttleTimeout;

    function throttle(callback, ms) {
        return function() {
            if (!_throttleTimeout) {
                var args = arguments,
                    _this = this;
                if (args.length === 1) {
                    callback.call(_this, args[0]);
                } else {
                    callback.apply(_this, args);
                }
                _throttleTimeout = setTimeout(function() {
                    _throttleTimeout = void 0;
                }, ms);
            }
        };
    }

    function cancelThrottle() {
        clearTimeout(_throttleTimeout);
        _throttleTimeout = void 0;
    }

    function scrollBy(el, x, y) {
        el.scrollLeft += x;
        el.scrollTop += y;
    }

    function clone(el) {
        var Polymer = window.Polymer;
        var $ = window.jQuery || window.Zepto;
        if (Polymer && Polymer.dom) {
            return Polymer.dom(el).cloneNode(true);
        } else if ($) {
            return $(el).clone(true)[0];
        } else {
            return el.cloneNode(true);
        }
    }

    function setRect(el, rect) {
        css(el, 'position', 'absolute');
        css(el, 'top', rect.top);
        css(el, 'left', rect.left);
        css(el, 'width', rect.width);
        css(el, 'height', rect.height);
    }

    function unsetRect(el) {
        css(el, 'position', '');
        css(el, 'top', '');
        css(el, 'left', '');
        css(el, 'width', '');
        css(el, 'height', '');
    }

    function getChildContainingRectFromElement(container, options, ghostEl) {
        var rect = {};
        Array.from(container.children).forEach(function(child) {
            var _rect$left, _rect$top, _rect$right, _rect$bottom;
            if (!closest(child, options.draggable, container, false) || child.animated || child === ghostEl) return;
            var childRect = getRect(child);
            rect.left = Math.min((_rect$left = rect.left) !== null && _rect$left !== void 0 ? _rect$left : Infinity, childRect.left);
            rect.top = Math.min((_rect$top = rect.top) !== null && _rect$top !== void 0 ? _rect$top : Infinity, childRect.top);
            rect.right = Math.max((_rect$right = rect.right) !== null && _rect$right !== void 0 ? _rect$right : -Infinity, childRect.right);
            rect.bottom = Math.max((_rect$bottom = rect.bottom) !== null && _rect$bottom !== void 0 ? _rect$bottom : -Infinity, childRect.bottom);
        });
        rect.width = rect.right - rect.left;
        rect.height = rect.bottom - rect.top;
        rect.x = rect.left;
        rect.y = rect.top;
        return rect;
    }
    var expando = 'Sortable' + new Date().getTime();

    function AnimationStateManager() {
        var animationStates = [],
            animationCallbackId;
        return {
            captureAnimationState: function captureAnimationState() {
                animationStates = [];
                if (!this.options.animation) return;
                var children = [].slice.call(this.el.children);
                children.forEach(function(child) {
                    if (css(child, 'display') === 'none' || child === Sortable.ghost) return;
                    animationStates.push({
                        target: child,
                        rect: getRect(child)
                    });
                    var fromRect = _objectSpread2({}, animationStates[animationStates.length - 1].rect);

                    // If animating: compensate for current animation
                    if (child.thisAnimationDuration) {
                        var childMatrix = matrix(child, true);
                        if (childMatrix) {
                            fromRect.top -= childMatrix.f;
                            fromRect.left -= childMatrix.e;
                        }
                    }
                    child.fromRect = fromRect;
                });
            },
            addAnimationState: function addAnimationState(state) {
                animationStates.push(state);
            },
            removeAnimationState: function removeAnimationState(target) {
                animationStates.splice(indexOfObject(animationStates, {
                    target: target
                }), 1);
            },
            animateAll: function animateAll(callback) {
                var _this = this;
                if (!this.options.animation) {
                    clearTimeout(animationCallbackId);
                    if (typeof callback === 'function') callback();
                    return;
                }
                var animating = false,
                    animationTime = 0;
                animationStates.forEach(function(state) {
                    var time = 0,
                        target = state.target,
                        fromRect = target.fromRect,
                        toRect = getRect(target),
                        prevFromRect = target.prevFromRect,
                        prevToRect = target.prevToRect,
                        animatingRect = state.rect,
                        targetMatrix = matrix(target, true);
                    if (targetMatrix) {
                        // Compensate for current animation
                        toRect.top -= targetMatrix.f;
                        toRect.left -= targetMatrix.e;
                    }
                    target.toRect = toRect;
                    if (target.thisAnimationDuration) {
                        // Could also check if animatingRect is between fromRect and toRect
                        if (isRectEqual(prevFromRect, toRect) && !isRectEqual(fromRect, toRect) &&
                            // Make sure animatingRect is on line between toRect & fromRect
                            (animatingRect.top - toRect.top) / (animatingRect.left - toRect.left) === (fromRect.top - toRect.top) / (fromRect.left - toRect.left)) {
                            // If returning to same place as started from animation and on same axis
                            time = calculateRealTime(animatingRect, prevFromRect, prevToRect, _this.options);
                        }
                    }

                    // if fromRect != toRect: animate
                    if (!isRectEqual(toRect, fromRect)) {
                        target.prevFromRect = fromRect;
                        target.prevToRect = toRect;
                        if (!time) {
                            time = _this.options.animation;
                        }
                        _this.animate(target, animatingRect, toRect, time);
                    }
                    if (time) {
                        animating = true;
                        animationTime = Math.max(animationTime, time);
                        clearTimeout(target.animationResetTimer);
                        target.animationResetTimer = setTimeout(function() {
                            target.animationTime = 0;
                            target.prevFromRect = null;
                            target.fromRect = null;
                            target.prevToRect = null;
                            target.thisAnimationDuration = null;
                        }, time);
                        target.thisAnimationDuration = time;
                    }
                });
                clearTimeout(animationCallbackId);
                if (!animating) {
                    if (typeof callback === 'function') callback();
                } else {
                    animationCallbackId = setTimeout(function() {
                        if (typeof callback === 'function') callback();
                    }, animationTime);
                }
                animationStates = [];
            },
            animate: function animate(target, currentRect, toRect, duration) {
                if (duration) {
                    css(target, 'transition', '');
                    css(target, 'transform', '');
                    var elMatrix = matrix(this.el),
                        scaleX = elMatrix && elMatrix.a,
                        scaleY = elMatrix && elMatrix.d,
                        translateX = (currentRect.left - toRect.left) / (scaleX || 1),
                        translateY = (currentRect.top - toRect.top) / (scaleY || 1);
                    target.animatingX = !!translateX;
                    target.animatingY = !!translateY;
                    css(target, 'transform', 'translate3d(' + translateX + 'px,' + translateY + 'px,0)');
                    this.forRepaintDummy = repaint(target); // repaint

                    css(target, 'transition', 'transform ' + duration + 'ms' + (this.options.easing ? ' ' + this.options.easing : ''));
                    css(target, 'transform', 'translate3d(0,0,0)');
                    typeof target.animated === 'number' && clearTimeout(target.animated);
                    target.animated = setTimeout(function() {
                        css(target, 'transition', '');
                        css(target, 'transform', '');
                        target.animated = false;
                        target.animatingX = false;
                        target.animatingY = false;
                    }, duration);
                }
            }
        };
    }

    function repaint(target) {
        return target.offsetWidth;
    }

    function calculateRealTime(animatingRect, fromRect, toRect, options) {
        return Math.sqrt(Math.pow(fromRect.top - animatingRect.top, 2) + Math.pow(fromRect.left - animatingRect.left, 2)) / Math.sqrt(Math.pow(fromRect.top - toRect.top, 2) + Math.pow(fromRect.left - toRect.left, 2)) * options.animation;
    }

    var plugins = [];
    var defaults = {
        initializeByDefault: true
    };
    var PluginManager = {
        mount: function mount(plugin) {
            // Set default static properties
            for (var option in defaults) {
                if (defaults.hasOwnProperty(option) && !(option in plugin)) {
                    plugin[option] = defaults[option];
                }
            }
            plugins.forEach(function(p) {
                if (p.pluginName === plugin.pluginName) {
                    throw "Sortable: Cannot mount plugin ".concat(plugin.pluginName, " more than once");
                }
            });
            plugins.push(plugin);
        },
        pluginEvent: function pluginEvent(eventName, sortable, evt) {
            var _this = this;
            this.eventCanceled = false;
            evt.cancel = function() {
                _this.eventCanceled = true;
            };
            var eventNameGlobal = eventName + 'Global';
            plugins.forEach(function(plugin) {
                if (!sortable[plugin.pluginName]) return;
                // Fire global events if it exists in this sortable
                if (sortable[plugin.pluginName][eventNameGlobal]) {
                    sortable[plugin.pluginName][eventNameGlobal](_objectSpread2({
                        sortable: sortable
                    }, evt));
                }

                // Only fire plugin event if plugin is enabled in this sortable,
                // and plugin has event defined
                if (sortable.options[plugin.pluginName] && sortable[plugin.pluginName][eventName]) {
                    sortable[plugin.pluginName][eventName](_objectSpread2({
                        sortable: sortable
                    }, evt));
                }
            });
        },
        initializePlugins: function initializePlugins(sortable, el, defaults, options) {
            plugins.forEach(function(plugin) {
                var pluginName = plugin.pluginName;
                if (!sortable.options[pluginName] && !plugin.initializeByDefault) return;
                var initialized = new plugin(sortable, el, sortable.options);
                initialized.sortable = sortable;
                initialized.options = sortable.options;
                sortable[pluginName] = initialized;

                // Add default options from plugin
                _extends(defaults, initialized.defaults);
            });
            for (var option in sortable.options) {
                if (!sortable.options.hasOwnProperty(option)) continue;
                var modified = this.modifyOption(sortable, option, sortable.options[option]);
                if (typeof modified !== 'undefined') {
                    sortable.options[option] = modified;
                }
            }
        },
        getEventProperties: function getEventProperties(name, sortable) {
            var eventProperties = {};
            plugins.forEach(function(plugin) {
                if (typeof plugin.eventProperties !== 'function') return;
                _extends(eventProperties, plugin.eventProperties.call(sortable[plugin.pluginName], name));
            });
            return eventProperties;
        },
        modifyOption: function modifyOption(sortable, name, value) {
            var modifiedValue;
            plugins.forEach(function(plugin) {
                // Plugin must exist on the Sortable
                if (!sortable[plugin.pluginName]) return;

                // If static option listener exists for this option, call in the context of the Sortable's instance of this plugin
                if (plugin.optionListeners && typeof plugin.optionListeners[name] === 'function') {
                    modifiedValue = plugin.optionListeners[name].call(sortable[plugin.pluginName], value);
                }
            });
            return modifiedValue;
        }
    };

    function dispatchEvent(_ref) {
        var sortable = _ref.sortable,
            rootEl = _ref.rootEl,
            name = _ref.name,
            targetEl = _ref.targetEl,
            cloneEl = _ref.cloneEl,
            toEl = _ref.toEl,
            fromEl = _ref.fromEl,
            oldIndex = _ref.oldIndex,
            newIndex = _ref.newIndex,
            oldDraggableIndex = _ref.oldDraggableIndex,
            newDraggableIndex = _ref.newDraggableIndex,
            originalEvent = _ref.originalEvent,
            putSortable = _ref.putSortable,
            extraEventProperties = _ref.extraEventProperties;
        sortable = sortable || rootEl && rootEl[expando];
        if (!sortable) return;
        var evt,
            options = sortable.options,
            onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);
        // Support for new CustomEvent feature
        if (window.CustomEvent && !IE11OrLess && !Edge) {
            evt = new CustomEvent(name, {
                bubbles: true,
                cancelable: true
            });
        } else {
            evt = document.createEvent('Event');
            evt.initEvent(name, true, true);
        }
        evt.to = toEl || rootEl;
        evt.from = fromEl || rootEl;
        evt.item = targetEl || rootEl;
        evt.clone = cloneEl;
        evt.oldIndex = oldIndex;
        evt.newIndex = newIndex;
        evt.oldDraggableIndex = oldDraggableIndex;
        evt.newDraggableIndex = newDraggableIndex;
        evt.originalEvent = originalEvent;
        evt.pullMode = putSortable ? putSortable.lastPutMode : undefined;
        var allEventProperties = _objectSpread2(_objectSpread2({}, extraEventProperties), PluginManager.getEventProperties(name, sortable));
        for (var option in allEventProperties) {
            evt[option] = allEventProperties[option];
        }
        if (rootEl) {
            rootEl.dispatchEvent(evt);
        }
        if (options[onName]) {
            options[onName].call(sortable, evt);
        }
    }

    var _excluded = ["evt"];
    var pluginEvent = function pluginEvent(eventName, sortable) {
        var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
            originalEvent = _ref.evt,
            data = _objectWithoutProperties(_ref, _excluded);
        PluginManager.pluginEvent.bind(Sortable)(eventName, sortable, _objectSpread2({
            dragEl: dragEl,
            parentEl: parentEl,
            ghostEl: ghostEl,
            rootEl: rootEl,
            nextEl: nextEl,
            lastDownEl: lastDownEl,
            cloneEl: cloneEl,
            cloneHidden: cloneHidden,
            dragStarted: moved,
            putSortable: putSortable,
            activeSortable: Sortable.active,
            originalEvent: originalEvent,
            oldIndex: oldIndex,
            oldDraggableIndex: oldDraggableIndex,
            newIndex: newIndex,
            newDraggableIndex: newDraggableIndex,
            hideGhostForTarget: _hideGhostForTarget,
            unhideGhostForTarget: _unhideGhostForTarget,
            cloneNowHidden: function cloneNowHidden() {
                cloneHidden = true;
            },
            cloneNowShown: function cloneNowShown() {
                cloneHidden = false;
            },
            dispatchSortableEvent: function dispatchSortableEvent(name) {
                _dispatchEvent({
                    sortable: sortable,
                    name: name,
                    originalEvent: originalEvent
                });
            }
        }, data));
    };

    function _dispatchEvent(info) {
        dispatchEvent(_objectSpread2({
            putSortable: putSortable,
            cloneEl: cloneEl,
            targetEl: dragEl,
            rootEl: rootEl,
            oldIndex: oldIndex,
            oldDraggableIndex: oldDraggableIndex,
            newIndex: newIndex,
            newDraggableIndex: newDraggableIndex
        }, info));
    }
    var dragEl,
        parentEl,
        ghostEl,
        rootEl,
        nextEl,
        lastDownEl,
        cloneEl,
        cloneHidden,
        oldIndex,
        newIndex,
        oldDraggableIndex,
        newDraggableIndex,
        activeGroup,
        putSortable,
        awaitingDragStarted = false,
        ignoreNextClick = false,
        sortables = [],
        tapEvt,
        touchEvt,
        lastDx,
        lastDy,
        tapDistanceLeft,
        tapDistanceTop,
        moved,
        lastTarget,
        lastDirection,
        pastFirstInvertThresh = false,
        isCircumstantialInvert = false,
        targetMoveDistance,
        // For positioning ghost absolutely
        ghostRelativeParent,
        ghostRelativeParentInitialScroll = [],
        // (left, top)

        _silent = false,
        savedInputChecked = [];

    /** @const */
    var documentExists = typeof document !== 'undefined',
        PositionGhostAbsolutely = IOS,
        CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float',
        // This will not pass for IE9, because IE9 DnD only works on anchors
        supportDraggable = documentExists && !ChromeForAndroid && !IOS && 'draggable' in document.createElement('div'),
        supportCssPointerEvents = function() {
            if (!documentExists) return;
            // false when <= IE11
            if (IE11OrLess) {
                return false;
            }
            var el = document.createElement('x');
            el.style.cssText = 'pointer-events:auto';
            return el.style.pointerEvents === 'auto';
        }(),
        _detectDirection = function _detectDirection(el, options) {
            var elCSS = css(el),
                elWidth = parseInt(elCSS.width) - parseInt(elCSS.paddingLeft) - parseInt(elCSS.paddingRight) - parseInt(elCSS.borderLeftWidth) - parseInt(elCSS.borderRightWidth),
                child1 = getChild(el, 0, options),
                child2 = getChild(el, 1, options),
                firstChildCSS = child1 && css(child1),
                secondChildCSS = child2 && css(child2),
                firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width,
                secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width;
            if (elCSS.display === 'flex') {
                return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse' ? 'vertical' : 'horizontal';
            }
            if (elCSS.display === 'grid') {
                return elCSS.gridTemplateColumns.split(' ').length <= 1 ? 'vertical' : 'horizontal';
            }
            if (child1 && firstChildCSS["float"] && firstChildCSS["float"] !== 'none') {
                var touchingSideChild2 = firstChildCSS["float"] === 'left' ? 'left' : 'right';
                return child2 && (secondChildCSS.clear === 'both' || secondChildCSS.clear === touchingSideChild2) ? 'vertical' : 'horizontal';
            }
            return child1 && (firstChildCSS.display === 'block' || firstChildCSS.display === 'flex' || firstChildCSS.display === 'table' || firstChildCSS.display === 'grid' || firstChildWidth >= elWidth && elCSS[CSSFloatProperty] === 'none' || child2 && elCSS[CSSFloatProperty] === 'none' && firstChildWidth + secondChildWidth > elWidth) ? 'vertical' : 'horizontal';
        },
        _dragElInRowColumn = function _dragElInRowColumn(dragRect, targetRect, vertical) {
            var dragElS1Opp = vertical ? dragRect.left : dragRect.top,
                dragElS2Opp = vertical ? dragRect.right : dragRect.bottom,
                dragElOppLength = vertical ? dragRect.width : dragRect.height,
                targetS1Opp = vertical ? targetRect.left : targetRect.top,
                targetS2Opp = vertical ? targetRect.right : targetRect.bottom,
                targetOppLength = vertical ? targetRect.width : targetRect.height;
            return dragElS1Opp === targetS1Opp || dragElS2Opp === targetS2Opp || dragElS1Opp + dragElOppLength / 2 === targetS1Opp + targetOppLength / 2;
        },
        /**
         * Detects first nearest empty sortable to X and Y position using emptyInsertThreshold.
         * @param  {Number} x      X position
         * @param  {Number} y      Y position
         * @return {HTMLElement}   Element of the first found nearest Sortable
         */
        _detectNearestEmptySortable = function _detectNearestEmptySortable(x, y) {
            var ret;
            sortables.some(function(sortable) {
                var threshold = sortable[expando].options.emptyInsertThreshold;
                if (!threshold || lastChild(sortable)) return;
                var rect = getRect(sortable),
                    insideHorizontally = x >= rect.left - threshold && x <= rect.right + threshold,
                    insideVertically = y >= rect.top - threshold && y <= rect.bottom + threshold;
                if (insideHorizontally && insideVertically) {
                    return ret = sortable;
                }
            });
            return ret;
        },
        _prepareGroup = function _prepareGroup(options) {
            function toFn(value, pull) {
                return function(to, from, dragEl, evt) {
                    var sameGroup = to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name;
                    if (value == null && (pull || sameGroup)) {
                        // Default pull value
                        // Default pull and put value if same group
                        return true;
                    } else if (value == null || value === false) {
                        return false;
                    } else if (pull && value === 'clone') {
                        return value;
                    } else if (typeof value === 'function') {
                        return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt);
                    } else {
                        var otherGroup = (pull ? to : from).options.group.name;
                        return value === true || typeof value === 'string' && value === otherGroup || value.join && value.indexOf(otherGroup) > -1;
                    }
                };
            }
            var group = {};
            var originalGroup = options.group;
            if (!originalGroup || _typeof(originalGroup) != 'object') {
                originalGroup = {
                    name: originalGroup
                };
            }
            group.name = originalGroup.name;
            group.checkPull = toFn(originalGroup.pull, true);
            group.checkPut = toFn(originalGroup.put);
            group.revertClone = originalGroup.revertClone;
            options.group = group;
        },
        _hideGhostForTarget = function _hideGhostForTarget() {
            if (!supportCssPointerEvents && ghostEl) {
                css(ghostEl, 'display', 'none');
            }
        },
        _unhideGhostForTarget = function _unhideGhostForTarget() {
            if (!supportCssPointerEvents && ghostEl) {
                css(ghostEl, 'display', '');
            }
        };

    // #1184 fix - Prevent click event on fallback if dragged but item not changed position
    if (documentExists && !ChromeForAndroid) {
        document.addEventListener('click', function(evt) {
            if (ignoreNextClick) {
                evt.preventDefault();
                evt.stopPropagation && evt.stopPropagation();
                evt.stopImmediatePropagation && evt.stopImmediatePropagation();
                ignoreNextClick = false;
                return false;
            }
        }, true);
    }
    var nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent(evt) {
        if (dragEl) {
            evt = evt.touches ? evt.touches[0] : evt;
            var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY);
            if (nearest) {
                // Create imitation event
                var event = {};
                for (var i in evt) {
                    if (evt.hasOwnProperty(i)) {
                        event[i] = evt[i];
                    }
                }
                event.target = event.rootEl = nearest;
                event.preventDefault = void 0;
                event.stopPropagation = void 0;
                nearest[expando]._onDragOver(event);
            }
        }
    };
    var _checkOutsideTargetEl = function _checkOutsideTargetEl(evt) {
        if (dragEl) {
            dragEl.parentNode[expando]._isOutsideThisEl(evt.target);
        }
    };

    /**
     * @class  Sortable
     * @param  {HTMLElement}  el
     * @param  {Object}       [options]
     */
    function Sortable(el, options) {
        if (!(el && el.nodeType && el.nodeType === 1)) {
            throw "Sortable: `el` must be an HTMLElement, not ".concat({}.toString.call(el));
        }
        this.el = el; // root element
        this.options = options = _extends({}, options);

        // Export instance
        el[expando] = this;
        var defaults = {
            group: null,
            sort: true,
            disabled: false,
            store: null,
            handle: null,
            draggable: /^[uo]l$/i.test(el.nodeName) ? '>li' : '>*',
            swapThreshold: 1,
            // percentage; 0 <= x <= 1
            invertSwap: false,
            // invert always
            invertedSwapThreshold: null,
            // will be set to same as swapThreshold if default
            removeCloneOnHide: true,
            direction: function direction() {
                return _detectDirection(el, this.options);
            },
            ghostClass: 'sortable-ghost',
            chosenClass: 'sortable-chosen',
            dragClass: 'sortable-drag',
            ignore: 'a, img',
            filter: null,
            preventOnFilter: true,
            animation: 0,
            easing: null,
            setData: function setData(dataTransfer, dragEl) {
                dataTransfer.setData('Text', dragEl.textContent);
            },
            dropBubble: false,
            dragoverBubble: false,
            dataIdAttr: 'data-id',
            delay: 0,
            delayOnTouchOnly: false,
            touchStartThreshold: (Number.parseInt ? Number : window).parseInt(window.devicePixelRatio, 10) || 1,
            forceFallback: false,
            fallbackClass: 'sortable-fallback',
            fallbackOnBody: false,
            fallbackTolerance: 0,
            fallbackOffset: {
                x: 0,
                y: 0
            },
            // Disabled on Safari: #1571; Enabled on Safari IOS: #2244
            supportPointer: Sortable.supportPointer !== false && 'PointerEvent' in window && (!Safari || IOS),
            emptyInsertThreshold: 5
        };
        PluginManager.initializePlugins(this, el, defaults);

        // Set default options
        for (var name in defaults) {
            !(name in options) && (options[name] = defaults[name]);
        }
        _prepareGroup(options);

        // Bind all private methods
        for (var fn in this) {
            if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
                this[fn] = this[fn].bind(this);
            }
        }

        // Setup drag mode
        this.nativeDraggable = options.forceFallback ? false : supportDraggable;
        if (this.nativeDraggable) {
            // Touch start threshold cannot be greater than the native dragstart threshold
            this.options.touchStartThreshold = 1;
        }

        // Bind events
        if (options.supportPointer) {
            on(el, 'pointerdown', this._onTapStart);
        } else {
            on(el, 'mousedown', this._onTapStart);
            on(el, 'touchstart', this._onTapStart);
        }
        if (this.nativeDraggable) {
            on(el, 'dragover', this);
            on(el, 'dragenter', this);
        }
        sortables.push(this.el);

        // Restore sorting
        options.store && options.store.get && this.sort(options.store.get(this) || []);

        // Add animation state manager
        _extends(this, AnimationStateManager());
    }
    Sortable.prototype = /** @lends Sortable.prototype */ {
        constructor: Sortable,
        _isOutsideThisEl: function _isOutsideThisEl(target) {
            if (!this.el.contains(target) && target !== this.el) {
                lastTarget = null;
            }
        },
        _getDirection: function _getDirection(evt, target) {
            return typeof this.options.direction === 'function' ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction;
        },
        _onTapStart: function _onTapStart( /** Event|TouchEvent */ evt) {
            if (!evt.cancelable) return;
            var _this = this,
                el = this.el,
                options = this.options,
                preventOnFilter = options.preventOnFilter,
                type = evt.type,
                touch = evt.touches && evt.touches[0] || evt.pointerType && evt.pointerType === 'touch' && evt,
                target = (touch || evt).target,
                originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0] || evt.composedPath && evt.composedPath()[0]) || target,
                filter = options.filter;
            _saveInputCheckedState(el);

            // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
            if (dragEl) {
                return;
            }
            if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {
                return; // only left button and enabled
            }

            // cancel dnd if original target is content editable
            if (originalTarget.isContentEditable) {
                return;
            }

            // Safari ignores further event handling after mousedown
            if (!this.nativeDraggable && Safari && target && target.tagName.toUpperCase() === 'SELECT') {
                return;
            }
            target = closest(target, options.draggable, el, false);
            if (target && target.animated) {
                return;
            }
            if (lastDownEl === target) {
                // Ignoring duplicate `down`
                return;
            }

            // Get the index of the dragged element within its parent
            oldIndex = index(target);
            oldDraggableIndex = index(target, options.draggable);

            // Check filter
            if (typeof filter === 'function') {
                if (filter.call(this, evt, target, this)) {
                    _dispatchEvent({
                        sortable: _this,
                        rootEl: originalTarget,
                        name: 'filter',
                        targetEl: target,
                        toEl: el,
                        fromEl: el
                    });
                    pluginEvent('filter', _this, {
                        evt: evt
                    });
                    preventOnFilter && evt.preventDefault();
                    return; // cancel dnd
                }
            } else if (filter) {
                filter = filter.split(',').some(function(criteria) {
                    criteria = closest(originalTarget, criteria.trim(), el, false);
                    if (criteria) {
                        _dispatchEvent({
                            sortable: _this,
                            rootEl: criteria,
                            name: 'filter',
                            targetEl: target,
                            fromEl: el,
                            toEl: el
                        });
                        pluginEvent('filter', _this, {
                            evt: evt
                        });
                        return true;
                    }
                });
                if (filter) {
                    preventOnFilter && evt.preventDefault();
                    return; // cancel dnd
                }
            }
            if (options.handle && !closest(originalTarget, options.handle, el, false)) {
                return;
            }

            // Prepare `dragstart`
            this._prepareDragStart(evt, touch, target);
        },
        _prepareDragStart: function _prepareDragStart( /** Event */ evt, /** Touch */ touch, /** HTMLElement */ target) {
            var _this = this,
                el = _this.el,
                options = _this.options,
                ownerDocument = el.ownerDocument,
                dragStartFn;
            if (target && !dragEl && target.parentNode === el) {
                var dragRect = getRect(target);
                rootEl = el;
                dragEl = target;
                parentEl = dragEl.parentNode;
                nextEl = dragEl.nextSibling;
                lastDownEl = target;
                activeGroup = options.group;
                Sortable.dragged = dragEl;
                tapEvt = {
                    target: dragEl,
                    clientX: (touch || evt).clientX,
                    clientY: (touch || evt).clientY
                };
                tapDistanceLeft = tapEvt.clientX - dragRect.left;
                tapDistanceTop = tapEvt.clientY - dragRect.top;
                this._lastX = (touch || evt).clientX;
                this._lastY = (touch || evt).clientY;
                dragEl.style['will-change'] = 'all';
                dragStartFn = function dragStartFn() {
                    pluginEvent('delayEnded', _this, {
                        evt: evt
                    });
                    if (Sortable.eventCanceled) {
                        _this._onDrop();
                        return;
                    }
                    // Delayed drag has been triggered
                    // we can re-enable the events: touchmove/mousemove
                    _this._disableDelayedDragEvents();
                    if (!FireFox && _this.nativeDraggable) {
                        dragEl.draggable = true;
                    }

                    // Bind the events: dragstart/dragend
                    _this._triggerDragStart(evt, touch);

                    // Drag start event
                    _dispatchEvent({
                        sortable: _this,
                        name: 'choose',
                        originalEvent: evt
                    });

                    // Chosen item
                    toggleClass(dragEl, options.chosenClass, true);
                };

                // Disable "draggable"
                options.ignore.split(',').forEach(function(criteria) {
                    find(dragEl, criteria.trim(), _disableDraggable);
                });
                on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent);
                on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent);
                on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent);
                if (options.supportPointer) {
                    on(ownerDocument, 'pointerup', _this._onDrop);
                    // Native D&D triggers pointercancel
                    !this.nativeDraggable && on(ownerDocument, 'pointercancel', _this._onDrop);
                } else {
                    on(ownerDocument, 'mouseup', _this._onDrop);
                    on(ownerDocument, 'touchend', _this._onDrop);
                    on(ownerDocument, 'touchcancel', _this._onDrop);
                }

                // Make dragEl draggable (must be before delay for FireFox)
                if (FireFox && this.nativeDraggable) {
                    this.options.touchStartThreshold = 4;
                    dragEl.draggable = true;
                }
                pluginEvent('delayStart', this, {
                    evt: evt
                });

                // Delay is impossible for native DnD in Edge or IE
                if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) {
                    if (Sortable.eventCanceled) {
                        this._onDrop();
                        return;
                    }
                    // If the user moves the pointer or let go the click or touch
                    // before the delay has been reached:
                    // disable the delayed drag
                    if (options.supportPointer) {
                        on(ownerDocument, 'pointerup', _this._disableDelayedDrag);
                        on(ownerDocument, 'pointercancel', _this._disableDelayedDrag);
                    } else {
                        on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
                        on(ownerDocument, 'touchend', _this._disableDelayedDrag);
                        on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
                    }
                    on(ownerDocument, 'mousemove', _this._delayedDragTouchMoveHandler);
                    on(ownerDocument, 'touchmove', _this._delayedDragTouchMoveHandler);
                    options.supportPointer && on(ownerDocument, 'pointermove', _this._delayedDragTouchMoveHandler);
                    _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
                } else {
                    dragStartFn();
                }
            }
        },
        _delayedDragTouchMoveHandler: function _delayedDragTouchMoveHandler( /** TouchEvent|PointerEvent **/ e) {
            var touch = e.touches ? e.touches[0] : e;
            if (Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1))) {
                this._disableDelayedDrag();
            }
        },
        _disableDelayedDrag: function _disableDelayedDrag() {
            dragEl && _disableDraggable(dragEl);
            clearTimeout(this._dragStartTimer);
            this._disableDelayedDragEvents();
        },
        _disableDelayedDragEvents: function _disableDelayedDragEvents() {
            var ownerDocument = this.el.ownerDocument;
            off(ownerDocument, 'mouseup', this._disableDelayedDrag);
            off(ownerDocument, 'touchend', this._disableDelayedDrag);
            off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
            off(ownerDocument, 'pointerup', this._disableDelayedDrag);
            off(ownerDocument, 'pointercancel', this._disableDelayedDrag);
            off(ownerDocument, 'mousemove', this._delayedDragTouchMoveHandler);
            off(ownerDocument, 'touchmove', this._delayedDragTouchMoveHandler);
            off(ownerDocument, 'pointermove', this._delayedDragTouchMoveHandler);
        },
        _triggerDragStart: function _triggerDragStart( /** Event */ evt, /** Touch */ touch) {
            touch = touch || evt.pointerType == 'touch' && evt;
            if (!this.nativeDraggable || touch) {
                if (this.options.supportPointer) {
                    on(document, 'pointermove', this._onTouchMove);
                } else if (touch) {
                    on(document, 'touchmove', this._onTouchMove);
                } else {
                    on(document, 'mousemove', this._onTouchMove);
                }
            } else {
                on(dragEl, 'dragend', this);
                on(rootEl, 'dragstart', this._onDragStart);
            }
            try {
                if (document.selection) {
                    _nextTick(function() {
                        document.selection.empty();
                    });
                } else {
                    window.getSelection().removeAllRanges();
                }
            } catch (err) {}
        },
        _dragStarted: function _dragStarted(fallback, evt) {
            awaitingDragStarted = false;
            if (rootEl && dragEl) {
                pluginEvent('dragStarted', this, {
                    evt: evt
                });
                if (this.nativeDraggable) {
                    on(document, 'dragover', _checkOutsideTargetEl);
                }
                var options = this.options;

                // Apply effect
                !fallback && toggleClass(dragEl, options.dragClass, false);
                toggleClass(dragEl, options.ghostClass, true);
                Sortable.active = this;
                fallback && this._appendGhost();

                // Drag start event
                _dispatchEvent({
                    sortable: this,
                    name: 'start',
                    originalEvent: evt
                });
            } else {
                this._nulling();
            }
        },
        _emulateDragOver: function _emulateDragOver() {
            if (touchEvt) {
                this._lastX = touchEvt.clientX;
                this._lastY = touchEvt.clientY;
                _hideGhostForTarget();
                var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
                var parent = target;
                while (target && target.shadowRoot) {
                    target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
                    if (target === parent) break;
                    parent = target;
                }
                dragEl.parentNode[expando]._isOutsideThisEl(target);
                if (parent) {
                    do {
                        if (parent[expando]) {
                            var inserted = void 0;
                            inserted = parent[expando]._onDragOver({
                                clientX: touchEvt.clientX,
                                clientY: touchEvt.clientY,
                                target: target,
                                rootEl: parent
                            });
                            if (inserted && !this.options.dragoverBubble) {
                                break;
                            }
                        }
                        target = parent; // store last element
                    }
                    /* jshint boss:true */
                    while (parent = getParentOrHost(parent));
                }
                _unhideGhostForTarget();
            }
        },
        _onTouchMove: function _onTouchMove( /**TouchEvent*/ evt) {
            if (tapEvt) {
                var options = this.options,
                    fallbackTolerance = options.fallbackTolerance,
                    fallbackOffset = options.fallbackOffset,
                    touch = evt.touches ? evt.touches[0] : evt,
                    ghostMatrix = ghostEl && matrix(ghostEl, true),
                    scaleX = ghostEl && ghostMatrix && ghostMatrix.a,
                    scaleY = ghostEl && ghostMatrix && ghostMatrix.d,
                    relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent),
                    dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1),
                    dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1);

                // only set the status to dragging, when we are actually dragging
                if (!Sortable.active && !awaitingDragStarted) {
                    if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) {
                        return;
                    }
                    this._onDragStart(evt, true);
                }
                if (ghostEl) {
                    if (ghostMatrix) {
                        ghostMatrix.e += dx - (lastDx || 0);
                        ghostMatrix.f += dy - (lastDy || 0);
                    } else {
                        ghostMatrix = {
                            a: 1,
                            b: 0,
                            c: 0,
                            d: 1,
                            e: dx,
                            f: dy
                        };
                    }
                    var cssMatrix = "matrix(".concat(ghostMatrix.a, ",").concat(ghostMatrix.b, ",").concat(ghostMatrix.c, ",").concat(ghostMatrix.d, ",").concat(ghostMatrix.e, ",").concat(ghostMatrix.f, ")");
                    css(ghostEl, 'webkitTransform', cssMatrix);
                    css(ghostEl, 'mozTransform', cssMatrix);
                    css(ghostEl, 'msTransform', cssMatrix);
                    css(ghostEl, 'transform', cssMatrix);
                    lastDx = dx;
                    lastDy = dy;
                    touchEvt = touch;
                }
                evt.cancelable && evt.preventDefault();
            }
        },
        _appendGhost: function _appendGhost() {
            // Bug if using scale(): https://stackoverflow.com/questions/2637058
            // Not being adjusted for
            if (!ghostEl) {
                var container = this.options.fallbackOnBody ? document.body : rootEl,
                    rect = getRect(dragEl, true, PositionGhostAbsolutely, true, container),
                    options = this.options;

                // Position absolutely
                if (PositionGhostAbsolutely) {
                    // Get relatively positioned parent
                    ghostRelativeParent = container;
                    while (css(ghostRelativeParent, 'position') === 'static' && css(ghostRelativeParent, 'transform') === 'none' && ghostRelativeParent !== document) {
                        ghostRelativeParent = ghostRelativeParent.parentNode;
                    }
                    if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) {
                        if (ghostRelativeParent === document) ghostRelativeParent = getWindowScrollingElement();
                        rect.top += ghostRelativeParent.scrollTop;
                        rect.left += ghostRelativeParent.scrollLeft;
                    } else {
                        ghostRelativeParent = getWindowScrollingElement();
                    }
                    ghostRelativeParentInitialScroll = getRelativeScrollOffset(ghostRelativeParent);
                }
                ghostEl = dragEl.cloneNode(true);
                toggleClass(ghostEl, options.ghostClass, false);
                toggleClass(ghostEl, options.fallbackClass, true);
                toggleClass(ghostEl, options.dragClass, true);
                css(ghostEl, 'transition', '');
                css(ghostEl, 'transform', '');
                css(ghostEl, 'box-sizing', 'border-box');
                css(ghostEl, 'margin', 0);
                css(ghostEl, 'top', rect.top);
                css(ghostEl, 'left', rect.left);
                css(ghostEl, 'width', rect.width);
                css(ghostEl, 'height', rect.height);
                css(ghostEl, 'opacity', '0.8');
                css(ghostEl, 'position', PositionGhostAbsolutely ? 'absolute' : 'fixed');
                css(ghostEl, 'zIndex', '100000');
                css(ghostEl, 'pointerEvents', 'none');
                Sortable.ghost = ghostEl;
                container.appendChild(ghostEl);

                // Set transform-origin
                css(ghostEl, 'transform-origin', tapDistanceLeft / parseInt(ghostEl.style.width) * 100 + '% ' + tapDistanceTop / parseInt(ghostEl.style.height) * 100 + '%');
            }
        },
        _onDragStart: function _onDragStart( /**Event*/ evt, /**boolean*/ fallback) {
            var _this = this;
            var dataTransfer = evt.dataTransfer;
            var options = _this.options;
            pluginEvent('dragStart', this, {
                evt: evt
            });
            if (Sortable.eventCanceled) {
                this._onDrop();
                return;
            }
            pluginEvent('setupClone', this);
            if (!Sortable.eventCanceled) {
                cloneEl = clone(dragEl);
                cloneEl.removeAttribute("id");
                cloneEl.draggable = false;
                cloneEl.style['will-change'] = '';
                this._hideClone();
                toggleClass(cloneEl, this.options.chosenClass, false);
                Sortable.clone = cloneEl;
            }

            // #1143: IFrame support workaround
            _this.cloneId = _nextTick(function() {
                pluginEvent('clone', _this);
                if (Sortable.eventCanceled) return;
                if (!_this.options.removeCloneOnHide) {
                    rootEl.insertBefore(cloneEl, dragEl);
                }
                _this._hideClone();
                _dispatchEvent({
                    sortable: _this,
                    name: 'clone'
                });
            });
            !fallback && toggleClass(dragEl, options.dragClass, true);

            // Set proper drop events
            if (fallback) {
                ignoreNextClick = true;
                _this._loopId = setInterval(_this._emulateDragOver, 50);
            } else {
                // Undo what was set in _prepareDragStart before drag started
                off(document, 'mouseup', _this._onDrop);
                off(document, 'touchend', _this._onDrop);
                off(document, 'touchcancel', _this._onDrop);
                if (dataTransfer) {
                    dataTransfer.effectAllowed = 'move';
                    options.setData && options.setData.call(_this, dataTransfer, dragEl);
                }
                on(document, 'drop', _this);

                // #1276 fix:
                css(dragEl, 'transform', 'translateZ(0)');
            }
            awaitingDragStarted = true;
            _this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt));
            on(document, 'selectstart', _this);
            moved = true;
            window.getSelection().removeAllRanges();
            if (Safari) {
                css(document.body, 'user-select', 'none');
            }
        },
        // Returns true - if no further action is needed (either inserted or another condition)
        _onDragOver: function _onDragOver( /**Event*/ evt) {
            var el = this.el,
                target = evt.target,
                dragRect,
                targetRect,
                revert,
                options = this.options,
                group = options.group,
                activeSortable = Sortable.active,
                isOwner = activeGroup === group,
                canSort = options.sort,
                fromSortable = putSortable || activeSortable,
                vertical,
                _this = this,
                completedFired = false;
            if (_silent) return;

            function dragOverEvent(name, extra) {
                pluginEvent(name, _this, _objectSpread2({
                    evt: evt,
                    isOwner: isOwner,
                    axis: vertical ? 'vertical' : 'horizontal',
                    revert: revert,
                    dragRect: dragRect,
                    targetRect: targetRect,
                    canSort: canSort,
                    fromSortable: fromSortable,
                    target: target,
                    completed: completed,
                    onMove: function onMove(target, after) {
                        return _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after);
                    },
                    changed: changed
                }, extra));
            }

            // Capture animation state
            function capture() {
                dragOverEvent('dragOverAnimationCapture');
                _this.captureAnimationState();
                if (_this !== fromSortable) {
                    fromSortable.captureAnimationState();
                }
            }

            // Return invocation when dragEl is inserted (or completed)
            function completed(insertion) {
                dragOverEvent('dragOverCompleted', {
                    insertion: insertion
                });
                if (insertion) {
                    // Clones must be hidden before folding animation to capture dragRectAbsolute properly
                    if (isOwner) {
                        activeSortable._hideClone();
                    } else {
                        activeSortable._showClone(_this);
                    }
                    if (_this !== fromSortable) {
                        // Set ghost class to new sortable's ghost class
                        toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false);
                        toggleClass(dragEl, options.ghostClass, true);
                    }
                    if (putSortable !== _this && _this !== Sortable.active) {
                        putSortable = _this;
                    } else if (_this === Sortable.active && putSortable) {
                        putSortable = null;
                    }

                    // Animation
                    if (fromSortable === _this) {
                        _this._ignoreWhileAnimating = target;
                    }
                    _this.animateAll(function() {
                        dragOverEvent('dragOverAnimationComplete');
                        _this._ignoreWhileAnimating = null;
                    });
                    if (_this !== fromSortable) {
                        fromSortable.animateAll();
                        fromSortable._ignoreWhileAnimating = null;
                    }
                }

                // Null lastTarget if it is not inside a previously swapped element
                if (target === dragEl && !dragEl.animated || target === el && !target.animated) {
                    lastTarget = null;
                }

                // no bubbling and not fallback
                if (!options.dragoverBubble && !evt.rootEl && target !== document) {
                    dragEl.parentNode[expando]._isOutsideThisEl(evt.target);

                    // Do not detect for empty insert if already inserted
                    !insertion && nearestEmptyInsertDetectEvent(evt);
                }!options.dragoverBubble && evt.stopPropagation && evt.stopPropagation();
                return completedFired = true;
            }

            // Call when dragEl has been inserted
            function changed() {
                newIndex = index(dragEl);
                newDraggableIndex = index(dragEl, options.draggable);
                _dispatchEvent({
                    sortable: _this,
                    name: 'change',
                    toEl: el,
                    newIndex: newIndex,
                    newDraggableIndex: newDraggableIndex,
                    originalEvent: evt
                });
            }
            if (evt.preventDefault !== void 0) {
                evt.cancelable && evt.preventDefault();
            }
            target = closest(target, options.draggable, el, true);
            dragOverEvent('dragOver');
            if (Sortable.eventCanceled) return completedFired;
            if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) {
                return completed(false);
            }
            ignoreNextClick = false;
            if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = parentEl !== rootEl) // Reverting item into the original list
                    :
                    putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) {
                vertical = this._getDirection(evt, target) === 'vertical';
                dragRect = getRect(dragEl);
                dragOverEvent('dragOverValid');
                if (Sortable.eventCanceled) return completedFired;
                if (revert) {
                    parentEl = rootEl; // actualization
                    capture();
                    this._hideClone();
                    dragOverEvent('revert');
                    if (!Sortable.eventCanceled) {
                        if (nextEl) {
                            rootEl.insertBefore(dragEl, nextEl);
                        } else {
                            rootEl.appendChild(dragEl);
                        }
                    }
                    return completed(true);
                }
                var elLastChild = lastChild(el, options.draggable);
                if (!elLastChild || _ghostIsLast(evt, vertical, this) && !elLastChild.animated) {
                    // Insert to end of list

                    // If already at end of list: Do not insert
                    if (elLastChild === dragEl) {
                        return completed(false);
                    }

                    // if there is a last element, it is the target
                    if (elLastChild && el === evt.target) {
                        target = elLastChild;
                    }
                    if (target) {
                        targetRect = getRect(target);
                    }
                    if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) {
                        capture();
                        if (elLastChild && elLastChild.nextSibling) {
                            // the last draggable element is not the last node
                            el.insertBefore(dragEl, elLastChild.nextSibling);
                        } else {
                            el.appendChild(dragEl);
                        }
                        parentEl = el; // actualization

                        changed();
                        return completed(true);
                    }
                } else if (elLastChild && _ghostIsFirst(evt, vertical, this)) {
                    // Insert to start of list
                    var firstChild = getChild(el, 0, options, true);
                    if (firstChild === dragEl) {
                        return completed(false);
                    }
                    target = firstChild;
                    targetRect = getRect(target);
                    if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, false) !== false) {
                        capture();
                        el.insertBefore(dragEl, firstChild);
                        parentEl = el; // actualization

                        changed();
                        return completed(true);
                    }
                } else if (target.parentNode === el) {
                    targetRect = getRect(target);
                    var direction = 0,
                        targetBeforeFirstSwap,
                        differentLevel = dragEl.parentNode !== el,
                        differentRowCol = !_dragElInRowColumn(dragEl.animated && dragEl.toRect || dragRect, target.animated && target.toRect || targetRect, vertical),
                        side1 = vertical ? 'top' : 'left',
                        scrolledPastTop = isScrolledPast(target, 'top', 'top') || isScrolledPast(dragEl, 'top', 'top'),
                        scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0;
                    if (lastTarget !== target) {
                        targetBeforeFirstSwap = targetRect[side1];
                        pastFirstInvertThresh = false;
                        isCircumstantialInvert = !differentRowCol && options.invertSwap || differentLevel;
                    }
                    direction = _getSwapDirection(evt, target, targetRect, vertical, differentRowCol ? 1 : options.swapThreshold, options.invertedSwapThreshold == null ? options.swapThreshold : options.invertedSwapThreshold, isCircumstantialInvert, lastTarget === target);
                    var sibling;
                    if (direction !== 0) {
                        // Check if target is beside dragEl in respective direction (ignoring hidden elements)
                        var dragIndex = index(dragEl);
                        do {
                            dragIndex -= direction;
                            sibling = parentEl.children[dragIndex];
                        } while (sibling && (css(sibling, 'display') === 'none' || sibling === ghostEl));
                    }
                    // If dragEl is already beside target: Do not insert
                    if (direction === 0 || sibling === target) {
                        return completed(false);
                    }
                    lastTarget = target;
                    lastDirection = direction;
                    var nextSibling = target.nextElementSibling,
                        after = false;
                    after = direction === 1;
                    var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
                    if (moveVector !== false) {
                        if (moveVector === 1 || moveVector === -1) {
                            after = moveVector === 1;
                        }
                        _silent = true;
                        setTimeout(_unsilent, 30);
                        capture();
                        if (after && !nextSibling) {
                            el.appendChild(dragEl);
                        } else {
                            target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
                        }

                        // Undo chrome's scroll adjustment (has no effect on other browsers)
                        if (scrolledPastTop) {
                            scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop);
                        }
                        parentEl = dragEl.parentNode; // actualization

                        // must be done before animation
                        if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) {
                            targetMoveDistance = Math.abs(targetBeforeFirstSwap - getRect(target)[side1]);
                        }
                        changed();
                        return completed(true);
                    }
                }
                if (el.contains(dragEl)) {
                    return completed(false);
                }
            }
            return false;
        },
        _ignoreWhileAnimating: null,
        _offMoveEvents: function _offMoveEvents() {
            off(document, 'mousemove', this._onTouchMove);
            off(document, 'touchmove', this._onTouchMove);
            off(document, 'pointermove', this._onTouchMove);
            off(document, 'dragover', nearestEmptyInsertDetectEvent);
            off(document, 'mousemove', nearestEmptyInsertDetectEvent);
            off(document, 'touchmove', nearestEmptyInsertDetectEvent);
        },
        _offUpEvents: function _offUpEvents() {
            var ownerDocument = this.el.ownerDocument;
            off(ownerDocument, 'mouseup', this._onDrop);
            off(ownerDocument, 'touchend', this._onDrop);
            off(ownerDocument, 'pointerup', this._onDrop);
            off(ownerDocument, 'pointercancel', this._onDrop);
            off(ownerDocument, 'touchcancel', this._onDrop);
            off(document, 'selectstart', this);
        },
        _onDrop: function _onDrop( /**Event*/ evt) {
            var el = this.el,
                options = this.options;

            // Get the index of the dragged element within its parent
            newIndex = index(dragEl);
            newDraggableIndex = index(dragEl, options.draggable);
            pluginEvent('drop', this, {
                evt: evt
            });
            parentEl = dragEl && dragEl.parentNode;

            // Get again after plugin event
            newIndex = index(dragEl);
            newDraggableIndex = index(dragEl, options.draggable);
            if (Sortable.eventCanceled) {
                this._nulling();
                return;
            }
            awaitingDragStarted = false;
            isCircumstantialInvert = false;
            pastFirstInvertThresh = false;
            clearInterval(this._loopId);
            clearTimeout(this._dragStartTimer);
            _cancelNextTick(this.cloneId);
            _cancelNextTick(this._dragStartId);

            // Unbind events
            if (this.nativeDraggable) {
                off(document, 'drop', this);
                off(el, 'dragstart', this._onDragStart);
            }
            this._offMoveEvents();
            this._offUpEvents();
            if (Safari) {
                css(document.body, 'user-select', '');
            }
            css(dragEl, 'transform', '');
            if (evt) {
                if (moved) {
                    evt.cancelable && evt.preventDefault();
                    !options.dropBubble && evt.stopPropagation();
                }
                ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
                if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') {
                    // Remove clone(s)
                    cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
                }
                if (dragEl) {
                    if (this.nativeDraggable) {
                        off(dragEl, 'dragend', this);
                    }
                    _disableDraggable(dragEl);
                    dragEl.style['will-change'] = '';

                    // Remove classes
                    // ghostClass is added in dragStarted
                    if (moved && !awaitingDragStarted) {
                        toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : this.options.ghostClass, false);
                    }
                    toggleClass(dragEl, this.options.chosenClass, false);

                    // Drag stop event
                    _dispatchEvent({
                        sortable: this,
                        name: 'unchoose',
                        toEl: parentEl,
                        newIndex: null,
                        newDraggableIndex: null,
                        originalEvent: evt
                    });
                    if (rootEl !== parentEl) {
                        if (newIndex >= 0) {
                            // Add event
                            _dispatchEvent({
                                rootEl: parentEl,
                                name: 'add',
                                toEl: parentEl,
                                fromEl: rootEl,
                                originalEvent: evt
                            });

                            // Remove event
                            _dispatchEvent({
                                sortable: this,
                                name: 'remove',
                                toEl: parentEl,
                                originalEvent: evt
                            });

                            // drag from one list and drop into another
                            _dispatchEvent({
                                rootEl: parentEl,
                                name: 'sort',
                                toEl: parentEl,
                                fromEl: rootEl,
                                originalEvent: evt
                            });
                            _dispatchEvent({
                                sortable: this,
                                name: 'sort',
                                toEl: parentEl,
                                originalEvent: evt
                            });
                        }
                        putSortable && putSortable.save();
                    } else {
                        if (newIndex !== oldIndex) {
                            if (newIndex >= 0) {
                                // drag & drop within the same list
                                _dispatchEvent({
                                    sortable: this,
                                    name: 'update',
                                    toEl: parentEl,
                                    originalEvent: evt
                                });
                                _dispatchEvent({
                                    sortable: this,
                                    name: 'sort',
                                    toEl: parentEl,
                                    originalEvent: evt
                                });
                            }
                        }
                    }
                    if (Sortable.active) {
                        /* jshint eqnull:true */
                        if (newIndex == null || newIndex === -1) {
                            newIndex = oldIndex;
                            newDraggableIndex = oldDraggableIndex;
                        }
                        _dispatchEvent({
                            sortable: this,
                            name: 'end',
                            toEl: parentEl,
                            originalEvent: evt
                        });

                        // Save sorting
                        this.save();
                    }
                }
            }
            this._nulling();
        },
        _nulling: function _nulling() {
            pluginEvent('nulling', this);
            rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable.dragged = Sortable.ghost = Sortable.clone = Sortable.active = null;
            var el = this.el;
            savedInputChecked.forEach(function(checkEl) {
                if (el.contains(checkEl)) {
                    checkEl.checked = true;
                }
            });
            savedInputChecked.length = lastDx = lastDy = 0;
        },
        handleEvent: function handleEvent( /**Event*/ evt) {
            switch (evt.type) {
                case 'drop':
                case 'dragend':
                    this._onDrop(evt);
                    break;
                case 'dragenter':
                case 'dragover':
                    if (dragEl) {
                        this._onDragOver(evt);
                        _globalDragOver(evt);
                    }
                    break;
                case 'selectstart':
                    evt.preventDefault();
                    break;
            }
        },
        /**
         * Serializes the item into an array of string.
         * @returns {String[]}
         */
        toArray: function toArray() {
            var order = [],
                el,
                children = this.el.children,
                i = 0,
                n = children.length,
                options = this.options;
            for (; i < n; i++) {
                el = children[i];
                if (closest(el, options.draggable, this.el, false)) {
                    order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
                }
            }
            return order;
        },
        /**
         * Sorts the elements according to the array.
         * @param  {String[]}  order  order of the items
         */
        sort: function sort(order, useAnimation) {
            var items = {},
                rootEl = this.el;
            this.toArray().forEach(function(id, i) {
                var el = rootEl.children[i];
                if (closest(el, this.options.draggable, rootEl, false)) {
                    items[id] = el;
                }
            }, this);
            useAnimation && this.captureAnimationState();
            order.forEach(function(id) {
                if (items[id]) {
                    rootEl.removeChild(items[id]);
                    rootEl.appendChild(items[id]);
                }
            });
            useAnimation && this.animateAll();
        },
        /**
         * Save the current sorting
         */
        save: function save() {
            var store = this.options.store;
            store && store.set && store.set(this);
        },
        /**
         * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
         * @param   {HTMLElement}  el
         * @param   {String}       [selector]  default: `options.draggable`
         * @returns {HTMLElement|null}
         */
        closest: function closest$1(el, selector) {
            return closest(el, selector || this.options.draggable, this.el, false);
        },
        /**
         * Set/get option
         * @param   {string} name
         * @param   {*}      [value]
         * @returns {*}
         */
        option: function option(name, value) {
            var options = this.options;
            if (value === void 0) {
                return options[name];
            } else {
                var modifiedValue = PluginManager.modifyOption(this, name, value);
                if (typeof modifiedValue !== 'undefined') {
                    options[name] = modifiedValue;
                } else {
                    options[name] = value;
                }
                if (name === 'group') {
                    _prepareGroup(options);
                }
            }
        },
        /**
         * Destroy
         */
        destroy: function destroy() {
            pluginEvent('destroy', this);
            var el = this.el;
            el[expando] = null;
            off(el, 'mousedown', this._onTapStart);
            off(el, 'touchstart', this._onTapStart);
            off(el, 'pointerdown', this._onTapStart);
            if (this.nativeDraggable) {
                off(el, 'dragover', this);
                off(el, 'dragenter', this);
            }
            // Remove draggable attributes
            Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function(el) {
                el.removeAttribute('draggable');
            });
            this._onDrop();
            this._disableDelayedDragEvents();
            sortables.splice(sortables.indexOf(this.el), 1);
            this.el = el = null;
        },
        _hideClone: function _hideClone() {
            if (!cloneHidden) {
                pluginEvent('hideClone', this);
                if (Sortable.eventCanceled) return;
                css(cloneEl, 'display', 'none');
                if (this.options.removeCloneOnHide && cloneEl.parentNode) {
                    cloneEl.parentNode.removeChild(cloneEl);
                }
                cloneHidden = true;
            }
        },
        _showClone: function _showClone(putSortable) {
            if (putSortable.lastPutMode !== 'clone') {
                this._hideClone();
                return;
            }
            if (cloneHidden) {
                pluginEvent('showClone', this);
                if (Sortable.eventCanceled) return;

                // show clone at dragEl or original position
                if (dragEl.parentNode == rootEl && !this.options.group.revertClone) {
                    rootEl.insertBefore(cloneEl, dragEl);
                } else if (nextEl) {
                    rootEl.insertBefore(cloneEl, nextEl);
                } else {
                    rootEl.appendChild(cloneEl);
                }
                if (this.options.group.revertClone) {
                    this.animate(dragEl, cloneEl);
                }
                css(cloneEl, 'display', '');
                cloneHidden = false;
            }
        }
    };

    function _globalDragOver( /**Event*/ evt) {
        if (evt.dataTransfer) {
            evt.dataTransfer.dropEffect = 'move';
        }
        evt.cancelable && evt.preventDefault();
    }

    function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) {
        var evt,
            sortable = fromEl[expando],
            onMoveFn = sortable.options.onMove,
            retVal;
        // Support for new CustomEvent feature
        if (window.CustomEvent && !IE11OrLess && !Edge) {
            evt = new CustomEvent('move', {
                bubbles: true,
                cancelable: true
            });
        } else {
            evt = document.createEvent('Event');
            evt.initEvent('move', true, true);
        }
        evt.to = toEl;
        evt.from = fromEl;
        evt.dragged = dragEl;
        evt.draggedRect = dragRect;
        evt.related = targetEl || toEl;
        evt.relatedRect = targetRect || getRect(toEl);
        evt.willInsertAfter = willInsertAfter;
        evt.originalEvent = originalEvent;
        fromEl.dispatchEvent(evt);
        if (onMoveFn) {
            retVal = onMoveFn.call(sortable, evt, originalEvent);
        }
        return retVal;
    }

    function _disableDraggable(el) {
        el.draggable = false;
    }

    function _unsilent() {
        _silent = false;
    }

    function _ghostIsFirst(evt, vertical, sortable) {
        var firstElRect = getRect(getChild(sortable.el, 0, sortable.options, true));
        var childContainingRect = getChildContainingRectFromElement(sortable.el, sortable.options, ghostEl);
        var spacer = 10;
        return vertical ? evt.clientX < childContainingRect.left - spacer || evt.clientY < firstElRect.top && evt.clientX < firstElRect.right : evt.clientY < childContainingRect.top - spacer || evt.clientY < firstElRect.bottom && evt.clientX < firstElRect.left;
    }

    function _ghostIsLast(evt, vertical, sortable) {
        var lastElRect = getRect(lastChild(sortable.el, sortable.options.draggable));
        var childContainingRect = getChildContainingRectFromElement(sortable.el, sortable.options, ghostEl);
        var spacer = 10;
        return vertical ? evt.clientX > childContainingRect.right + spacer || evt.clientY > lastElRect.bottom && evt.clientX > lastElRect.left : evt.clientY > childContainingRect.bottom + spacer || evt.clientX > lastElRect.right && evt.clientY > lastElRect.top;
    }

    function _getSwapDirection(evt, target, targetRect, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) {
        var mouseOnAxis = vertical ? evt.clientY : evt.clientX,
            targetLength = vertical ? targetRect.height : targetRect.width,
            targetS1 = vertical ? targetRect.top : targetRect.left,
            targetS2 = vertical ? targetRect.bottom : targetRect.right,
            invert = false;
        if (!invertSwap) {
            // Never invert or create dragEl shadow when target movemenet causes mouse to move past the end of regular swapThreshold
            if (isLastTarget && targetMoveDistance < targetLength * swapThreshold) {
                // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2
                // check if past first invert threshold on side opposite of lastDirection
                if (!pastFirstInvertThresh && (lastDirection === 1 ? mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2 : mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2)) {
                    // past first invert threshold, do not restrict inverted threshold to dragEl shadow
                    pastFirstInvertThresh = true;
                }
                if (!pastFirstInvertThresh) {
                    // dragEl shadow (target move distance shadow)
                    if (lastDirection === 1 ? mouseOnAxis < targetS1 + targetMoveDistance // over dragEl shadow
                        :
                        mouseOnAxis > targetS2 - targetMoveDistance) {
                        return -lastDirection;
                    }
                } else {
                    invert = true;
                }
            } else {
                // Regular
                if (mouseOnAxis > targetS1 + targetLength * (1 - swapThreshold) / 2 && mouseOnAxis < targetS2 - targetLength * (1 - swapThreshold) / 2) {
                    return _getInsertDirection(target);
                }
            }
        }
        invert = invert || invertSwap;
        if (invert) {
            // Invert of regular
            if (mouseOnAxis < targetS1 + targetLength * invertedSwapThreshold / 2 || mouseOnAxis > targetS2 - targetLength * invertedSwapThreshold / 2) {
                return mouseOnAxis > targetS1 + targetLength / 2 ? 1 : -1;
            }
        }
        return 0;
    }

    /**
     * Gets the direction dragEl must be swapped relative to target in order to make it
     * seem that dragEl has been "inserted" into that element's position
     * @param  {HTMLElement} target       The target whose position dragEl is being inserted at
     * @return {Number}                   Direction dragEl must be swapped
     */
    function _getInsertDirection(target) {
        if (index(dragEl) < index(target)) {
            return 1;
        } else {
            return -1;
        }
    }

    /**
     * Generate id
     * @param   {HTMLElement} el
     * @returns {String}
     * @private
     */
    function _generateId(el) {
        var str = el.tagName + el.className + el.src + el.href + el.textContent,
            i = str.length,
            sum = 0;
        while (i--) {
            sum += str.charCodeAt(i);
        }
        return sum.toString(36);
    }

    function _saveInputCheckedState(root) {
        savedInputChecked.length = 0;
        var inputs = root.getElementsByTagName('input');
        var idx = inputs.length;
        while (idx--) {
            var el = inputs[idx];
            el.checked && savedInputChecked.push(el);
        }
    }

    function _nextTick(fn) {
        return setTimeout(fn, 0);
    }

    function _cancelNextTick(id) {
        return clearTimeout(id);
    }

    // Fixed #973:
    if (documentExists) {
        on(document, 'touchmove', function(evt) {
            if ((Sortable.active || awaitingDragStarted) && evt.cancelable) {
                evt.preventDefault();
            }
        });
    }

    // Export utils
    Sortable.utils = {
        on: on,
        off: off,
        css: css,
        find: find,
        is: function is(el, selector) {
            return !!closest(el, selector, el, false);
        },
        extend: extend,
        throttle: throttle,
        closest: closest,
        toggleClass: toggleClass,
        clone: clone,
        index: index,
        nextTick: _nextTick,
        cancelNextTick: _cancelNextTick,
        detectDirection: _detectDirection,
        getChild: getChild,
        expando: expando
    };

    /**
     * Get the Sortable instance of an element
     * @param  {HTMLElement} element The element
     * @return {Sortable|undefined}         The instance of Sortable
     */
    Sortable.get = function(element) {
        return element[expando];
    };

    /**
     * Mount a plugin to Sortable
     * @param  {...SortablePlugin|SortablePlugin[]} plugins       Plugins being mounted
     */
    Sortable.mount = function() {
        for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) {
            plugins[_key] = arguments[_key];
        }
        if (plugins[0].constructor === Array) plugins = plugins[0];
        plugins.forEach(function(plugin) {
            if (!plugin.prototype || !plugin.prototype.constructor) {
                throw "Sortable: Mounted plugin must be a constructor function, not ".concat({}.toString.call(plugin));
            }
            if (plugin.utils) Sortable.utils = _objectSpread2(_objectSpread2({}, Sortable.utils), plugin.utils);
            PluginManager.mount(plugin);
        });
    };

    /**
     * Create sortable instance
     * @param {HTMLElement}  el
     * @param {Object}      [options]
     */
    Sortable.create = function(el, options) {
        return new Sortable(el, options);
    };

    // Export
    Sortable.version = version;

    var autoScrolls = [],
        scrollEl,
        scrollRootEl,
        scrolling = false,
        lastAutoScrollX,
        lastAutoScrollY,
        touchEvt$1,
        pointerElemChangedInterval;

    function AutoScrollPlugin() {
        function AutoScroll() {
            this.defaults = {
                scroll: true,
                forceAutoScrollFallback: false,
                scrollSensitivity: 30,
                scrollSpeed: 10,
                bubbleScroll: true
            };

            // Bind all private methods
            for (var fn in this) {
                if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
                    this[fn] = this[fn].bind(this);
                }
            }
        }
        AutoScroll.prototype = {
            dragStarted: function dragStarted(_ref) {
                var originalEvent = _ref.originalEvent;
                if (this.sortable.nativeDraggable) {
                    on(document, 'dragover', this._handleAutoScroll);
                } else {
                    if (this.options.supportPointer) {
                        on(document, 'pointermove', this._handleFallbackAutoScroll);
                    } else if (originalEvent.touches) {
                        on(document, 'touchmove', this._handleFallbackAutoScroll);
                    } else {
                        on(document, 'mousemove', this._handleFallbackAutoScroll);
                    }
                }
            },
            dragOverCompleted: function dragOverCompleted(_ref2) {
                var originalEvent = _ref2.originalEvent;
                // For when bubbling is canceled and using fallback (fallback 'touchmove' always reached)
                if (!this.options.dragOverBubble && !originalEvent.rootEl) {
                    this._handleAutoScroll(originalEvent);
                }
            },
            drop: function drop() {
                if (this.sortable.nativeDraggable) {
                    off(document, 'dragover', this._handleAutoScroll);
                } else {
                    off(document, 'pointermove', this._handleFallbackAutoScroll);
                    off(document, 'touchmove', this._handleFallbackAutoScroll);
                    off(document, 'mousemove', this._handleFallbackAutoScroll);
                }
                clearPointerElemChangedInterval();
                clearAutoScrolls();
                cancelThrottle();
            },
            nulling: function nulling() {
                touchEvt$1 = scrollRootEl = scrollEl = scrolling = pointerElemChangedInterval = lastAutoScrollX = lastAutoScrollY = null;
                autoScrolls.length = 0;
            },
            _handleFallbackAutoScroll: function _handleFallbackAutoScroll(evt) {
                this._handleAutoScroll(evt, true);
            },
            _handleAutoScroll: function _handleAutoScroll(evt, fallback) {
                var _this = this;
                var x = (evt.touches ? evt.touches[0] : evt).clientX,
                    y = (evt.touches ? evt.touches[0] : evt).clientY,
                    elem = document.elementFromPoint(x, y);
                touchEvt$1 = evt;

                // IE does not seem to have native autoscroll,
                // Edge's autoscroll seems too conditional,
                // MACOS Safari does not have autoscroll,
                // Firefox and Chrome are good
                if (fallback || this.options.forceAutoScrollFallback || Edge || IE11OrLess || Safari) {
                    autoScroll(evt, this.options, elem, fallback);

                    // Listener for pointer element change
                    var ogElemScroller = getParentAutoScrollElement(elem, true);
                    if (scrolling && (!pointerElemChangedInterval || x !== lastAutoScrollX || y !== lastAutoScrollY)) {
                        pointerElemChangedInterval && clearPointerElemChangedInterval();
                        // Detect for pointer elem change, emulating native DnD behaviour
                        pointerElemChangedInterval = setInterval(function() {
                            var newElem = getParentAutoScrollElement(document.elementFromPoint(x, y), true);
                            if (newElem !== ogElemScroller) {
                                ogElemScroller = newElem;
                                clearAutoScrolls();
                            }
                            autoScroll(evt, _this.options, newElem, fallback);
                        }, 10);
                        lastAutoScrollX = x;
                        lastAutoScrollY = y;
                    }
                } else {
                    // if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll
                    if (!this.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) {
                        clearAutoScrolls();
                        return;
                    }
                    autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false);
                }
            }
        };
        return _extends(AutoScroll, {
            pluginName: 'scroll',
            initializeByDefault: true
        });
    }

    function clearAutoScrolls() {
        autoScrolls.forEach(function(autoScroll) {
            clearInterval(autoScroll.pid);
        });
        autoScrolls = [];
    }

    function clearPointerElemChangedInterval() {
        clearInterval(pointerElemChangedInterval);
    }
    var autoScroll = throttle(function(evt, options, rootEl, isFallback) {
        // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
        if (!options.scroll) return;
        var x = (evt.touches ? evt.touches[0] : evt).clientX,
            y = (evt.touches ? evt.touches[0] : evt).clientY,
            sens = options.scrollSensitivity,
            speed = options.scrollSpeed,
            winScroller = getWindowScrollingElement();
        var scrollThisInstance = false,
            scrollCustomFn;

        // New scroll root, set scrollEl
        if (scrollRootEl !== rootEl) {
            scrollRootEl = rootEl;
            clearAutoScrolls();
            scrollEl = options.scroll;
            scrollCustomFn = options.scrollFn;
            if (scrollEl === true) {
                scrollEl = getParentAutoScrollElement(rootEl, true);
            }
        }
        var layersOut = 0;
        var currentParent = scrollEl;
        do {
            var el = currentParent,
                rect = getRect(el),
                top = rect.top,
                bottom = rect.bottom,
                left = rect.left,
                right = rect.right,
                width = rect.width,
                height = rect.height,
                canScrollX = void 0,
                canScrollY = void 0,
                scrollWidth = el.scrollWidth,
                scrollHeight = el.scrollHeight,
                elCSS = css(el),
                scrollPosX = el.scrollLeft,
                scrollPosY = el.scrollTop;
            if (el === winScroller) {
                canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll' || elCSS.overflowX === 'visible');
                canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll' || elCSS.overflowY === 'visible');
            } else {
                canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll');
                canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll');
            }
            var vx = canScrollX && (Math.abs(right - x) <= sens && scrollPosX + width < scrollWidth) - (Math.abs(left - x) <= sens && !!scrollPosX);
            var vy = canScrollY && (Math.abs(bottom - y) <= sens && scrollPosY + height < scrollHeight) - (Math.abs(top - y) <= sens && !!scrollPosY);
            if (!autoScrolls[layersOut]) {
                for (var i = 0; i <= layersOut; i++) {
                    if (!autoScrolls[i]) {
                        autoScrolls[i] = {};
                    }
                }
            }
            if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) {
                autoScrolls[layersOut].el = el;
                autoScrolls[layersOut].vx = vx;
                autoScrolls[layersOut].vy = vy;
                clearInterval(autoScrolls[layersOut].pid);
                if (vx != 0 || vy != 0) {
                    scrollThisInstance = true;
                    /* jshint loopfunc:true */
                    autoScrolls[layersOut].pid = setInterval(function() {
                        // emulate drag over during autoscroll (fallback), emulating native DnD behaviour
                        if (isFallback && this.layer === 0) {
                            Sortable.active._onTouchMove(touchEvt$1); // To move ghost if it is positioned absolutely
                        }
                        var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0;
                        var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0;
                        if (typeof scrollCustomFn === 'function') {
                            if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== 'continue') {
                                return;
                            }
                        }
                        scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY);
                    }.bind({
                        layer: layersOut
                    }), 24);
                }
            }
            layersOut++;
        } while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false)));
        scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not
    }, 30);

    var drop = function drop(_ref) {
        var originalEvent = _ref.originalEvent,
            putSortable = _ref.putSortable,
            dragEl = _ref.dragEl,
            activeSortable = _ref.activeSortable,
            dispatchSortableEvent = _ref.dispatchSortableEvent,
            hideGhostForTarget = _ref.hideGhostForTarget,
            unhideGhostForTarget = _ref.unhideGhostForTarget;
        if (!originalEvent) return;
        var toSortable = putSortable || activeSortable;
        hideGhostForTarget();
        var touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent;
        var target = document.elementFromPoint(touch.clientX, touch.clientY);
        unhideGhostForTarget();
        if (toSortable && !toSortable.el.contains(target)) {
            dispatchSortableEvent('spill');
            this.onSpill({
                dragEl: dragEl,
                putSortable: putSortable
            });
        }
    };

    function Revert() {}
    Revert.prototype = {
        startIndex: null,
        dragStart: function dragStart(_ref2) {
            var oldDraggableIndex = _ref2.oldDraggableIndex;
            this.startIndex = oldDraggableIndex;
        },
        onSpill: function onSpill(_ref3) {
            var dragEl = _ref3.dragEl,
                putSortable = _ref3.putSortable;
            this.sortable.captureAnimationState();
            if (putSortable) {
                putSortable.captureAnimationState();
            }
            var nextSibling = getChild(this.sortable.el, this.startIndex, this.options);
            if (nextSibling) {
                this.sortable.el.insertBefore(dragEl, nextSibling);
            } else {
                this.sortable.el.appendChild(dragEl);
            }
            this.sortable.animateAll();
            if (putSortable) {
                putSortable.animateAll();
            }
        },
        drop: drop
    };
    _extends(Revert, {
        pluginName: 'revertOnSpill'
    });

    function Remove() {}
    Remove.prototype = {
        onSpill: function onSpill(_ref4) {
            var dragEl = _ref4.dragEl,
                putSortable = _ref4.putSortable;
            var parentSortable = putSortable || this.sortable;
            parentSortable.captureAnimationState();
            dragEl.parentNode && dragEl.parentNode.removeChild(dragEl);
            parentSortable.animateAll();
        },
        drop: drop
    };
    _extends(Remove, {
        pluginName: 'removeOnSpill'
    });

    var lastSwapEl;

    function SwapPlugin() {
        function Swap() {
            this.defaults = {
                swapClass: 'sortable-swap-highlight'
            };
        }
        Swap.prototype = {
            dragStart: function dragStart(_ref) {
                var dragEl = _ref.dragEl;
                lastSwapEl = dragEl;
            },
            dragOverValid: function dragOverValid(_ref2) {
                var completed = _ref2.completed,
                    target = _ref2.target,
                    onMove = _ref2.onMove,
                    activeSortable = _ref2.activeSortable,
                    changed = _ref2.changed,
                    cancel = _ref2.cancel;
                if (!activeSortable.options.swap) return;
                var el = this.sortable.el,
                    options = this.options;
                if (target && target !== el) {
                    var prevSwapEl = lastSwapEl;
                    if (onMove(target) !== false) {
                        toggleClass(target, options.swapClass, true);
                        lastSwapEl = target;
                    } else {
                        lastSwapEl = null;
                    }
                    if (prevSwapEl && prevSwapEl !== lastSwapEl) {
                        toggleClass(prevSwapEl, options.swapClass, false);
                    }
                }
                changed();
                completed(true);
                cancel();
            },
            drop: function drop(_ref3) {
                var activeSortable = _ref3.activeSortable,
                    putSortable = _ref3.putSortable,
                    dragEl = _ref3.dragEl;
                var toSortable = putSortable || this.sortable;
                var options = this.options;
                lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false);
                if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) {
                    if (dragEl !== lastSwapEl) {
                        toSortable.captureAnimationState();
                        if (toSortable !== activeSortable) activeSortable.captureAnimationState();
                        swapNodes(dragEl, lastSwapEl);
                        toSortable.animateAll();
                        if (toSortable !== activeSortable) activeSortable.animateAll();
                    }
                }
            },
            nulling: function nulling() {
                lastSwapEl = null;
            }
        };
        return _extends(Swap, {
            pluginName: 'swap',
            eventProperties: function eventProperties() {
                return {
                    swapItem: lastSwapEl
                };
            }
        });
    }

    function swapNodes(n1, n2) {
        var p1 = n1.parentNode,
            p2 = n2.parentNode,
            i1,
            i2;
        if (!p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1)) return;
        i1 = index(n1);
        i2 = index(n2);
        if (p1.isEqualNode(p2) && i1 < i2) {
            i2++;
        }
        p1.insertBefore(n2, p1.children[i1]);
        p2.insertBefore(n1, p2.children[i2]);
    }

    var multiDragElements = [],
        multiDragClones = [],
        lastMultiDragSelect,
        // for selection with modifier key down (SHIFT)
        multiDragSortable,
        initialFolding = false,
        // Initial multi-drag fold when drag started
        folding = false,
        // Folding any other time
        dragStarted = false,
        dragEl$1,
        clonesFromRect,
        clonesHidden;

    function MultiDragPlugin() {
        function MultiDrag(sortable) {
            // Bind all private methods
            for (var fn in this) {
                if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
                    this[fn] = this[fn].bind(this);
                }
            }
            if (!sortable.options.avoidImplicitDeselect) {
                if (sortable.options.supportPointer) {
                    on(document, 'pointerup', this._deselectMultiDrag);
                } else {
                    on(document, 'mouseup', this._deselectMultiDrag);
                    on(document, 'touchend', this._deselectMultiDrag);
                }
            }
            on(document, 'keydown', this._checkKeyDown);
            on(document, 'keyup', this._checkKeyUp);
            this.defaults = {
                selectedClass: 'sortable-selected',
                multiDragKey: null,
                avoidImplicitDeselect: false,
                setData: function setData(dataTransfer, dragEl) {
                    var data = '';
                    if (multiDragElements.length && multiDragSortable === sortable) {
                        multiDragElements.forEach(function(multiDragElement, i) {
                            data += (!i ? '' : ', ') + multiDragElement.textContent;
                        });
                    } else {
                        data = dragEl.textContent;
                    }
                    dataTransfer.setData('Text', data);
                }
            };
        }
        MultiDrag.prototype = {
            multiDragKeyDown: false,
            isMultiDrag: false,
            delayStartGlobal: function delayStartGlobal(_ref) {
                var dragged = _ref.dragEl;
                dragEl$1 = dragged;
            },
            delayEnded: function delayEnded() {
                this.isMultiDrag = ~multiDragElements.indexOf(dragEl$1);
            },
            setupClone: function setupClone(_ref2) {
                var sortable = _ref2.sortable,
                    cancel = _ref2.cancel;
                if (!this.isMultiDrag) return;
                for (var i = 0; i < multiDragElements.length; i++) {
                    multiDragClones.push(clone(multiDragElements[i]));
                    multiDragClones[i].sortableIndex = multiDragElements[i].sortableIndex;
                    multiDragClones[i].draggable = false;
                    multiDragClones[i].style['will-change'] = '';
                    toggleClass(multiDragClones[i], this.options.selectedClass, false);
                    multiDragElements[i] === dragEl$1 && toggleClass(multiDragClones[i], this.options.chosenClass, false);
                }
                sortable._hideClone();
                cancel();
            },
            clone: function clone(_ref3) {
                var sortable = _ref3.sortable,
                    rootEl = _ref3.rootEl,
                    dispatchSortableEvent = _ref3.dispatchSortableEvent,
                    cancel = _ref3.cancel;
                if (!this.isMultiDrag) return;
                if (!this.options.removeCloneOnHide) {
                    if (multiDragElements.length && multiDragSortable === sortable) {
                        insertMultiDragClones(true, rootEl);
                        dispatchSortableEvent('clone');
                        cancel();
                    }
                }
            },
            showClone: function showClone(_ref4) {
                var cloneNowShown = _ref4.cloneNowShown,
                    rootEl = _ref4.rootEl,
                    cancel = _ref4.cancel;
                if (!this.isMultiDrag) return;
                insertMultiDragClones(false, rootEl);
                multiDragClones.forEach(function(clone) {
                    css(clone, 'display', '');
                });
                cloneNowShown();
                clonesHidden = false;
                cancel();
            },
            hideClone: function hideClone(_ref5) {
                var _this = this;
                var sortable = _ref5.sortable,
                    cloneNowHidden = _ref5.cloneNowHidden,
                    cancel = _ref5.cancel;
                if (!this.isMultiDrag) return;
                multiDragClones.forEach(function(clone) {
                    css(clone, 'display', 'none');
                    if (_this.options.removeCloneOnHide && clone.parentNode) {
                        clone.parentNode.removeChild(clone);
                    }
                });
                cloneNowHidden();
                clonesHidden = true;
                cancel();
            },
            dragStartGlobal: function dragStartGlobal(_ref6) {
                var sortable = _ref6.sortable;
                if (!this.isMultiDrag && multiDragSortable) {
                    multiDragSortable.multiDrag._deselectMultiDrag();
                }
                multiDragElements.forEach(function(multiDragElement) {
                    multiDragElement.sortableIndex = index(multiDragElement);
                });

                // Sort multi-drag elements
                multiDragElements = multiDragElements.sort(function(a, b) {
                    return a.sortableIndex - b.sortableIndex;
                });
                dragStarted = true;
            },
            dragStarted: function dragStarted(_ref7) {
                var _this2 = this;
                var sortable = _ref7.sortable;
                if (!this.isMultiDrag) return;
                if (this.options.sort) {
                    // Capture rects,
                    // hide multi drag elements (by positioning them absolute),
                    // set multi drag elements rects to dragRect,
                    // show multi drag elements,
                    // animate to rects,
                    // unset rects & remove from DOM

                    sortable.captureAnimationState();
                    if (this.options.animation) {
                        multiDragElements.forEach(function(multiDragElement) {
                            if (multiDragElement === dragEl$1) return;
                            css(multiDragElement, 'position', 'absolute');
                        });
                        var dragRect = getRect(dragEl$1, false, true, true);
                        multiDragElements.forEach(function(multiDragElement) {
                            if (multiDragElement === dragEl$1) return;
                            setRect(multiDragElement, dragRect);
                        });
                        folding = true;
                        initialFolding = true;
                    }
                }
                sortable.animateAll(function() {
                    folding = false;
                    initialFolding = false;
                    if (_this2.options.animation) {
                        multiDragElements.forEach(function(multiDragElement) {
                            unsetRect(multiDragElement);
                        });
                    }

                    // Remove all auxiliary multidrag items from el, if sorting enabled
                    if (_this2.options.sort) {
                        removeMultiDragElements();
                    }
                });
            },
            dragOver: function dragOver(_ref8) {
                var target = _ref8.target,
                    completed = _ref8.completed,
                    cancel = _ref8.cancel;
                if (folding && ~multiDragElements.indexOf(target)) {
                    completed(false);
                    cancel();
                }
            },
            revert: function revert(_ref9) {
                var fromSortable = _ref9.fromSortable,
                    rootEl = _ref9.rootEl,
                    sortable = _ref9.sortable,
                    dragRect = _ref9.dragRect;
                if (multiDragElements.length > 1) {
                    // Setup unfold animation
                    multiDragElements.forEach(function(multiDragElement) {
                        sortable.addAnimationState({
                            target: multiDragElement,
                            rect: folding ? getRect(multiDragElement) : dragRect
                        });
                        unsetRect(multiDragElement);
                        multiDragElement.fromRect = dragRect;
                        fromSortable.removeAnimationState(multiDragElement);
                    });
                    folding = false;
                    insertMultiDragElements(!this.options.removeCloneOnHide, rootEl);
                }
            },
            dragOverCompleted: function dragOverCompleted(_ref10) {
                var sortable = _ref10.sortable,
                    isOwner = _ref10.isOwner,
                    insertion = _ref10.insertion,
                    activeSortable = _ref10.activeSortable,
                    parentEl = _ref10.parentEl,
                    putSortable = _ref10.putSortable;
                var options = this.options;
                if (insertion) {
                    // Clones must be hidden before folding animation to capture dragRectAbsolute properly
                    if (isOwner) {
                        activeSortable._hideClone();
                    }
                    initialFolding = false;
                    // If leaving sort:false root, or already folding - Fold to new location
                    if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) {
                        // Fold: Set all multi drag elements's rects to dragEl's rect when multi-drag elements are invisible
                        var dragRectAbsolute = getRect(dragEl$1, false, true, true);
                        multiDragElements.forEach(function(multiDragElement) {
                            if (multiDragElement === dragEl$1) return;
                            setRect(multiDragElement, dragRectAbsolute);

                            // Move element(s) to end of parentEl so that it does not interfere with multi-drag clones insertion if they are inserted
                            // while folding, and so that we can capture them again because old sortable will no longer be fromSortable
                            parentEl.appendChild(multiDragElement);
                        });
                        folding = true;
                    }

                    // Clones must be shown (and check to remove multi drags) after folding when interfering multiDragElements are moved out
                    if (!isOwner) {
                        // Only remove if not folding (folding will remove them anyways)
                        if (!folding) {
                            removeMultiDragElements();
                        }
                        if (multiDragElements.length > 1) {
                            var clonesHiddenBefore = clonesHidden;
                            activeSortable._showClone(sortable);

                            // Unfold animation for clones if showing from hidden
                            if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) {
                                multiDragClones.forEach(function(clone) {
                                    activeSortable.addAnimationState({
                                        target: clone,
                                        rect: clonesFromRect
                                    });
                                    clone.fromRect = clonesFromRect;
                                    clone.thisAnimationDuration = null;
                                });
                            }
                        } else {
                            activeSortable._showClone(sortable);
                        }
                    }
                }
            },
            dragOverAnimationCapture: function dragOverAnimationCapture(_ref11) {
                var dragRect = _ref11.dragRect,
                    isOwner = _ref11.isOwner,
                    activeSortable = _ref11.activeSortable;
                multiDragElements.forEach(function(multiDragElement) {
                    multiDragElement.thisAnimationDuration = null;
                });
                if (activeSortable.options.animation && !isOwner && activeSortable.multiDrag.isMultiDrag) {
                    clonesFromRect = _extends({}, dragRect);
                    var dragMatrix = matrix(dragEl$1, true);
                    clonesFromRect.top -= dragMatrix.f;
                    clonesFromRect.left -= dragMatrix.e;
                }
            },
            dragOverAnimationComplete: function dragOverAnimationComplete() {
                if (folding) {
                    folding = false;
                    removeMultiDragElements();
                }
            },
            drop: function drop(_ref12) {
                var evt = _ref12.originalEvent,
                    rootEl = _ref12.rootEl,
                    parentEl = _ref12.parentEl,
                    sortable = _ref12.sortable,
                    dispatchSortableEvent = _ref12.dispatchSortableEvent,
                    oldIndex = _ref12.oldIndex,
                    putSortable = _ref12.putSortable;
                var toSortable = putSortable || this.sortable;
                if (!evt) return;
                var options = this.options,
                    children = parentEl.children;

                // Multi-drag selection
                if (!dragStarted) {
                    if (options.multiDragKey && !this.multiDragKeyDown) {
                        this._deselectMultiDrag();
                    }
                    toggleClass(dragEl$1, options.selectedClass, !~multiDragElements.indexOf(dragEl$1));
                    if (!~multiDragElements.indexOf(dragEl$1)) {
                        multiDragElements.push(dragEl$1);
                        dispatchEvent({
                            sortable: sortable,
                            rootEl: rootEl,
                            name: 'select',
                            targetEl: dragEl$1,
                            originalEvent: evt
                        });

                        // Modifier activated, select from last to dragEl
                        if (evt.shiftKey && lastMultiDragSelect && sortable.el.contains(lastMultiDragSelect)) {
                            var lastIndex = index(lastMultiDragSelect),
                                currentIndex = index(dragEl$1);
                            if (~lastIndex && ~currentIndex && lastIndex !== currentIndex) {
                                (function() {
                                    // Must include lastMultiDragSelect (select it), in case modified selection from no selection
                                    // (but previous selection existed)
                                    var n, i;
                                    if (currentIndex > lastIndex) {
                                        i = lastIndex;
                                        n = currentIndex;
                                    } else {
                                        i = currentIndex;
                                        n = lastIndex + 1;
                                    }
                                    var filter = options.filter;
                                    for (; i < n; i++) {
                                        if (~multiDragElements.indexOf(children[i])) continue;
                                        // Check if element is draggable
                                        if (!closest(children[i], options.draggable, parentEl, false)) continue;
                                        // Check if element is filtered
                                        var filtered = filter && (typeof filter === 'function' ? filter.call(sortable, evt, children[i], sortable) : filter.split(',').some(function(criteria) {
                                            return closest(children[i], criteria.trim(), parentEl, false);
                                        }));
                                        if (filtered) continue;
                                        toggleClass(children[i], options.selectedClass, true);
                                        multiDragElements.push(children[i]);
                                        dispatchEvent({
                                            sortable: sortable,
                                            rootEl: rootEl,
                                            name: 'select',
                                            targetEl: children[i],
                                            originalEvent: evt
                                        });
                                    }
                                })();
                            }
                        } else {
                            lastMultiDragSelect = dragEl$1;
                        }
                        multiDragSortable = toSortable;
                    } else {
                        multiDragElements.splice(multiDragElements.indexOf(dragEl$1), 1);
                        lastMultiDragSelect = null;
                        dispatchEvent({
                            sortable: sortable,
                            rootEl: rootEl,
                            name: 'deselect',
                            targetEl: dragEl$1,
                            originalEvent: evt
                        });
                    }
                }

                // Multi-drag drop
                if (dragStarted && this.isMultiDrag) {
                    folding = false;
                    // Do not "unfold" after around dragEl if reverted
                    if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) {
                        var dragRect = getRect(dragEl$1),
                            multiDragIndex = index(dragEl$1, ':not(.' + this.options.selectedClass + ')');
                        if (!initialFolding && options.animation) dragEl$1.thisAnimationDuration = null;
                        toSortable.captureAnimationState();
                        if (!initialFolding) {
                            if (options.animation) {
                                dragEl$1.fromRect = dragRect;
                                multiDragElements.forEach(function(multiDragElement) {
                                    multiDragElement.thisAnimationDuration = null;
                                    if (multiDragElement !== dragEl$1) {
                                        var rect = folding ? getRect(multiDragElement) : dragRect;
                                        multiDragElement.fromRect = rect;

                                        // Prepare unfold animation
                                        toSortable.addAnimationState({
                                            target: multiDragElement,
                                            rect: rect
                                        });
                                    }
                                });
                            }

                            // Multi drag elements are not necessarily removed from the DOM on drop, so to reinsert
                            // properly they must all be removed
                            removeMultiDragElements();
                            multiDragElements.forEach(function(multiDragElement) {
                                if (children[multiDragIndex]) {
                                    parentEl.insertBefore(multiDragElement, children[multiDragIndex]);
                                } else {
                                    parentEl.appendChild(multiDragElement);
                                }
                                multiDragIndex++;
                            });

                            // If initial folding is done, the elements may have changed position because they are now
                            // unfolding around dragEl, even though dragEl may not have his index changed, so update event
                            // must be fired here as Sortable will not.
                            if (oldIndex === index(dragEl$1)) {
                                var update = false;
                                multiDragElements.forEach(function(multiDragElement) {
                                    if (multiDragElement.sortableIndex !== index(multiDragElement)) {
                                        update = true;
                                        return;
                                    }
                                });
                                if (update) {
                                    dispatchSortableEvent('update');
                                    dispatchSortableEvent('sort');
                                }
                            }
                        }

                        // Must be done after capturing individual rects (scroll bar)
                        multiDragElements.forEach(function(multiDragElement) {
                            unsetRect(multiDragElement);
                        });
                        toSortable.animateAll();
                    }
                    multiDragSortable = toSortable;
                }

                // Remove clones if necessary
                if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') {
                    multiDragClones.forEach(function(clone) {
                        clone.parentNode && clone.parentNode.removeChild(clone);
                    });
                }
            },
            nullingGlobal: function nullingGlobal() {
                this.isMultiDrag = dragStarted = false;
                multiDragClones.length = 0;
            },
            destroyGlobal: function destroyGlobal() {
                this._deselectMultiDrag();
                off(document, 'pointerup', this._deselectMultiDrag);
                off(document, 'mouseup', this._deselectMultiDrag);
                off(document, 'touchend', this._deselectMultiDrag);
                off(document, 'keydown', this._checkKeyDown);
                off(document, 'keyup', this._checkKeyUp);
            },
            _deselectMultiDrag: function _deselectMultiDrag(evt) {
                if (typeof dragStarted !== "undefined" && dragStarted) return;

                // Only deselect if selection is in this sortable
                if (multiDragSortable !== this.sortable) return;

                // Only deselect if target is not item in this sortable
                if (evt && closest(evt.target, this.options.draggable, this.sortable.el, false)) return;

                // Only deselect if left click
                if (evt && evt.button !== 0) return;
                while (multiDragElements.length) {
                    var el = multiDragElements[0];
                    toggleClass(el, this.options.selectedClass, false);
                    multiDragElements.shift();
                    dispatchEvent({
                        sortable: this.sortable,
                        rootEl: this.sortable.el,
                        name: 'deselect',
                        targetEl: el,
                        originalEvent: evt
                    });
                }
            },
            _checkKeyDown: function _checkKeyDown(evt) {
                if (evt.key === this.options.multiDragKey) {
                    this.multiDragKeyDown = true;
                }
            },
            _checkKeyUp: function _checkKeyUp(evt) {
                if (evt.key === this.options.multiDragKey) {
                    this.multiDragKeyDown = false;
                }
            }
        };
        return _extends(MultiDrag, {
            // Static methods & properties
            pluginName: 'multiDrag',
            utils: {
                /**
                 * Selects the provided multi-drag item
                 * @param  {HTMLElement} el    The element to be selected
                 */
                select: function select(el) {
                    var sortable = el.parentNode[expando];
                    if (!sortable || !sortable.options.multiDrag || ~multiDragElements.indexOf(el)) return;
                    if (multiDragSortable && multiDragSortable !== sortable) {
                        multiDragSortable.multiDrag._deselectMultiDrag();
                        multiDragSortable = sortable;
                    }
                    toggleClass(el, sortable.options.selectedClass, true);
                    multiDragElements.push(el);
                },
                /**
                 * Deselects the provided multi-drag item
                 * @param  {HTMLElement} el    The element to be deselected
                 */
                deselect: function deselect(el) {
                    var sortable = el.parentNode[expando],
                        index = multiDragElements.indexOf(el);
                    if (!sortable || !sortable.options.multiDrag || !~index) return;
                    toggleClass(el, sortable.options.selectedClass, false);
                    multiDragElements.splice(index, 1);
                }
            },
            eventProperties: function eventProperties() {
                var _this3 = this;
                var oldIndicies = [],
                    newIndicies = [];
                multiDragElements.forEach(function(multiDragElement) {
                    oldIndicies.push({
                        multiDragElement: multiDragElement,
                        index: multiDragElement.sortableIndex
                    });

                    // multiDragElements will already be sorted if folding
                    var newIndex;
                    if (folding && multiDragElement !== dragEl$1) {
                        newIndex = -1;
                    } else if (folding) {
                        newIndex = index(multiDragElement, ':not(.' + _this3.options.selectedClass + ')');
                    } else {
                        newIndex = index(multiDragElement);
                    }
                    newIndicies.push({
                        multiDragElement: multiDragElement,
                        index: newIndex
                    });
                });
                return {
                    items: _toConsumableArray(multiDragElements),
                    clones: [].concat(multiDragClones),
                    oldIndicies: oldIndicies,
                    newIndicies: newIndicies
                };
            },
            optionListeners: {
                multiDragKey: function multiDragKey(key) {
                    key = key.toLowerCase();
                    if (key === 'ctrl') {
                        key = 'Control';
                    } else if (key.length > 1) {
                        key = key.charAt(0).toUpperCase() + key.substr(1);
                    }
                    return key;
                }
            }
        });
    }

    function insertMultiDragElements(clonesInserted, rootEl) {
        multiDragElements.forEach(function(multiDragElement, i) {
            var target = rootEl.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)];
            if (target) {
                rootEl.insertBefore(multiDragElement, target);
            } else {
                rootEl.appendChild(multiDragElement);
            }
        });
    }

    /**
     * Insert multi-drag clones
     * @param  {[Boolean]} elementsInserted  Whether the multi-drag elements are inserted
     * @param  {HTMLElement} rootEl
     */
    function insertMultiDragClones(elementsInserted, rootEl) {
        multiDragClones.forEach(function(clone, i) {
            var target = rootEl.children[clone.sortableIndex + (elementsInserted ? Number(i) : 0)];
            if (target) {
                rootEl.insertBefore(clone, target);
            } else {
                rootEl.appendChild(clone);
            }
        });
    }

    function removeMultiDragElements() {
        multiDragElements.forEach(function(multiDragElement) {
            if (multiDragElement === dragEl$1) return;
            multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement);
        });
    }

    Sortable.mount(new AutoScrollPlugin());
    Sortable.mount(Remove, Revert);

    Sortable.mount(new SwapPlugin());
    Sortable.mount(new MultiDragPlugin());

    return Sortable;

})));
/*! @license DOMPurify 3.4.13 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.13/LICENSE */

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

    function _arrayLikeToArray(r, a) {
        (null == a || a > r.length) && (a = r.length);
        for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
        return n;
    }

    function _arrayWithHoles(r) {
        if (Array.isArray(r)) return r;
    }

    function _iterableToArrayLimit(r, l) {
        var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
        if (null != t) {
            var e,
                n,
                i,
                u,
                a = [],
                f = true,
                o = false;
            try {
                if (i = (t = t.call(r)).next, 0 === l);
                else
                    for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
            } catch (r) {
                o = true, n = r;
            } finally {
                try {
                    if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
                } finally {
                    if (o) throw n;
                }
            }
            return a;
        }
    }

    function _nonIterableRest() {
        throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
    }

    function _slicedToArray(r, e) {
        return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
    }

    function _unsupportedIterableToArray(r, a) {
        if (r) {
            if ("string" == typeof r) return _arrayLikeToArray(r, a);
            var t = {}.toString.call(r).slice(8, -1);
            return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
        }
    }

    const entries = Object.entries,
        setPrototypeOf = Object.setPrototypeOf,
        isFrozen = Object.isFrozen,
        getPrototypeOf = Object.getPrototypeOf,
        getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
    let freeze = Object.freeze,
        seal = Object.seal,
        create = Object.create; // eslint-disable-line import/no-mutable-exports
    let _ref = typeof Reflect !== 'undefined' && Reflect,
        apply = _ref.apply,
        construct = _ref.construct;
    if (!freeze) {
        freeze = function freeze(x) {
            return x;
        };
    }
    if (!seal) {
        seal = function seal(x) {
            return x;
        };
    }
    if (!apply) {
        apply = function apply(func, thisArg) {
            for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
                args[_key - 2] = arguments[_key];
            }
            return func.apply(thisArg, args);
        };
    }
    if (!construct) {
        construct = function construct(Func) {
            for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
                args[_key2 - 1] = arguments[_key2];
            }
            return new Func(...args);
        };
    }
    const arrayForEach = unapply(Array.prototype.forEach);
    const arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
    const arrayPop = unapply(Array.prototype.pop);
    const arrayPush = unapply(Array.prototype.push);
    const arraySplice = unapply(Array.prototype.splice);
    const arrayIsArray = Array.isArray;
    const stringToLowerCase = unapply(String.prototype.toLowerCase);
    const stringToString = unapply(String.prototype.toString);
    const stringMatch = unapply(String.prototype.match);
    const stringReplace = unapply(String.prototype.replace);
    const stringIndexOf = unapply(String.prototype.indexOf);
    const stringTrim = unapply(String.prototype.trim);
    const numberToString = unapply(Number.prototype.toString);
    const booleanToString = unapply(Boolean.prototype.toString);
    const bigintToString = typeof BigInt === 'undefined' ? null : unapply(BigInt.prototype.toString);
    const symbolToString = typeof Symbol === 'undefined' ? null : unapply(Symbol.prototype.toString);
    const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
    const objectToString = unapply(Object.prototype.toString);
    const regExpTest = unapply(RegExp.prototype.test);
    const typeErrorCreate = unconstruct(TypeError);
    /**
     * Creates a new function that calls the given function with a specified thisArg and arguments.
     *
     * @param func - The function to be wrapped and called.
     * @returns A new function that calls the given function with a specified thisArg and arguments.
     */
    function unapply(func) {
        return function(thisArg) {
            if (thisArg instanceof RegExp) {
                thisArg.lastIndex = 0;
            }
            for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
                args[_key3 - 1] = arguments[_key3];
            }
            return apply(func, thisArg, args);
        };
    }
    /**
     * Creates a new function that constructs an instance of the given constructor function with the provided arguments.
     *
     * @param func - The constructor function to be wrapped and called.
     * @returns A new function that constructs an instance of the given constructor function with the provided arguments.
     */
    function unconstruct(Func) {
        return function() {
            for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
                args[_key4] = arguments[_key4];
            }
            return construct(Func, args);
        };
    }
    /**
     * Add properties to a lookup table
     *
     * @param set - The set to which elements will be added.
     * @param array - The array containing elements to be added to the set.
     * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.
     * @returns The modified set with added elements.
     */
    function addToSet(set, array) {
        let transformCaseFunc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : stringToLowerCase;
        if (setPrototypeOf) {
            // Make 'in' and truthy checks like Boolean(set.constructor)
            // independent of any properties defined on Object.prototype.
            // Prevent prototype setters from intercepting set as a this value.
            setPrototypeOf(set, null);
        }
        if (!arrayIsArray(array)) {
            return set;
        }
        let l = array.length;
        while (l--) {
            let element = array[l];
            if (typeof element === 'string') {
                const lcElement = transformCaseFunc(element);
                if (lcElement !== element) {
                    // Config presets (e.g. tags.js, attrs.js) are immutable.
                    if (!isFrozen(array)) {
                        array[l] = lcElement;
                    }
                    element = lcElement;
                }
            }
            set[element] = true;
        }
        return set;
    }
    /**
     * Clean up an array to harden against CSPP
     *
     * @param array - The array to be cleaned.
     * @returns The cleaned version of the array
     */
    function cleanArray(array) {
        for (let index = 0; index < array.length; index++) {
            const isPropertyExist = objectHasOwnProperty(array, index);
            if (!isPropertyExist) {
                array[index] = null;
            }
        }
        return array;
    }
    /**
     * Shallow clone an object
     *
     * @param object - The object to be cloned.
     * @returns A new object that copies the original.
     */
    function clone(object) {
        const newObject = create(null);
        for (const _ref2 of entries(object)) {
            var _ref3 = _slicedToArray(_ref2, 2);
            const property = _ref3[0];
            const value = _ref3[1];
            const isPropertyExist = objectHasOwnProperty(object, property);
            if (isPropertyExist) {
                if (arrayIsArray(value)) {
                    newObject[property] = cleanArray(value);
                } else if (value && typeof value === 'object' && value.constructor === Object) {
                    newObject[property] = clone(value);
                } else {
                    newObject[property] = value;
                }
            }
        }
        return newObject;
    }
    /**
     * Convert non-node values into strings without depending on direct property access.
     *
     * @param value - The value to stringify.
     * @returns A string representation of the provided value.
     */
    function stringifyValue(value) {
        switch (typeof value) {
            case 'string': {
                return value;
            }
            case 'number': {
                return numberToString(value);
            }
            case 'boolean': {
                return booleanToString(value);
            }
            case 'bigint': {
                return bigintToString ? bigintToString(value) : '0';
            }
            case 'symbol': {
                return symbolToString ? symbolToString(value) : 'Symbol()';
            }
            case 'undefined': {
                return objectToString(value);
            }
            case 'function':
            case 'object': {
                if (value === null) {
                    return objectToString(value);
                }
                const valueAsRecord = value;
                const valueToString = lookupGetter(valueAsRecord, 'toString');
                if (typeof valueToString === 'function') {
                    const stringified = valueToString(valueAsRecord);
                    return typeof stringified === 'string' ? stringified : objectToString(stringified);
                }
                return objectToString(value);
            }
            default: {
                return objectToString(value);
            }
        }
    }
    /**
     * This method automatically checks if the prop is function or getter and behaves accordingly.
     *
     * @param object - The object to look up the getter function in its prototype chain.
     * @param prop - The property name for which to find the getter function.
     * @returns The getter function found in the prototype chain or a fallback function.
     */
    function lookupGetter(object, prop) {
        while (object !== null) {
            const desc = getOwnPropertyDescriptor(object, prop);
            if (desc) {
                if (desc.get) {
                    return unapply(desc.get);
                }
                if (typeof desc.value === 'function') {
                    return unapply(desc.value);
                }
            }
            object = getPrototypeOf(object);
        }

        function fallbackValue() {
            return null;
        }
        return fallbackValue;
    }

    function isRegex(value) {
        try {
            regExpTest(value, '');
            return true;
        } catch (_unused) {
            return false;
        }
    }

    const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
    const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
    const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
    // List of SVG elements that are disallowed by default.
    // We still need to know them so that we can do namespace
    // checks properly in case one wants to add them to
    // allow-list.
    const svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);
    const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);
    // Similarly to SVG, we want to know all MathML elements,
    // even those that we disallow by default.
    const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);
    const text = freeze(['#text']);

    const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'command', 'commandfor', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns']);
    const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dominant-baseline', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-orientation', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
    const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnalign', 'columnlines', 'columnspacing', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lquote', 'lspace', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
    const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);

    const MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
    const ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g);
    const TMPLIT_EXPR = seal(/\${[\w\W]*/g);
    const DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/); // eslint-disable-line no-useless-escape
    const ARIA_ATTR = seal(/^aria-[\-\w]+$/); // eslint-disable-line no-useless-escape
    const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i // eslint-disable-line no-useless-escape
    );
    const IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
    const ATTR_WHITESPACE = seal(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g // eslint-disable-line no-control-regex
    );
    const DOCTYPE_NAME = seal(/^html$/i);
    const CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
    // Markup-significant character probes used by _sanitizeElements.
    // Shared module-level instances are safe despite the sticky /g flags:
    // unapply() resets lastIndex for RegExp receivers before every call.
    const ELEMENT_MARKUP_PROBE = seal(/<[/\w!]/g);
    const COMMENT_MARKUP_PROBE = seal(/<[/\w]/g);
    const FALLBACK_TAG_CLOSE = seal(/<\/no(script|embed|frames)/i);
    const SELF_CLOSING_TAG = seal(/\/>/i);

    // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
    const NODE_TYPE = {
        element: 1,
        attribute: 2,
        text: 3,
        cdataSection: 4,
        entityReference: 5,
        // Deprecated
        entityNode: 6,
        // Deprecated
        processingInstruction: 7,
        comment: 8,
        document: 9,
        documentType: 10,
        documentFragment: 11,
        notation: 12 // Deprecated
    };
    const getGlobal = function getGlobal() {
        return typeof window === 'undefined' ? null : window;
    };
    /**
     * Creates a no-op policy for internal use only.
     * Don't export this function outside this module!
     * @param trustedTypes The policy factory.
     * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).
     * @return The policy created (or null, if Trusted Types
     * are not supported or creating the policy failed).
     */
    const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {
        if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {
            return null;
        }
        // Allow the callers to control the unique policy name
        // by adding a data-tt-policy-suffix to the script element with the DOMPurify.
        // Policy creation with duplicate names throws in Trusted Types.
        let suffix = null;
        const ATTR_NAME = 'data-tt-policy-suffix';
        if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
            suffix = purifyHostElement.getAttribute(ATTR_NAME);
        }
        const policyName = 'dompurify' + (suffix ? '#' + suffix : '');
        try {
            return trustedTypes.createPolicy(policyName, {
                createHTML(html) {
                    return html;
                },
                createScriptURL(scriptUrl) {
                    return scriptUrl;
                }
            });
        } catch (_) {
            // Policy creation failed (most likely another DOMPurify script has
            // already run). Skip creating the policy, as this will only cause errors
            // if TT are enforced.
            console.warn('TrustedTypes policy ' + policyName + ' could not be created.');
            return null;
        }
    };
    const _createHooksMap = function _createHooksMap() {
        return {
            afterSanitizeAttributes: [],
            afterSanitizeElements: [],
            afterSanitizeShadowDOM: [],
            beforeSanitizeAttributes: [],
            beforeSanitizeElements: [],
            beforeSanitizeShadowDOM: [],
            uponSanitizeAttribute: [],
            uponSanitizeElement: [],
            uponSanitizeShadowNode: []
        };
    };
    /**
     * Resolve a set-valued configuration option: a fresh set built from
     * cfg[key] when it is an own array property (seeded with a clone of
     * options.base when given, case-normalized via options.transform),
     * the fallback set otherwise.
     *
     * @param cfg the cloned, prototype-free configuration object
     * @param key the configuration property to read
     * @param fallback the set to use when the option is absent or not an array
     * @param options transform and optional base set to merge into
     * @returns the resolved set
     */
    const _resolveSetOption = function _resolveSetOption(cfg, key, fallback, options) {
        return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback;
    };

    function createDOMPurify() {
        let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
        const DOMPurify = root => createDOMPurify(root);
        DOMPurify.version = '3.4.13';
        DOMPurify.removed = [];
        if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
            // Not running in a browser, provide a factory function
            // so that you can pass your own Window
            DOMPurify.isSupported = false;
            return DOMPurify;
        }
        let document = window.document;
        const originalDocument = document;
        const currentScript = originalDocument.currentScript;
        window.DocumentFragment;
        const HTMLTemplateElement = window.HTMLTemplateElement,
            Node = window.Node,
            Element = window.Element,
            NodeFilter = window.NodeFilter,
            _window$NamedNodeMap = window.NamedNodeMap;
        _window$NamedNodeMap === void 0 ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap;
        window.HTMLFormElement;
        const DOMParser = window.DOMParser,
            trustedTypes = window.trustedTypes;
        const ElementPrototype = Element.prototype;
        const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');
        const remove = lookupGetter(ElementPrototype, 'remove');
        const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');
        const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');
        const getParentNode = lookupGetter(ElementPrototype, 'parentNode');
        const getShadowRoot = lookupGetter(ElementPrototype, 'shadowRoot');
        const getAttributes = lookupGetter(ElementPrototype, 'attributes');
        const getNodeType = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeType') : null;
        const getNodeName = Node && Node.prototype ? lookupGetter(Node.prototype, 'nodeName') : null;
        const getOwnerDocument = Node && Node.prototype ? lookupGetter(Node.prototype, 'ownerDocument') : null;
        // As per issue #47, the web-components registry is inherited by a
        // new document created via createHTMLDocument. As per the spec
        // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
        // a new empty registry is used when creating a template contents owner
        // document, so we use that as our parent document to ensure nothing
        // is inherited.
        if (typeof HTMLTemplateElement === 'function') {
            const template = document.createElement('template');
            if (template.content && template.content.ownerDocument) {
                document = template.content.ownerDocument;
            }
        }
        let trustedTypesPolicy;
        let emptyHTML = '';
        // The instance's own internal Trusted Types policy. Unlike a caller-supplied
        // `TRUSTED_TYPES_POLICY`, this is created at most once — Trusted Types throws
        // on duplicate policy names — and is the only policy allowed to persist
        // across configurations and survive `clearConfig()`.
        let defaultTrustedTypesPolicy;
        let defaultTrustedTypesPolicyResolved = false;
        // Tracks whether we are already inside a call to the configured Trusted Types
        // policy (`createHTML` or `createScriptURL`). If a supplied policy callback
        // itself calls `DOMPurify.sanitize` (the cause of #1422), `sanitize` would
        // re-enter the policy and recurse until the stack overflows. We detect that
        // re-entry and throw a clear, actionable error instead. The guard is shared
        // across both callbacks, because either one re-entering `sanitize` triggers
        // the same unbounded recursion.
        let IN_TRUSTED_TYPES_POLICY = 0;
        const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy() {
            if (IN_TRUSTED_TYPES_POLICY > 0) {
                throw typeErrorCreate('A configured TRUSTED_TYPES_POLICY callback (createHTML or ' + 'createScriptURL) must not call DOMPurify.sanitize, as that causes ' + 'infinite recursion. Do not pass a policy whose callbacks wrap ' + 'DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted ' + 'Types" section of the README.');
            }
        };
        const _createTrustedHTML = function _createTrustedHTML(html) {
            _assertNotInTrustedTypesPolicy();
            IN_TRUSTED_TYPES_POLICY++;
            try {
                return trustedTypesPolicy.createHTML(html);
            } finally {
                IN_TRUSTED_TYPES_POLICY--;
            }
        };
        const _createTrustedScriptURL = function _createTrustedScriptURL(scriptUrl) {
            _assertNotInTrustedTypesPolicy();
            IN_TRUSTED_TYPES_POLICY++;
            try {
                return trustedTypesPolicy.createScriptURL(scriptUrl);
            } finally {
                IN_TRUSTED_TYPES_POLICY--;
            }
        };
        // Lazily resolve (and cache) the instance's internal default policy.
        // Resolution is attempted at most once: a successful `createPolicy` cannot be
        // repeated (Trusted Types throws on duplicate names), and a failed or
        // unsupported attempt must not be retried on every parse.
        const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy() {
            if (!defaultTrustedTypesPolicyResolved) {
                defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
                defaultTrustedTypesPolicyResolved = true;
            }
            return defaultTrustedTypesPolicy;
        };
        const _document = document,
            implementation = _document.implementation,
            createNodeIterator = _document.createNodeIterator,
            createDocumentFragment = _document.createDocumentFragment,
            getElementsByTagName = _document.getElementsByTagName;
        const importNode = originalDocument.importNode;
        let hooks = _createHooksMap();
        /**
         * Expose whether this browser supports running the full DOMPurify.
         */
        DOMPurify.isSupported = typeof entries === 'function' && typeof getParentNode === 'function' && implementation && implementation.createHTMLDocument !== undefined;
        const MUSTACHE_EXPR$1 = MUSTACHE_EXPR,
            ERB_EXPR$1 = ERB_EXPR,
            TMPLIT_EXPR$1 = TMPLIT_EXPR,
            DATA_ATTR$1 = DATA_ATTR,
            ARIA_ATTR$1 = ARIA_ATTR,
            IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA,
            ATTR_WHITESPACE$1 = ATTR_WHITESPACE,
            CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
        let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
        /**
         * We consider the elements and attributes below to be safe. Ideally
         * don't add any new ones but feel free to remove unwanted ones.
         */
        /* allowed element names */
        let ALLOWED_TAGS = null;
        const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);
        /* Allowed attribute names */
        let ALLOWED_ATTR = null;
        const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
        /*
         * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.
         * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)
         * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)
         * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.
         */
        let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {
            tagNameCheck: {
                writable: true,
                configurable: false,
                enumerable: true,
                value: null
            },
            attributeNameCheck: {
                writable: true,
                configurable: false,
                enumerable: true,
                value: null
            },
            allowCustomizedBuiltInElements: {
                writable: true,
                configurable: false,
                enumerable: true,
                value: false
            }
        }));
        /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
        let FORBID_TAGS = null;
        /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
        let FORBID_ATTR = null;
        /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */
        const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {
            tagCheck: {
                writable: true,
                configurable: false,
                enumerable: true,
                value: null
            },
            attributeCheck: {
                writable: true,
                configurable: false,
                enumerable: true,
                value: null
            }
        }));
        /* Decide if ARIA attributes are okay */
        let ALLOW_ARIA_ATTR = true;
        /* Decide if custom data attributes are okay */
        let ALLOW_DATA_ATTR = true;
        /* Decide if unknown protocols are okay */
        let ALLOW_UNKNOWN_PROTOCOLS = false;
        /* Decide if self-closing tags in attributes are allowed.
         * Usually removed due to a mXSS issue in jQuery 3.0 */
        let ALLOW_SELF_CLOSE_IN_ATTR = true;
        /* Output should be safe for common template engines.
         * This means, DOMPurify removes data attributes, mustaches and ERB
         */
        let SAFE_FOR_TEMPLATES = false;
        /* Output should be safe even for XML used within HTML and alike.
         * This means, DOMPurify removes comments when containing risky content.
         */
        let SAFE_FOR_XML = true;
        /* Decide if document with <html>... should be returned */
        let WHOLE_DOCUMENT = false;
        /* Track whether config is already set on this instance of DOMPurify. */
        let SET_CONFIG = false;
        /* Pristine allowlist bindings captured at setConfig() time. On the
         * persistent-config path sanitize() restores the sets from these before
         * the per-walk hook clone-guard, so a hook's in-call widening cannot
         * carry across calls. Null until setConfig() is called; reset by
         * clearConfig(). */
        let SET_CONFIG_ALLOWED_TAGS = null;
        let SET_CONFIG_ALLOWED_ATTR = null;
        /* Decide if all elements (e.g. style, script) must be children of
         * document.body. By default, browsers might move them to document.head */
        let FORCE_BODY = false;
        /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html
         * string (or a TrustedHTML object if Trusted Types are supported).
         * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
         */
        let RETURN_DOM = false;
        /* Decide if a DOM `DocumentFragment` should be returned, instead of a html
         * string  (or a TrustedHTML object if Trusted Types are supported) */
        let RETURN_DOM_FRAGMENT = false;
        /* Try to return a Trusted Type object instead of a string, return a string in
         * case Trusted Types are not supported  */
        let RETURN_TRUSTED_TYPE = false;
        /* Output should be free from DOM clobbering attacks?
         * This sanitizes markups named with colliding, clobberable built-in DOM APIs.
         */
        let SANITIZE_DOM = true;
        /* Achieve full DOM Clobbering protection by isolating the namespace of named
         * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.
         *
         * HTML/DOM spec rules that enable DOM Clobbering:
         *   - Named Access on Window (§7.3.3)
         *   - DOM Tree Accessors (§3.1.5)
         *   - Form Element Parent-Child Relations (§4.10.3)
         *   - Iframe srcdoc / Nested WindowProxies (§4.8.5)
         *   - HTMLCollection (§4.2.10.2)
         *
         * Namespace isolation is implemented by prefixing `id` and `name` attributes
         * with a constant string, i.e., `user-content-`
         */
        let SANITIZE_NAMED_PROPS = false;
        const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';
        /* Keep element content when removing element? */
        let KEEP_CONTENT = true;
        /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead
         * of importing it into a new Document and returning a sanitized copy */
        let IN_PLACE = false;
        /* Allow usage of profiles like html, svg and mathMl */
        let USE_PROFILES = {};
        /* Tags to ignore content of when KEEP_CONTENT is true */
        let FORBID_CONTENTS = null;
        const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script',
            // <selectedcontent> mirrors the selected <option>'s subtree, cloned by
            // the UA (customizable <select>) — including any on* handlers — and the
            // engine re-mirrors synchronously whenever a removal changes which
            // option/selectedcontent is current, even inside DOMPurify's inert
            // DOMParser document. Hoisting its children on removal re-inserts a fresh
            // mirror target ahead of the walk, which the engine refills, looping
            // forever (DoS) and amplifying output. Dropping its content on removal
            // (rather than hoisting) breaks that cascade; the content is a duplicate
            // of the option, which is sanitized on its own. See campaign-3 F1/F6.
            'selectedcontent', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp'
        ]);
        /* Tags that are safe for data: URIs */
        let DATA_URI_TAGS = null;
        const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);
        /* Attributes safe for values like "javascript:" */
        let URI_SAFE_ATTRIBUTES = null;
        const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);
        const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';
        const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
        const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
        /* Document namespace */
        let NAMESPACE = HTML_NAMESPACE;
        let IS_EMPTY_INPUT = false;
        /* Allowed XHTML+XML namespaces */
        let ALLOWED_NAMESPACES = null;
        const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
        const DEFAULT_MATHML_TEXT_INTEGRATION_POINTS = freeze(['mi', 'mo', 'mn', 'ms', 'mtext']);
        let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS);
        const DEFAULT_HTML_INTEGRATION_POINTS = freeze(['annotation-xml']);
        let HTML_INTEGRATION_POINTS = addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS);
        // Certain elements are allowed in both SVG and HTML
        // namespace. We need to specify them explicitly
        // so that they don't get erroneously deleted from
        // HTML namespace.
        const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);
        /* Parsing of strict XHTML documents */
        let PARSER_MEDIA_TYPE = null;
        const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];
        const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';
        let transformCaseFunc = null;
        /* Keep a reference to config to pass to hooks */
        let CONFIG = null;
        /* Ideally, do not touch anything below this line */
        /* ______________________________________________ */
        const formElement = document.createElement('form');
        const isRegexOrFunction = function isRegexOrFunction(testValue) {
            return testValue instanceof RegExp || testValue instanceof Function;
        };
        /**
         * _parseConfig
         *
         * @param cfg optional config literal
         */
        // eslint-disable-next-line complexity
        const _parseConfig = function _parseConfig() {
            let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
            if (CONFIG && CONFIG === cfg) {
                return;
            }
            /* Shield configuration object from tampering */
            if (!cfg || typeof cfg !== 'object') {
                cfg = {};
            }
            /* Shield configuration object from prototype pollution */
            cfg = clone(cfg);
            PARSER_MEDIA_TYPE =
                // eslint-disable-next-line unicorn/prefer-includes
                SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;
            // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.
            transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;
            /* Set configuration parameters */
            ALLOWED_TAGS = _resolveSetOption(cfg, 'ALLOWED_TAGS', DEFAULT_ALLOWED_TAGS, {
                transform: transformCaseFunc
            });
            ALLOWED_ATTR = _resolveSetOption(cfg, 'ALLOWED_ATTR', DEFAULT_ALLOWED_ATTR, {
                transform: transformCaseFunc
            });
            ALLOWED_NAMESPACES = _resolveSetOption(cfg, 'ALLOWED_NAMESPACES', DEFAULT_ALLOWED_NAMESPACES, {
                transform: stringToString
            });
            URI_SAFE_ATTRIBUTES = _resolveSetOption(cfg, 'ADD_URI_SAFE_ATTR', DEFAULT_URI_SAFE_ATTRIBUTES, {
                transform: transformCaseFunc,
                base: DEFAULT_URI_SAFE_ATTRIBUTES
            });
            DATA_URI_TAGS = _resolveSetOption(cfg, 'ADD_DATA_URI_TAGS', DEFAULT_DATA_URI_TAGS, {
                transform: transformCaseFunc,
                base: DEFAULT_DATA_URI_TAGS
            });
            FORBID_CONTENTS = _resolveSetOption(cfg, 'FORBID_CONTENTS', DEFAULT_FORBID_CONTENTS, {
                transform: transformCaseFunc
            });
            FORBID_TAGS = _resolveSetOption(cfg, 'FORBID_TAGS', clone({}), {
                transform: transformCaseFunc
            });
            FORBID_ATTR = _resolveSetOption(cfg, 'FORBID_ATTR', clone({}), {
                transform: transformCaseFunc
            });
            USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === 'object' ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;
            ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true
            ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
            ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false
            ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true
            SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false
            SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true
            WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
            RETURN_DOM = cfg.RETURN_DOM || false; // Default false
            RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
            RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false
            FORCE_BODY = cfg.FORCE_BODY || false; // Default false
            SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
            SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false
            KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
            IN_PLACE = cfg.IN_PLACE || false; // Default false
            IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI; // Default regexp
            NAMESPACE = typeof cfg.NAMESPACE === 'string' ? cfg.NAMESPACE : HTML_NAMESPACE; // Default HTML namespace
            MATHML_TEXT_INTEGRATION_POINTS = objectHasOwnProperty(cfg, 'MATHML_TEXT_INTEGRATION_POINTS') && cfg.MATHML_TEXT_INTEGRATION_POINTS && typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === 'object' ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS); // Default built-in map
            HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, 'HTML_INTEGRATION_POINTS') && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === 'object' ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS); // Default built-in map
            const customElementHandling = objectHasOwnProperty(cfg, 'CUSTOM_ELEMENT_HANDLING') && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === 'object' ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null);
            CUSTOM_ELEMENT_HANDLING = create(null);
            if (objectHasOwnProperty(customElementHandling, 'tagNameCheck') && isRegexOrFunction(customElementHandling.tagNameCheck)) {
                CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; // Default undefined
            }
            if (objectHasOwnProperty(customElementHandling, 'attributeNameCheck') && isRegexOrFunction(customElementHandling.attributeNameCheck)) {
                CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; // Default undefined
            }
            if (objectHasOwnProperty(customElementHandling, 'allowCustomizedBuiltInElements') && typeof customElementHandling.allowCustomizedBuiltInElements === 'boolean') {
                CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; // Default undefined
            }
            seal(CUSTOM_ELEMENT_HANDLING);
            if (SAFE_FOR_TEMPLATES) {
                ALLOW_DATA_ATTR = false;
            }
            if (RETURN_DOM_FRAGMENT) {
                RETURN_DOM = true;
            }
            /* Parse profile info */
            if (USE_PROFILES) {
                ALLOWED_TAGS = addToSet({}, text);
                ALLOWED_ATTR = create(null);
                if (USE_PROFILES.html === true) {
                    addToSet(ALLOWED_TAGS, html$1);
                    addToSet(ALLOWED_ATTR, html);
                }
                if (USE_PROFILES.svg === true) {
                    addToSet(ALLOWED_TAGS, svg$1);
                    addToSet(ALLOWED_ATTR, svg);
                    addToSet(ALLOWED_ATTR, xml);
                }
                if (USE_PROFILES.svgFilters === true) {
                    addToSet(ALLOWED_TAGS, svgFilters);
                    addToSet(ALLOWED_ATTR, svg);
                    addToSet(ALLOWED_ATTR, xml);
                }
                if (USE_PROFILES.mathMl === true) {
                    addToSet(ALLOWED_TAGS, mathMl$1);
                    addToSet(ALLOWED_ATTR, mathMl);
                    addToSet(ALLOWED_ATTR, xml);
                }
            }
            /* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent
             * leaking across calls when switching from function to array config */
            EXTRA_ELEMENT_HANDLING.tagCheck = null;
            EXTRA_ELEMENT_HANDLING.attributeCheck = null;
            /* Merge configuration parameters */
            if (objectHasOwnProperty(cfg, 'ADD_TAGS')) {
                if (typeof cfg.ADD_TAGS === 'function') {
                    EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
                } else if (arrayIsArray(cfg.ADD_TAGS)) {
                    if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
                        ALLOWED_TAGS = clone(ALLOWED_TAGS);
                    }
                    addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
                }
            }
            if (objectHasOwnProperty(cfg, 'ADD_ATTR')) {
                if (typeof cfg.ADD_ATTR === 'function') {
                    EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
                } else if (arrayIsArray(cfg.ADD_ATTR)) {
                    if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
                        ALLOWED_ATTR = clone(ALLOWED_ATTR);
                    }
                    addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
                }
            }
            if (objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {
                addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
            }
            if (objectHasOwnProperty(cfg, 'FORBID_CONTENTS') && arrayIsArray(cfg.FORBID_CONTENTS)) {
                if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
                    FORBID_CONTENTS = clone(FORBID_CONTENTS);
                }
                addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
            }
            if (objectHasOwnProperty(cfg, 'ADD_FORBID_CONTENTS') && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
                if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
                    FORBID_CONTENTS = clone(FORBID_CONTENTS);
                }
                addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
            }
            /* Add #text in case KEEP_CONTENT is set to true */
            if (KEEP_CONTENT) {
                ALLOWED_TAGS['#text'] = true;
            }
            /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */
            if (WHOLE_DOCUMENT) {
                addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);
            }
            /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */
            if (ALLOWED_TAGS.table) {
                addToSet(ALLOWED_TAGS, ['tbody']);
                delete FORBID_TAGS.tbody;
            }
            // Re-derive the active Trusted Types policy from this configuration on
            // every parse. The active policy must never be sticky closure state that
            // outlives the config that set it: a caller-supplied policy left in place
            // after `clearConfig()` — or after a later call that supplied none, or
            // `TRUSTED_TYPES_POLICY: null` — could sign a subsequent "default"
            // `RETURN_TRUSTED_TYPE` result with a foreign, possibly unsafe policy.
            // See GHSA-vxr8-fq34-vvx9.
            if (cfg.TRUSTED_TYPES_POLICY) {
                if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {
                    throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
                }
                if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {
                    throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
                }
                // A caller-supplied policy applies to this configuration only.
                const previousTrustedTypesPolicy = trustedTypesPolicy;
                trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
                // Sign local variables required by `sanitize`. If the supplied policy's
                // `createHTML` is circular (i.e. it calls `DOMPurify.sanitize`), this
                // throws via the re-entrancy guard. Restore the previous policy first so
                // the instance is not left in a poisoned state. See #1422.
                try {
                    emptyHTML = _createTrustedHTML('');
                } catch (error) {
                    trustedTypesPolicy = previousTrustedTypesPolicy;
                    throw error;
                }
            } else if (cfg.TRUSTED_TYPES_POLICY === null) {
                // Explicit opt-out for this call: perform no Trusted Types signing and
                // create nothing (so a strict `trusted-types` CSP that disallows a
                // `dompurify` policy can still call `sanitize` from inside its own
                // policy — see #1422). Resetting to `undefined` rather than a sticky
                // `null` also drops any previously retained caller policy, so it cannot
                // resurface on a later call, while still allowing the next config-less
                // call to restore the internal default policy. See GHSA-vxr8-fq34-vvx9.
                trustedTypesPolicy = undefined;
                emptyHTML = '';
            } else {
                // No policy supplied: keep the currently active policy if one is set — a
                // previously supplied policy is intentionally sticky across config-less
                // calls — otherwise fall back to the instance's own internal policy,
                // created at most once. (A policy supplied for a *single* call still
                // lingers by design; what must not linger is a policy whose configuration
                // has been torn down via `clearConfig()`, which restores the default.)
                if (trustedTypesPolicy === undefined) {
                    trustedTypesPolicy = _getDefaultTrustedTypesPolicy();
                }
                // Sign internal variables only when a policy is active. A falsy policy
                // (Trusted Types unsupported, creation failed, or an explicit opt-out)
                // leaves `emptyHTML` as a plain string, so we never call `.createHTML` on
                // a non-policy and throw. See #1422.
                if (trustedTypesPolicy && typeof emptyHTML === 'string') {
                    emptyHTML = _createTrustedHTML('');
                }
            }
            // Prevent further manipulation of configuration.
            // Not available in IE8, Safari 5, etc.
            if (freeze) {
                freeze(cfg);
            }
            CONFIG = cfg;
        };
        /* Keep track of all possible SVG and MathML tags
         * so that we can perform the namespace checks
         * correctly. */
        const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
        const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);
        /**
         * Namespace rules for an element in the SVG namespace.
         *
         * @param tagName the element's lowercase tag name
         * @param parent the (possibly simulated) parent node
         * @param parentTagName the parent's lowercase tag name
         * @returns true if a spec-compliant parser could produce this element
         */
        const _checkSvgNamespace = function _checkSvgNamespace(tagName, parent, parentTagName) {
            // The only way to switch from HTML namespace to SVG
            // is via <svg>. If it happens via any other tag, then
            // it should be killed.
            if (parent.namespaceURI === HTML_NAMESPACE) {
                return tagName === 'svg';
            }
            // The only way to switch from MathML to SVG is via <svg>
            // if the parent is either <annotation-xml> or a MathML
            // text integration point.
            if (parent.namespaceURI === MATHML_NAMESPACE) {
                return tagName === 'svg' && (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
            }
            // We only allow elements that are defined in SVG
            // spec. All others are disallowed in SVG namespace.
            return Boolean(ALL_SVG_TAGS[tagName]);
        };
        /**
         * Namespace rules for an element in the MathML namespace.
         *
         * @param tagName the element's lowercase tag name
         * @param parent the (possibly simulated) parent node
         * @param parentTagName the parent's lowercase tag name
         * @returns true if a spec-compliant parser could produce this element
         */
        const _checkMathMlNamespace = function _checkMathMlNamespace(tagName, parent, parentTagName) {
            // The only way to switch from HTML namespace to MathML
            // is via <math>. If it happens via any other tag, then
            // it should be killed.
            if (parent.namespaceURI === HTML_NAMESPACE) {
                return tagName === 'math';
            }
            // The only way to switch from SVG to MathML is via
            // <math> and HTML integration points
            if (parent.namespaceURI === SVG_NAMESPACE) {
                return tagName === 'math' && HTML_INTEGRATION_POINTS[parentTagName];
            }
            // We only allow elements that are defined in MathML
            // spec. All others are disallowed in MathML namespace.
            return Boolean(ALL_MATHML_TAGS[tagName]);
        };
        /**
         * Namespace rules for an element in the HTML namespace.
         *
         * @param tagName the element's lowercase tag name
         * @param parent the (possibly simulated) parent node
         * @param parentTagName the parent's lowercase tag name
         * @returns true if a spec-compliant parser could produce this element
         */
        const _checkHtmlNamespace = function _checkHtmlNamespace(tagName, parent, parentTagName) {
            // The only way to switch from SVG to HTML is via
            // HTML integration points, and from MathML to HTML
            // is via MathML text integration points
            if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
                return false;
            }
            if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
                return false;
            }
            // We disallow tags that are specific for MathML
            // or SVG and should never appear in HTML namespace
            return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
        };
        /**
         * @param element a DOM element whose namespace is being checked
         * @returns Return false if the element has a
         *  namespace that a spec-compliant parser would never
         *  return. Return true otherwise.
         */
        const _checkValidNamespace = function _checkValidNamespace(element) {
            let parent = getParentNode(element);
            // In JSDOM, if we're inside shadow DOM, then parentNode
            // can be null. We just simulate parent in this case.
            if (!parent || !parent.tagName) {
                parent = {
                    namespaceURI: NAMESPACE,
                    tagName: 'template'
                };
            }
            const tagName = stringToLowerCase(element.tagName);
            const parentTagName = stringToLowerCase(parent.tagName);
            if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
                return false;
            }
            if (element.namespaceURI === SVG_NAMESPACE) {
                return _checkSvgNamespace(tagName, parent, parentTagName);
            }
            if (element.namespaceURI === MATHML_NAMESPACE) {
                return _checkMathMlNamespace(tagName, parent, parentTagName);
            }
            if (element.namespaceURI === HTML_NAMESPACE) {
                return _checkHtmlNamespace(tagName, parent, parentTagName);
            }
            // For XHTML and XML documents that support custom namespaces
            if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && ALLOWED_NAMESPACES[element.namespaceURI]) {
                return true;
            }
            // The code should never reach this place (this means
            // that the element somehow got namespace that is not
            // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).
            // Return false just in case.
            return false;
        };
        /**
         * _forceRemove
         *
         * @param node a DOM node
         */
        const _forceRemove = function _forceRemove(node) {
            arrayPush(DOMPurify.removed, {
                element: node
            });
            try {
                // eslint-disable-next-line unicorn/prefer-dom-node-remove
                getParentNode(node).removeChild(node);
            } catch (_) {
                /* The normal detach failed — this is reached for a parentless node
                   (getParentNode() is null, so .removeChild throws). Element.prototype
                   .remove() is itself a spec no-op on a parentless node, so a recorded
                   "removal" would otherwise hand the caller back an intact,
                   payload-bearing node (e.g. a detached IN_PLACE root the mXSS canary or
                   the style-with-element-child rule decided to kill). Fail closed by
                   throwing — exactly as a clobbered root does at the IN_PLACE entry —
                   rather than trying to "neutralize" the node via its own methods.
                   Neutralizing would mean calling getAttributeNames()/removeAttribute()
                   on the node, both of which a <form> root can clobber via a named child
                   (and _isClobbered does not even probe getAttributeNames), so the
                   neutralize step could itself be silently defeated, leaving the payload
                   intact. A throw touches only the cached, clobber-safe remove() and
                   getParentNode(). Generalizes GHSA-r47g-fvhr-h676 (clobbered-form root)
                   to every root-kill reason. REPORT-3.
                          This lives inside the catch, so it never fires for a normally-removed
                   in-tree node: those have a parent, removeChild() succeeds, and the
                   catch is not entered. Only a kept (parentless) root reaches here. */
                remove(node);
                if (!getParentNode(node)) {
                    throw typeErrorCreate('a node selected for removal could not be detached from its tree ' + 'and cannot be safely returned; refusing to sanitize in place');
                }
            }
        };
        /**
         * _neutralizeRoot
         *
         * Fail-closed teardown of an in-place root after the sanitize walk aborts
         * (campaign-3 F2). An internal throw mid-walk — e.g. a page-registered
         * custom element's reaction detaches a node so `_forceRemove`'s deliberate
         * parentless guard throws, or any other re-entrant engine mutation — would
         * otherwise leave the caller's *live* tree half-sanitized, with everything
         * after the abort point still carrying its handlers. There is no safe way
         * to resume the walk (the tree mutated under us), so we strip the root bare:
         * remove every child and every attribute, then let the caller's catch see
         * the original error. Clobber-safe (cached `remove`/`childNodes`/`attributes`
         * getters; the root was already clobber-pre-flighted at the IN_PLACE entry).
         *
         * @param root the in-place root to empty
         */
        const _neutralizeRoot = function _neutralizeRoot(root) {
            /* Strip every disallowed attribute (on* handlers included) off the whole
               subtree BEFORE detaching anything. Detaching first would hand back
               handler-bearing originals (e.g. an already-loading `<img onerror>`)
               whose queued resource event still fires in page scope after we throw.
               Clobber-safe reads; a doomed clobbered node's own attributes are
               irrelevant while its non-clobbered descendants are reached and scrubbed. */
            _neutralizeSubtree(root);
            const childNodes = getChildNodes(root);
            if (childNodes) {
                const snapshot = [];
                arrayForEach(childNodes, child => {
                    arrayPush(snapshot, child);
                });
                arrayForEach(snapshot, child => {
                    try {
                        remove(child);
                    } catch (_) {
                        /* Best-effort teardown; a still-attached child is handled below */
                    }
                });
            }
            const attributes = getAttributes(root);
            if (attributes) {
                for (let i = attributes.length - 1; i >= 0; --i) {
                    const attribute = attributes[i];
                    const name = attribute && attribute.name;
                    if (typeof name === 'string') {
                        try {
                            root.removeAttribute(name);
                        } catch (_) {
                            /* Clobbered removeAttribute — ignore (fail-closed best effort) */
                        }
                    }
                }
            }
        };
        /**
         * _removeAttribute
         *
         * @param name an Attribute name
         * @param element a DOM node
         */
        const _removeAttribute = function _removeAttribute(name, element) {
            try {
                arrayPush(DOMPurify.removed, {
                    attribute: element.getAttributeNode(name),
                    from: element
                });
            } catch (_) {
                arrayPush(DOMPurify.removed, {
                    attribute: null,
                    from: element
                });
            }
            element.removeAttribute(name);
            // We void attribute values for unremovable "is" attributes
            if (name === 'is') {
                if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
                    try {
                        _forceRemove(element);
                    } catch (_) {}
                } else {
                    try {
                        element.setAttribute(name, '');
                    } catch (_) {}
                }
            }
        };
        /**
         * _stripDisallowedAttributes
         *
         * Removes every attribute the active configuration does not allow from a
         * single element, using the same allowlist as the main attribute pass (so
         * `on*` handlers go, but no `/^on/` blocklist is introduced). Used only to
         * neutralise nodes that are being discarded from an in-place tree.
         *
         * @param element the element to strip
         */
        const _stripDisallowedAttributes = function _stripDisallowedAttributes(element) {
            const attributes = getAttributes(element);
            if (!attributes) {
                return;
            }
            for (let i = attributes.length - 1; i >= 0; --i) {
                const attribute = attributes[i];
                const name = attribute && attribute.name;
                if (typeof name !== 'string' || ALLOWED_ATTR[transformCaseFunc(name)]) {
                    continue;
                }
                try {
                    element.removeAttribute(name);
                } catch (_) {
                    /* Clobbered removeAttribute on a doomed node — ignore */
                }
            }
        };
        /**
         * _neutralizeSubtree
         *
         * Completes the audit-5 F1 fix across every removal path. The KEEP_CONTENT
         * move-hoist neutralises only disallowed-tag removals; clobber, mXSS-canary,
         * namespace, comment, processing-instruction and KEEP_CONTENT:false removals
         * all drop their subtree wholesale via `_forceRemove`. On the IN_PLACE path
         * those dropped nodes are detached from the caller's LIVE tree but a
         * handler-bearing original among them (an `<img onerror>`/`<video>` that was
         * loading) keeps its queued resource event, which fires in page scope after
         * sanitize returns. This walks a removed subtree and strips every attribute
         * the active configuration does not allow — so `on*` handlers are cancelled
         * through the SAME allowlist that governs kept nodes, not a separate `/^on/`
         * blocklist. Run synchronously before sanitize returns, i.e. before any
         * queued event can fire. Hook-free by design: these nodes leave the output,
         * so firing attribute hooks for them would be surprising. Clobber-safe reads;
         * a doomed clobbered node may shadow `removeAttribute` (its own attributes are
         * irrelevant — it is discarded — while its non-clobbered descendants, e.g.
         * the `<img>`, are reached and scrubbed).
         *
         * @param root the root of a removed subtree to neutralise
         */
        const _neutralizeSubtree = function _neutralizeSubtree(root) {
            const stack = [root];
            while (stack.length > 0) {
                const node = stack.pop();
                const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
                if (nodeType === NODE_TYPE.element) {
                    _stripDisallowedAttributes(node);
                }
                const childNodes = getChildNodes(node);
                if (childNodes) {
                    for (let i = childNodes.length - 1; i >= 0; --i) {
                        stack.push(childNodes[i]);
                    }
                }
            }
        };
        /**
         * _neutralizePatchLinkage
         *
         * IN_PLACE entry pre-pass (declarative-partial-updates / streaming
         * hardening, https://github.com/WICG/declarative-partial-updates).
         *
         * The main walk strips patch linkage (`for`/`patchsrc`) and removes range
         * markers (PIs / markup comments) node-by-node, in document order, AS it
         * reaches each node. On a live in-place root that leaves a window: from the
         * moment the root is connected until the walk arrives at a given node, that
         * node's linkage is live. A patch applied on connection/stream can fire as
         * a microtask during the walk and inject or teleport an unsanitized DOM
         * range into a region the iterator has already passed and will not revisit,
         * so the post-return "tree is sanitized" contract is violated. Sweep the
         * whole tree once up front and sever every linkage before the walk begins,
         * closing that window.
         *
         * This CANNOT undo a patch that already fired before sanitize ran — that is
         * the irreducible "do not IN_PLACE a live-connected attacker tree" caveat —
         * but it closes everything from sanitize-start onward. Gated on SAFE_FOR_XML
         * to group with the rest of the declarative-partial-updates handling and
         * stay overridable, consistent with the codebase.
         *
         * Clobber-safe traversal (cached childNodes getter); per-node try/catch so a
         * clobbered root cannot defeat the sweep of its non-clobbered descendants.
         *
         * NOTE (pending real-Chrome confirmation, see test/declarative-patch-probe
         * .html Q1): this mirrors the existing policy of keeping `for` on
         * <label>/<output>. If the shipping feature can drive a patch through a
         * surviving `for`-on-label/output + `id` pair, this pre-pass and the
         * attribute check at _isBasicCustomElement's caller must additionally drop
         * that pair on the IN_PLACE path. Left as-is until the taxonomy is verified.
         *
         * @param root the in-place root to sweep
         */
        const _neutralizePatchLinkage = function _neutralizePatchLinkage(root) {
            if (!SAFE_FOR_XML) {
                return;
            }
            const stack = [root];
            while (stack.length > 0) {
                const node = stack.pop();
                const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
                /* Remove range markers (the target side of a patch linkage): every
                   processing instruction, and any markup-bearing comment. */
                if (nodeType === NODE_TYPE.processingInstruction || nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, node.data)) {
                    try {
                        remove(node);
                    } catch (_) {
                        /* Best-effort */
                    }
                    continue;
                }
                /* Strip patch-source attributes (the source side) off elements. */
                if (nodeType === NODE_TYPE.element) {
                    const element = node;
                    const lcTag = transformCaseFunc(getNodeName ? getNodeName(node) : node.nodeName);
                    try {
                        if (element.hasAttribute && element.hasAttribute('patchsrc')) {
                            element.removeAttribute('patchsrc');
                        }
                        if (element.hasAttribute && element.hasAttribute('for') && lcTag !== 'label' && lcTag !== 'output') {
                            element.removeAttribute('for');
                        }
                    } catch (_) {
                        /* Clobbered removeAttribute/hasAttribute on a doomed node — ignore */
                    }
                }
                const childNodes = getChildNodes(node);
                if (childNodes) {
                    for (let i = childNodes.length - 1; i >= 0; --i) {
                        stack.push(childNodes[i]);
                    }
                }
            }
        };
        /**
         * _initDocument
         *
         * @param dirty - a string of dirty markup
         * @return a DOM, filled with the dirty markup
         */
        const _initDocument = function _initDocument(dirty) {
            /* Create a HTML document */
            let doc = null;
            let leadingWhitespace = null;
            if (FORCE_BODY) {
                dirty = '<remove></remove>' + dirty;
            } else {
                /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */
                const matches = stringMatch(dirty, /^[\r\n\t ]+/);
                leadingWhitespace = matches && matches[0];
            }
            if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' && NAMESPACE === HTML_NAMESPACE) {
                // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)
                dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + '</body></html>';
            }
            const dirtyPayload = trustedTypesPolicy ? _createTrustedHTML(dirty) : dirty;
            /*
             * Use the DOMParser API by default, fallback later if needs be
             * DOMParser not work for svg when has multiple root element.
             */
            if (NAMESPACE === HTML_NAMESPACE) {
                try {
                    doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
                } catch (_) {}
            }
            /* Use createHTMLDocument in case DOMParser is not available */
            if (!doc || !doc.documentElement) {
                doc = implementation.createDocument(NAMESPACE, 'template', null);
                try {
                    doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
                } catch (_) {
                    // Syntax error if dirtyPayload is invalid xml
                }
            }
            const body = doc.body || doc.documentElement;
            if (dirty && leadingWhitespace) {
                body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);
            }
            /* Work on whole document or just its body */
            if (NAMESPACE === HTML_NAMESPACE) {
                return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];
            }
            return WHOLE_DOCUMENT ? doc.documentElement : body;
        };
        /**
         * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.
         *
         * @param root The root element or node to start traversing on.
         * @return The created NodeIterator
         */
        const _createNodeIterator = function _createNodeIterator(root) {
            /* Read ownerDocument through the cached Node.prototype getter, never the
               direct property. HTMLFormElement has [LegacyOverrideBuiltIns], so a
               clobbering child (<input name="ownerDocument"> or a form-associated
               external input) shadows the prototype getter and makes a direct read
               return that <input>. createNodeIterator.call(<input>, ...) then throws
               "Illegal invocation", and on the IN_PLACE path that throw lands before
               the walk's fail-closed barrier - leaving the caller's live tree, with
               any already-armed handler in it, un-neutralized. The cached getter
               returns the real Document regardless of the clobber. */
            const doc = getOwnerDocument ? getOwnerDocument(root) : root.ownerDocument;
            return createNodeIterator.call(doc || root, root,
                // eslint-disable-next-line no-bitwise
                NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);
        };
        /**
         * Replace template expression syntax (mustache, ERB, template
         * literal) with a space; shared by all SAFE_FOR_TEMPLATES scrub
         * sites. Order matters: mustache, then ERB, then template literal.
         *
         * @param value the string to scrub
         * @returns the scrubbed string
         */
        const _stripTemplateExpressions = function _stripTemplateExpressions(value) {
            value = stringReplace(value, MUSTACHE_EXPR$1, ' ');
            value = stringReplace(value, ERB_EXPR$1, ' ');
            value = stringReplace(value, TMPLIT_EXPR$1, ' ');
            return value;
        };
        /**
         * Strip template-engine expressions ({{...}}, ${...}, <%...%>) from the
         * character data of an element subtree. Used as the final safety net for
         * SAFE_FOR_TEMPLATES on every DOM-returning code path so that expressions
         * which only form after text-node normalization (e.g. fragments split across
         * stripped elements) cannot survive into a template-evaluating framework.
         *
         * Walks text/comment/CDATA/processing-instruction nodes and mutates `.data`
         * in place rather than round-tripping through innerHTML. This preserves
         * descendant node references (important for IN_PLACE callers), avoids a
         * serialize/reparse cycle, and reads literal character data — which means
         * `<%...%>` in text content matches the ERB regex against its real bytes
         * instead of the HTML-entity-escaped form innerHTML would produce.
         *
         * Attribute values are not visited here; SAFE_FOR_TEMPLATES handling for
         * attributes is performed during the per-node `_sanitizeAttributes` pass.
         *
         * @param node The root element whose character data should be scrubbed.
         */
        const _scrubTemplateExpressions2 = function _scrubTemplateExpressions(node) {
            var _node$querySelectorAl;
            node.normalize();
            /* Clobber-safe ownerDocument read, same reasoning as _createNodeIterator:
               under SAFE_FOR_TEMPLATES this runs on the live IN_PLACE root, which may
               carry a form-named-getter override of ownerDocument. */
            const doc = getOwnerDocument ? getOwnerDocument(node) : node.ownerDocument;
            const walker = createNodeIterator.call(doc || node, node,
                // eslint-disable-next-line no-bitwise
                NodeFilter.SHOW_TEXT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_CDATA_SECTION | NodeFilter.SHOW_PROCESSING_INSTRUCTION, null);
            let currentNode = walker.nextNode();
            while (currentNode) {
                currentNode.data = _stripTemplateExpressions(currentNode.data);
                currentNode = walker.nextNode();
            }
            // NodeIterator does not descend into <template>.content per the DOM spec,
            // so we must explicitly recurse into each template's content fragment,
            // mirroring the approach used by _sanitizeShadowDOM.
            const templates = (_node$querySelectorAl = node.querySelectorAll) === null || _node$querySelectorAl === void 0 ? void 0 : _node$querySelectorAl.call(node, 'template');
            if (templates) {
                arrayForEach(templates, tmpl => {
                    if (_isDocumentFragment(tmpl.content)) {
                        _scrubTemplateExpressions2(tmpl.content);
                    }
                });
            }
        };
        /**
         * _isClobbered
         *
         * Detect DOM-clobbering on HTMLFormElement nodes. Form is the only HTML
         * interface with [LegacyOverrideBuiltIns]; a descendant element with a
         * `name` attribute matching a prototype property shadows that property
         * on direct reads. We use this check at the IN_PLACE entry-point and
         * during attribute sanitization to refuse clobbered forms.
         *
         * @param element element to check for clobbering attacks
         * @return true if clobbered, false if safe
         */
        const _isClobbered = function _isClobbered(element) {
            // Realm-independent tag-name probe. If we can't determine the tag
            // name at all, we can't reason about clobbering — return false
            // (the caller's other defences still apply).
            const realTagName = getNodeName ? getNodeName(element) : null;
            if (typeof realTagName !== 'string') {
                return false;
            }
            if (transformCaseFunc(realTagName) !== 'form') {
                return false;
            }
            return typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' ||
                // Realm-safe NamedNodeMap detection: equality against the cached
                // prototype getter. Clobbered .attributes (e.g. <input name="attributes">)
                // makes the direct read diverge from the cached read; a clean form
                // (same-realm OR foreign-realm) has both reads pointing at the same
                // canonical NamedNodeMap.
                element.attributes !== getAttributes(element) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function' ||
                // NodeType clobbering probe. Cached Node.prototype.nodeType getter
                // returns the integer 1 for any Element regardless of realm; direct
                // read on a clobbered form (e.g. <input name="nodeType">) returns
                // the named child element. Cheap addition — nodeType is read from
                // an internal slot, no serialization cost — and removes a residual
                // clobbering surface used by several mXSS / PI / comment branches
                // in _sanitizeElements that compare currentNode.nodeType directly.
                element.nodeType !== getNodeType(element) ||
                // HTMLFormElement has [LegacyOverrideBuiltIns]: a descendant named
                // "childNodes" shadows the prototype getter. Direct reads of
                // form.childNodes from a clobbered form return the named child
                // instead of the real NodeList, so any walk that reads it directly
                // skips the form's real children. Compare the direct read to the
                // cached Node.prototype getter — when the form's named-property
                // getter intercepts the read, the two values differ and we flag
                // the form. This catches every clobbering child type (input,
                // select, etc.) regardless of whether the named child happens to
                // carry a numeric .length, which a typeof-based probe would miss
                // (e.g. HTMLSelectElement.length is a defined unsigned-long).
                element.childNodes !== getChildNodes(element);
        };
        /**
         * Checks whether the given value is a DocumentFragment from any realm.
         *
         * The realm-independent replacement reads `nodeType` through the cached
         * Node.prototype getter and compares to the DOCUMENT_FRAGMENT_NODE
         * constant (11). nodeType is a numeric value resolved from the node's
         * internal slot, identical across realms for the same kind of node.
         *
         * @param value object to check
         * @return true if value is a DocumentFragment-shaped node from any realm
         */
        const _isDocumentFragment = function _isDocumentFragment(value) {
            if (!getNodeType || typeof value !== 'object' || value === null) {
                return false;
            }
            try {
                return getNodeType(value) === NODE_TYPE.documentFragment;
            } catch (_) {
                return false;
            }
        };
        /**
         * Checks whether the given object is a DOM node, including nodes that
         * originate from a different window/realm (e.g. an iframe's
         * contentDocument). The previous `value instanceof Node` check was
         * realm-bound: nodes from a different window failed it, causing
         * sanitize() to silently stringify them and reset IN_PLACE to false,
         * returning the original node unsanitized. See GHSA-4w3q-35jp-p934.
         *
         * @param value object to check whether it's a DOM node
         * @return true if value is a DOM node from any realm
         */
        const _isNode = function _isNode(value) {
            if (!getNodeType || typeof value !== 'object' || value === null) {
                return false;
            }
            try {
                return typeof getNodeType(value) === 'number';
            } catch (_) {
                return false;
            }
        };

        function _executeHooks(hooks, currentNode, data) {
            if (hooks.length === 0) {
                return;
            }
            arrayForEach(hooks, hook => {
                hook.call(DOMPurify, currentNode, data, CONFIG);
            });
        }
        /**
         * Structural-threat checks that condemn a node regardless of the
         * allowlists: mXSS via namespace confusion, risky CSS construction,
         * processing instructions, markup-bearing comments. Pure predicate;
         * the caller removes. Check order is load-bearing.
         *
         * @param currentNode the node to inspect
         * @param tagName the node's transformCaseFunc'd tag name
         * @return true if the node must be removed
         */
        const _isUnsafeNode = function _isUnsafeNode(currentNode, tagName) {
            /* Detect mXSS attempts abusing namespace confusion */
            if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) {
                return true;
            }
            /* Remove risky CSS construction leading to mXSS */
            if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === 'style' && _isNode(currentNode.firstElementChild)) {
                return true;
            }
            /* Remove any occurrence of processing instructions */
            if (currentNode.nodeType === NODE_TYPE.processingInstruction) {
                return true;
            }
            /* Remove any kind of possibly harmful comments */
            if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, currentNode.data)) {
                return true;
            }
            return false;
        };
        /**
         * Handle a node whose tag is forbidden or not allowlisted: keep
         * allowed custom elements (false return exits _sanitizeElements
         * early - the namespace and fallback-tag removal checks are
         * intentionally skipped for kept custom elements), else hoist
         * content per KEEP_CONTENT and remove.
         *
         * A kept custom element is the ONLY case in which this function
         * returns false, so the caller uses that return value to run the
         * afterSanitizeElements hook on the kept element and keep the
         * element-hook lifecycle consistent with normal allowlisted
         * elements (GHSA-c2j3-45gr-mqc4).
         *
         * @param currentNode the disallowed node
         * @param tagName the node's transformCaseFunc'd tag name
         * @return true if the node was removed, false if kept
         */
        const _sanitizeDisallowedNode = function _sanitizeDisallowedNode(currentNode, tagName, root) {
            /* Check if we have a custom element to handle */
            if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
                if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
                    return false;
                }
                if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
                    return false;
                }
            }
            /* Keep content except for bad-listed elements.
                 Use the cached prototype getters exclusively — the previous code
                 had `|| currentNode.parentNode` / `|| currentNode.childNodes`
                 fallbacks, but the cached getters always return the canonical
                 value (or null for a real parent-less node), so the fallback
                 path was dead in safe cases and a clobbering surface in unsafe
                 ones. Falsy cached results stay falsy; the `if (childNodes &&
                 parentNode)` check already gates correctly. */
            if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
                const parentNode = getParentNode(currentNode);
                const childNodes = getChildNodes(currentNode);
                if (childNodes && parentNode) {
                    const childCount = childNodes.length;
                    /* Hoist by moving each child up one level rather than deep-cloning
                         it. Moving transfers every descendant exactly once, so a chain of
                         nested disallowed elements costs O(n) instead of the O(n^2) that
                         re-cloning the shrinking subtree at each level produced; it also
                         empties the removed original, so `DOMPurify.removed` no longer
                         pins whole subtrees. Moving preserves the in-place guarantee too:
                         an original carrying already-queued resource events (`<img
                         onerror>`, `<video>`/`<audio>` error, lazy/`onload`, …) is
                         relocated and sanitised rather than left detached but still armed.
                                  The sole case that must clone is removing the walk root itself.
                         The result is serialised from the root's subtree, so a restrictive
                         ALLOWED_TAGS that strips the root (`body` on the string path) must
                         leave the content inside it, which only cloning does. In IN_PLACE
                         the root is pre-validated as an allowed tag and so is never removed
                         here, so that path always takes the move branch.
                                  `childNodes` is live; a tail-to-head walk keeps `childNodes[i]`
                         valid whether we move (drops the trailing entry) or clone (leaves
                         the list intact). */
                    for (let i = childCount - 1; i >= 0; --i) {
                        const hoisted = currentNode === root ? cloneNode(childNodes[i], true) : childNodes[i];
                        parentNode.insertBefore(hoisted, getNextSibling(currentNode));
                    }
                }
            }
            _forceRemove(currentNode);
            return true;
        };
        /**
         * Fork a hook-mutable allowlist off its shared binding the first time a
         * (possibly lazily-installed) uponSanitize* hook is about to see it, so the
         * hook cannot widen the per-instance default or the setConfig binding by
         * reference and leak past the call. Returns the set unchanged once it is
         * already call-local, so repeated calls across elements are idempotent.
         *
         * @param hookList the uponSanitize* hook array for this event
         * @param set the current ALLOWED_TAGS / ALLOWED_ATTR binding
         * @param defaultSet the per-instance DEFAULT_ALLOWED_* constant
         * @param setConfigSet the captured setConfig() binding, or null
         * @return a call-local clone if a hook is present and set is still shared,
         *   else set unchanged
         */
        const _forkSharedAllowlist = function _forkSharedAllowlist(hookList, set, defaultSet, setConfigSet) {
            if (hookList.length === 0) {
                return set;
            }
            return set === defaultSet || set === setConfigSet ? clone(set) : set;
        };
        /**
         * _sanitizeElements
         *
         * @protect nodeName
         * @protect textContent
         * @protect removeChild
         * @param currentNode to check for permission to exist
         * @return true if node was killed, false if left alive
         */
        // eslint-disable-next-line complexity
        const _sanitizeElements = function _sanitizeElements(currentNode, root) {
            /* Execute a hook if present */
            _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
            /* A hook may have detached the node - treat it as removed (see the
               detached-node comment after the uponSanitizeElement hook below). On
               the IN_PLACE path, neutralize the detached subtree first so a queued
               resource handler on it cannot fire in page scope after we return. */
            if (currentNode !== root && getParentNode(currentNode) === null) {
                if (IN_PLACE) {
                    _neutralizeSubtree(currentNode);
                }
                return true;
            }
            /* Check if element is clobbered or can clobber */
            if (_isClobbered(currentNode)) {
                _forceRemove(currentNode);
                return true;
            }
            /* Now let's check the element's type and name */
            const tagName = transformCaseFunc(getNodeName ? getNodeName(currentNode) : currentNode.nodeName);
            /* Close the pre-walk clone-guard's timing gap: an uponSanitizeElement
               hook may have been installed after that guard sampled the hook arrays
               (e.g. lazily from beforeSanitizeElements), leaving ALLOWED_TAGS still
               aliasing a shared binding that a widening hook would mutate by
               reference. Fork it before exposing it to the hook. */
            ALLOWED_TAGS = _forkSharedAllowlist(hooks.uponSanitizeElement, ALLOWED_TAGS, DEFAULT_ALLOWED_TAGS, SET_CONFIG_ALLOWED_TAGS);
            /* Execute a hook if present */
            _executeHooks(hooks.uponSanitizeElement, currentNode, {
                tagName,
                allowedTags: ALLOWED_TAGS
            });
            /* A hook may have detached the node from the tree — a long-standing
               user pattern (issue #469; draw.io-style foreignObject filtering).
               Per the cached, unclobberable parentNode getter the node is
               genuinely out of the tree, so it can reach neither the serialized
               output nor an IN_PLACE live tree; treat it as removed and stop
               processing it. Without this guard, the unsafe-node / namespace
               checks below would call _forceRemove on a parentless node and hit
               the REPORT-3 fail-closed throw — which exists for nodes DOMPurify
               wants gone but *cannot* detach (clobbered / parentless roots), the
               opposite of a node that is already safely gone. The walk root is
               exempt: a detached IN_PLACE root is legitimate input and must still
               be fully sanitized, and a kill-decision on it must keep hitting the
               REPORT-3 throw. Nodes detached by hooks stay the hook's
               responsibility for placement: they are not recorded in
               DOMPurify.removed, so the post-walk IN_PLACE pass (which iterates
               DOMPurify.removed) does not reach them. But a hook-detached subtree
               can still hold a queued resource-event handler - e.g. an <img onload>
               that began loading when the caller built the live tree - which fires
               in page scope after sanitize returns even though the handler never
               reached the returned tree. That is the audit-5 F1 hazard, and the
               documented node.remove() hook pattern walks straight into it. So on
               the IN_PLACE path we neutralize the detached subtree inline here,
               stripping its non-allow-listed attributes before returning, exactly
               as the post-walk pass does for _forceRemove'd subtrees. */
            if (currentNode !== root && getParentNode(currentNode) === null) {
                if (IN_PLACE) {
                    _neutralizeSubtree(currentNode);
                }
                return true;
            }
            /* Remove mXSS vectors, processing instructions and risky comments */
            if (_isUnsafeNode(currentNode, tagName)) {
                _forceRemove(currentNode);
                return true;
            }
            /* Remove element if anything forbids its presence */
            if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
                const removed = _sanitizeDisallowedNode(currentNode, tagName, root);
                /* A false return means the node is a custom element kept via
                   CUSTOM_ELEMENT_HANDLING - the only keep path through
                   _sanitizeDisallowedNode. Run afterSanitizeElements on it so the
                   element-hook lifecycle matches normal allowlisted elements: a
                   security policy applied in this hook (e.g. stripping an attribute
                   from every surviving element) must not silently skip kept custom
                   elements (GHSA-c2j3-45gr-mqc4). This mirrors the normal-element
                   tail below - the hook runs, then the walker's subsequent
                   _sanitizeAttributes pass sanitizes the element's attributes. The
                   deliberately skipped namespace and fallback-tag removal checks stay
                   skipped; they are removal decisions, not the hook contract. */
                if (removed === false) {
                    _executeHooks(hooks.afterSanitizeElements, currentNode, null);
                }
                return removed;
            }
            /* Check whether element has a valid namespace.
               Realm-safe check (GHSA-hpcv-96wg-7vj8): use the cached Node.prototype
               nodeType getter rather than `instanceof Element`, which is realm-
               bound and short-circuits to false for any node minted in a different
               realm — letting a foreign-realm element with a forbidden namespace
               slip past the namespace check entirely. */
            const nt = getNodeType ? getNodeType(currentNode) : currentNode.nodeType;
            if (nt === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
                _forceRemove(currentNode);
                return true;
            }
            /* Make sure that older browsers don't get fallback-tag mXSS */
            if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') && regExpTest(FALLBACK_TAG_CLOSE, currentNode.innerHTML)) {
                _forceRemove(currentNode);
                return true;
            }
            /* Sanitize element content to be template-safe */
            if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
                /* Get the element's text content */
                const content = _stripTemplateExpressions(currentNode.textContent);
                if (currentNode.textContent !== content) {
                    arrayPush(DOMPurify.removed, {
                        element: currentNode.cloneNode()
                    });
                    currentNode.textContent = content;
                }
            }
            /* Execute a hook if present */
            _executeHooks(hooks.afterSanitizeElements, currentNode, null);
            return false;
        };
        /**
         * _isValidAttribute
         *
         * @param lcTag Lowercase tag name of containing element.
         * @param lcName Lowercase attribute name.
         * @param value Attribute value.
         * @return Returns true if `value` is valid, otherwise false.
         */
        // eslint-disable-next-line complexity
        const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {
            /* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */
            if (FORBID_ATTR[lcName]) {
                return false;
            }
            /* Reject declarative-partial-updates patch-linkage attributes
               (https://github.com/WICG/declarative-partial-updates).
                    Empirical note (Chrome 150, verified — see
               test/declarative-patch-probe-v3.html): expansion is NOT applied after
               sanitization. For the string path it fires during sanitize()'s own
               parse, so the walk sees and sanitizes the fully materialized expanded
               tree — teleports into MathML/SVG integration points included; a
               weaponized `<template for>`->`<img onerror>` comes back with the handler
               stripped. For the IN_PLACE path it fires on connection, before the walk.
               Either way DOMPurify is NOT blind to the patch.
                    This removal is therefore defense-in-depth rather than the sole barrier:
               it prevents live linkage from surviving into the OUTPUT and re-expanding
               in the caller's context, and keeps behaviour deterministic if a future
               engine defers expansion. `for` is legitimate only on <label>/<output>;
               anywhere else (notably <template for>) it links the element to a patch
               target and teleports or removes an arbitrary DOM range by id/marker name.
               `patchsrc` fetches remote markup and is treated as a script-loading
               mechanism (CSP). Gated on SAFE_FOR_XML so the removal groups with the
               other structural-threat checks and stays overridable, consistent with
               the rest of the codebase. PI range markers are already removed by
               _isUnsafeNode. */
            if (SAFE_FOR_XML && lcName === 'patchsrc') {
                return false;
            }
            if (SAFE_FOR_XML && lcName === 'for' && lcTag !== 'label' && lcTag !== 'output') {
                return false;
            }
            /* Make sure attribute cannot clobber */
            if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {
                return false;
            }
            const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
            /* Allow valid data-* attributes: At least one character after "-"
                (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
                XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
                We don't need to check the value; it's always URI safe. */
            if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName));
            else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName));
            else if (!nameIsPermitted) {
                if (
                    // First condition does a very basic check if a) it's basically a valid custom element tagname AND
                    // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
                    // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
                    _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) ||
                    // Alternative, second condition checks if it's an `is`-attribute, AND
                    // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
                    lcName === 'is' && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value)));
                else {
                    return false;
                }
                /* Check value is safe. First, is attr inert? If so, is safe */
            } else if (URI_SAFE_ATTRIBUTES[lcName]);
            else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
            else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]);
            else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, '')));
            else if (value) {
                return false;
            } else;
            return true;
        };
        /* Names the HTML spec reserves from valid-custom-element-name; these must
         * never be treated as basic custom elements even when a permissive
         * CUSTOM_ELEMENT_HANDLING.tagNameCheck is configured. */
        const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, ['annotation-xml', 'color-profile', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'missing-glyph']);
        /**
         * _isBasicCustomElement
         * checks if at least one dash is included in tagName, and it's not the first char
         * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name
         *
         * @param tagName name of the tag of the node to sanitize
         * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.
         */
        const _isBasicCustomElement = function _isBasicCustomElement(tagName) {
            return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
        };
        /**
         * Wrap an attribute value in the matching Trusted Types object when
         * the active policy requires it. Namespaced attributes pass through
         * unchanged (no TT support yet, see
         * https://bugs.chromium.org/p/chromium/issues/detail?id=1305293).
         *
         * @param lcTag lowercase tag name of the containing element
         * @param lcName lowercase attribute name
         * @param namespaceURI the attribute's namespace, if any
         * @param value the attribute value to wrap
         * @return the value, wrapped when Trusted Types demand it
         */
        const _applyTrustedTypesToAttribute = function _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value) {
            if (trustedTypesPolicy && typeof trustedTypes === 'object' && typeof trustedTypes.getAttributeType === 'function' && !namespaceURI) {
                switch (trustedTypes.getAttributeType(lcTag, lcName)) {
                    case 'TrustedHTML': {
                        return _createTrustedHTML(value);
                    }
                    case 'TrustedScriptURL': {
                        return _createTrustedScriptURL(value);
                    }
                }
            }
            return value;
        };
        /**
         * Write a modified attribute value back onto the element. On
         * success, re-probe for clobbering introduced by the new value and
         * remove the element when found; otherwise pop the removal entry
         * recorded by the earlier _removeAttribute (long-standing pairing
         * with the SANITIZE_NAMED_PROPS path - do not "fix" casually). On
         * failure, remove the attribute instead.
         *
         * @param currentNode the element carrying the attribute
         * @param name the attribute name as present on the element
         * @param namespaceURI the attribute's namespace, if any
         * @param value the new attribute value
         */
        const _setAttributeValue = function _setAttributeValue(currentNode, name, namespaceURI, value) {
            try {
                if (namespaceURI) {
                    currentNode.setAttributeNS(namespaceURI, name, value);
                } else {
                    /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. "x-schema". */
                    currentNode.setAttribute(name, value);
                }
                if (_isClobbered(currentNode)) {
                    _forceRemove(currentNode);
                } else {
                    arrayPop(DOMPurify.removed);
                }
            } catch (_) {
                _removeAttribute(name, currentNode);
            }
        };
        /**
         * _sanitizeAttributes
         *
         * @protect attributes
         * @protect nodeName
         * @protect removeAttribute
         * @protect setAttribute
         *
         * @param currentNode to sanitize
         */
        const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {
            /* Execute a hook if present */
            _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
            const attributes = currentNode.attributes;
            /* Check if we have attributes; if not we might have a text node */
            if (!attributes || _isClobbered(currentNode)) {
                return;
            }
            /* Same lazy-install guard as uponSanitizeElement (see there): fork the
               attribute allowlist off its shared binding before a hook can see it. */
            ALLOWED_ATTR = _forkSharedAllowlist(hooks.uponSanitizeAttribute, ALLOWED_ATTR, DEFAULT_ALLOWED_ATTR, SET_CONFIG_ALLOWED_ATTR);
            const hookEvent = {
                attrName: '',
                attrValue: '',
                keepAttr: true,
                allowedAttributes: ALLOWED_ATTR,
                forceKeepAttr: undefined
            };
            let l = attributes.length;
            const lcTag = transformCaseFunc(currentNode.nodeName);
            /* Go backwards over all attributes; safely remove bad ones */
            while (l--) {
                const attr = attributes[l];
                const name = attr.name,
                    namespaceURI = attr.namespaceURI,
                    attrValue = attr.value;
                const lcName = transformCaseFunc(name);
                const initValue = attrValue;
                let value = name === 'value' ? initValue : stringTrim(initValue);
                /* Execute a hook if present */
                hookEvent.attrName = lcName;
                hookEvent.attrValue = value;
                hookEvent.keepAttr = true;
                hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set
                _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
                value = hookEvent.attrValue;
                /* Full DOM Clobbering protection via namespace isolation,
                 * Prefix id and name attributes with `user-content-`
                 */
                if (SANITIZE_NAMED_PROPS && (lcName === 'id' || lcName === 'name') && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
                    // Remove the attribute with this value
                    _removeAttribute(name, currentNode);
                    // Prefix the value and later re-create the attribute with the sanitized value
                    value = SANITIZE_NAMED_PROPS_PREFIX + value;
                }
                // Else: already prefixed, leave the attribute alone — the prefix is
                // itself the clobbering protection, and re-applying it is incorrect.
                /* Work around a security issue with comments inside attributes */
                if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
                    _removeAttribute(name, currentNode);
                    continue;
                }
                /* Make sure we cannot easily use animated hrefs, even if animations are allowed */
                if (lcName === 'attributename' && stringMatch(value, 'href')) {
                    _removeAttribute(name, currentNode);
                    continue;
                }
                /* Did the hooks force-keep the attribute? */
                if (hookEvent.forceKeepAttr) {
                    continue;
                }
                /* Did the hooks approve of the attribute? */
                if (!hookEvent.keepAttr) {
                    _removeAttribute(name, currentNode);
                    continue;
                }
                /* Work around a security issue in jQuery 3.0 */
                if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) {
                    _removeAttribute(name, currentNode);
                    continue;
                }
                /* Sanitize attribute content to be template-safe */
                if (SAFE_FOR_TEMPLATES) {
                    value = _stripTemplateExpressions(value);
                }
                /* Is `value` valid for this attribute? */
                if (!_isValidAttribute(lcTag, lcName, value)) {
                    _removeAttribute(name, currentNode);
                    continue;
                }
                /* Handle attributes that require Trusted Types */
                value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value);
                /* Handle invalid data-* attribute set by try-catching it */
                if (value !== initValue) {
                    _setAttributeValue(currentNode, name, namespaceURI, value);
                }
            }
            /* Execute a hook if present */
            _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
        };
        /**
         * _sanitizeShadowDOM
         *
         * @param fragment to iterate over recursively
         */
        const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
            let shadowNode = null;
            const shadowIterator = _createNodeIterator(fragment);
            /* Execute a hook if present */
            _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
            while (shadowNode = shadowIterator.nextNode()) {
                /* Execute a hook if present */
                _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
                /* Sanitize tags and elements */
                _sanitizeElements(shadowNode, fragment);
                /* Check attributes next */
                _sanitizeAttributes(shadowNode);
                /* Deep shadow DOM detected.
                   Realm-safe check (GHSA-hpcv-96wg-7vj8): use nodeType against the
                   DOCUMENT_FRAGMENT_NODE constant rather than instanceof, so we
                   recurse into <template>.content from foreign realms too. */
                if (_isDocumentFragment(shadowNode.content)) {
                    _sanitizeShadowDOM2(shadowNode.content);
                }
                /* An element iterated here may itself host an attached
                   shadow root. The default NodeIterator does not enter shadow
                   trees, so a shadow root nested inside template.content was
                   previously reached by no walk at all (the pre-pass at
                   _sanitizeAttachedShadowRoots descends via childNodes, which
                   doesn't enter template.content; the template-content recursion
                   above iterates the content but never inspected shadowRoot).
                   Walk it explicitly. The nodeType guard avoids reading
                   shadowRoot off text / comment / CDATA / PI nodes that the
                   iterator also surfaces. */
                const shadowNodeType = getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType;
                if (shadowNodeType === NODE_TYPE.element) {
                    const innerSr = getShadowRoot(shadowNode);
                    if (_isDocumentFragment(innerSr)) {
                        _sanitizeAttachedShadowRoots(innerSr);
                        _sanitizeShadowDOM2(innerSr);
                    }
                }
            }
            /* Execute a hook if present */
            _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
        };
        /**
         * _sanitizeAttachedShadowRoots
         *
         * Walks `root` and feeds every attached shadow root we encounter into
         * the existing _sanitizeShadowDOM pipeline. The default node iterator
         * does not descend into shadow trees, so nodes inside an attached
         * shadow root would otherwise be skipped entirely.
         *
         * Two real input paths put attached shadow roots in front of us:
         *   1. IN_PLACE on a DOM node that already has shadow roots attached.
         *   2. DOM-node input where importNode(dirty, true) deep-clones the
         *      shadow root because it was created with `clonable: true`.
         *
         * This pass runs once, up front, so the main iteration loop (and the
         * existing _sanitizeShadowDOM template-content recursion) stay
         * untouched — string-input paths are not affected.
         *
         * @param root the subtree root to walk for attached shadow roots
         */
        const _sanitizeAttachedShadowRoots = function _sanitizeAttachedShadowRoots(root) {
            /* Iterative (explicit stack) rather than per-child recursion. DOM APIs
               impose no depth cap, so an attacker-shaped tree (JSON/CRDT/editor data
               built straight into the DOM — the IN_PLACE surface) deeper than the JS
               call-stack budget would otherwise overflow native recursion here and
               throw at the IN_PLACE entry pre-pass, before a single node is
               sanitized, leaving the caller's live tree untouched (fail-open). See
               campaign-3 F4. A heap stack keeps depth off the call stack.
                    Each work item is either a node to descend into, or a deferred
               `_sanitizeShadowDOM` for an already-walked shadow root. The deferred
               form preserves the original post-order discipline: a shadow root's
               nested shadow roots are discovered before the outer shadow is
               sanitized (which may remove hosts). Pushes are in reverse of the
               desired processing order (LIFO): template content, then children, then
               the shadow-sanitize, then the shadow walk — so the order matches the
               previous recursion exactly. */
            const stack = [{
                node: root,
                shadow: null
            }];
            while (stack.length > 0) {
                const item = stack.pop();
                /* Deferred shadow-DOM sanitisation: runs after its subtree was walked. */
                if (item.shadow) {
                    _sanitizeShadowDOM2(item.shadow);
                    continue;
                }
                const node = item.node;
                const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
                const isElement = nodeType === NODE_TYPE.element;
                /* (pushed last → processed first) Children, snapshotted in reverse so
                   the first child is processed first. Snapshotting matters because a
                   hook may detach siblings mid-walk. */
                const childNodes = getChildNodes(node);
                if (childNodes) {
                    for (let i = childNodes.length - 1; i >= 0; --i) {
                        stack.push({
                            node: childNodes[i],
                            shadow: null
                        });
                    }
                }
                /* (pushed before children → processed after them, matching the old
                   "template content last" order) When the node is a <template>,
                   descend into its content. */
                if (isElement) {
                    const rootName = getNodeName ? getNodeName(node) : null;
                    if (typeof rootName === 'string' && transformCaseFunc(rootName) === 'template') {
                        const content = node.content;
                        if (_isDocumentFragment(content)) {
                            stack.push({
                                node: content,
                                shadow: null
                            });
                        }
                    }
                }
                /* Shadow root (processed first): walk its subtree, then sanitise it.
                   Realm-safe check (GHSA-hpcv-96wg-7vj8): nodeType-based detection
                   rather than `instanceof DocumentFragment`, which is realm-bound and
                   silently skipped foreign-realm shadow roots (e.g.
                   iframe.contentDocument attachShadow). */
                if (isElement) {
                    const sr = getShadowRoot(node);
                    if (_isDocumentFragment(sr)) {
                        /* Push the deferred sanitise first so it pops after the shadow
                           walk we push next, i.e. nested shadow roots are discovered
                           before this one is sanitised. */
                        stack.push({
                            node: null,
                            shadow: sr
                        }, {
                            node: sr,
                            shadow: null
                        });
                    }
                }
            }
        };
        // eslint-disable-next-line complexity
        DOMPurify.sanitize = function(dirty) {
            let cfg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
            let body = null;
            let importedNode = null;
            let currentNode = null;
            let returnNode = null;
            /* Make sure we have a string to sanitize.
              DO NOT return early, as this will return the wrong type if
              the user has requested a DOM object rather than a string */
            IS_EMPTY_INPUT = !dirty;
            if (IS_EMPTY_INPUT) {
                dirty = '<!-->';
            }
            /* Stringify, in case dirty is an object */
            if (typeof dirty !== 'string' && !_isNode(dirty)) {
                dirty = stringifyValue(dirty);
                if (typeof dirty !== 'string') {
                    throw typeErrorCreate('dirty is not a string, aborting');
                }
            }
            /* Return dirty HTML if DOMPurify cannot run */
            if (!DOMPurify.isSupported) {
                return dirty;
            }
            /* Assign config vars */
            if (SET_CONFIG) {
                /* Persistent setConfig() path: _parseConfig is skipped, so the sets are
                 * not re-derived per call. Restore them from the pristine bindings
                 * captured at setConfig() time so a previous call's hook clone (mutated
                 * below) does not carry over. */
                ALLOWED_TAGS = SET_CONFIG_ALLOWED_TAGS;
                ALLOWED_ATTR = SET_CONFIG_ALLOWED_ATTR;
            } else {
                _parseConfig(cfg);
            }
            /* Clone the hook-mutable allowlists before the walk whenever an
             * uponSanitize* hook is registered. The hook event exposes ALLOWED_TAGS
             * and ALLOWED_ATTR by reference (as allowedTags / allowedAttributes), so
             * a hook that widens them would otherwise mutate the shared set
             * permanently: across later calls and across every element. Cloning per
             * walk keeps documented in-call widening working while scoping it to the
             * call. A single guard for both config paths - the per-call path rebinds
             * the sets in _parseConfig each call, the persistent path restores them
             * from the captured bindings just above - so the two cannot diverge. */
            if (hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) {
                ALLOWED_TAGS = clone(ALLOWED_TAGS);
            }
            if (hooks.uponSanitizeAttribute.length > 0) {
                ALLOWED_ATTR = clone(ALLOWED_ATTR);
            }
            /* Clean up removed elements */
            DOMPurify.removed = [];
            /* Resolve IN_PLACE for this call without mutating persistent config.
               Writing the IN_PLACE closure variable here leaks under setConfig(),
               where _parseConfig is skipped on later calls: a single string call would
               disable in-place mode for every subsequent node call, returning a
               sanitized copy while leaving the caller's node — which in-place callers
               keep using and whose return value they ignore — unsanitized. REPORT-2. */
            const inPlace = IN_PLACE && typeof dirty !== 'string' && _isNode(dirty);
            if (inPlace) {
                /* Declarative-partial-updates / streaming pre-pass: sever every patch
                   linkage across the live tree BEFORE the walk, so no patch can fire
                   mid-walk and inject into an already-processed region. Runs first, so
                   it also covers the forbidden/clobbered roots that throw below. */
                _neutralizePatchLinkage(dirty);
                /* Do some early pre-sanitization to avoid unsafe root nodes.
                   Read nodeName through the cached prototype getter — a clobbering
                   child named "nodeName" on the form root would otherwise shadow
                   the property and let this check skip the root-allowlist
                   validation entirely. */
                const nn = getNodeName ? getNodeName(dirty) : dirty.nodeName;
                if (typeof nn === 'string') {
                    const tagName = transformCaseFunc(nn);
                    if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
                        /* Fail closed on a live root: neutralize handlers/children before
                           throwing, exactly as the mid-walk abort path does. */
                        _neutralizeRoot(dirty);
                        throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');
                    }
                }
                /* Pre-flight the root through _isClobbered. The iterator-driven
                   removal path can not detach a parent-less root: _forceRemove
                   falls through to Element.prototype.remove(), which per spec
                   is a no-op on a node with no parent. A clobbered root would
                   then survive the main loop with its attributes uninspected,
                   because _sanitizeAttributes early-returns on _isClobbered. The
                   result would be an attacker-controlled form, complete with any
                   event-handler attributes the caller passed in, handed back to
                   the application unsanitized. Refuse to sanitize such a root
                   the same way we refuse a forbidden tag. GHSA-r47g-fvhr-h676. */
                if (_isClobbered(dirty)) {
                    /* Fail closed on a live clobbered root before throwing.
                       _neutralizeRoot's reads are clobber-safe (cached getters); the
                       form's non-clobbered descendants, e.g. an armed <img>, are scrubbed. */
                    _neutralizeRoot(dirty);
                    throw typeErrorCreate('root node is clobbered and cannot be sanitized in-place');
                }
                /* Sanitize attached shadow roots before the main iterator runs.
                   The iterator does not descend into shadow trees. Same fail-closed
                   barrier as the main walk (campaign-3 F2): a custom-element reaction
                   inside a shadow root could abort this pre-pass before the walk runs,
                   which would otherwise leave the entire live tree unsanitized. */
                try {
                    _sanitizeAttachedShadowRoots(dirty);
                } catch (error) {
                    _neutralizeRoot(dirty);
                    throw error;
                }
            } else if (_isNode(dirty)) {
                /* If dirty is a DOM element, append to an empty document to avoid
                   elements being stripped by the parser */
                body = _initDocument('<!---->');
                importedNode = body.ownerDocument.importNode(dirty, true);
                if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === 'BODY') {
                    /* Node is already a body, use as is */
                    body = importedNode;
                } else if (importedNode.nodeName === 'HTML') {
                    body = importedNode;
                } else {
                    // eslint-disable-next-line unicorn/prefer-dom-node-append
                    body.appendChild(importedNode);
                }
                /* Clonable shadow roots are deep-cloned by importNode(); sanitize
                   them before the main iterator runs, since the iterator does not
                   descend into shadow trees. The walk routes every read through a
                   cached prototype getter so clobbering descendants on a form root
                   cannot hide a shadow host from this pass. */
                _sanitizeAttachedShadowRoots(importedNode);
            } else {
                /* Exit directly if we have nothing to do */
                if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&
                    // eslint-disable-next-line unicorn/prefer-includes
                    dirty.indexOf('<') === -1) {
                    return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty;
                }
                /* Initialize the document to work on */
                body = _initDocument(dirty);
                /* Check we have a DOM node from the data */
                if (!body) {
                    return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';
                }
            }
            /* Remove first element node (ours) if FORCE_BODY is set */
            if (body && FORCE_BODY) {
                _forceRemove(body.firstChild);
            }
            /* Get node iterator */
            const walkRoot = inPlace ? dirty : body;
            /* Now start iterating over the created document.
               The walk runs inside an exception barrier (campaign-3 F2): a re-entrant
               engine/custom-element mutation can detach a node mid-walk so
               `_forceRemove`'s parentless guard throws, aborting the loop. Without the
               barrier the caller's in-place tree would be left half-sanitized with the
               unvisited tail still armed. _createNodeIterator itself is inside the
               barrier too: constructing the iterator dereferences the root's document,
               and any failure there (e.g. an exotic/clobbered root) must still fail
               closed rather than skip the neutralize. On any throw we fail closed -
               strip the in-place root bare - then rethrow so the existing throw
               contract is preserved. (String/DOM-copy paths never return the partial
               body, so the propagating throw is already fail-closed there.) */
            try {
                const nodeIterator = _createNodeIterator(walkRoot);
                while (currentNode = nodeIterator.nextNode()) {
                    /* Sanitize tags and elements */
                    _sanitizeElements(currentNode, walkRoot);
                    /* Check attributes next */
                    _sanitizeAttributes(currentNode);
                    /* Shadow DOM detected, sanitize it.
                       Realm-safe check (GHSA-hpcv-96wg-7vj8): nodeType-based detection
                       instead of instanceof, so foreign-realm <template>.content is
                       walked correctly. */
                    if (_isDocumentFragment(currentNode.content)) {
                        _sanitizeShadowDOM2(currentNode.content);
                    }
                }
            } catch (error) {
                if (inPlace) {
                    _neutralizeRoot(dirty);
                    /* Nodes _forceRemove'd earlier in the aborted walk are already
                       detached from the root, so _neutralizeRoot's subtree pass does not
                       reach them. Defuse them too, mirroring the success-path loop below. */
                    arrayForEach(DOMPurify.removed, entry => {
                        if (entry.element) {
                            _neutralizeSubtree(entry.element);
                        }
                    });
                }
                throw error;
            }
            /* If we sanitized `dirty` in-place, return it. */
            if (inPlace) {
                /* Fail-closed completion of the audit-5 F1 fix: every node removed from
                   the caller's live tree is detached but may still hold a queued
                   resource-event handler that fires in page scope after we return. The
                   move-hoist covers only disallowed-tag KEEP_CONTENT removals; strip the
                   non-allow-listed attributes off every other removed subtree (clobber,
                   mXSS, namespace, comments, KEEP_CONTENT:false, …) so those handlers are
                   cancelled before any event can fire. Runs synchronously, pre-return. */
                arrayForEach(DOMPurify.removed, entry => {
                    if (entry.element) {
                        _neutralizeSubtree(entry.element);
                    }
                });
                if (SAFE_FOR_TEMPLATES) {
                    _scrubTemplateExpressions2(dirty);
                }
                return dirty;
            }
            /* Return sanitized string or DOM */
            if (RETURN_DOM) {
                if (SAFE_FOR_TEMPLATES) {
                    _scrubTemplateExpressions2(body);
                }
                if (RETURN_DOM_FRAGMENT) {
                    returnNode = createDocumentFragment.call(body.ownerDocument);
                    while (body.firstChild) {
                        // eslint-disable-next-line unicorn/prefer-dom-node-append
                        returnNode.appendChild(body.firstChild);
                    }
                } else {
                    returnNode = body;
                }
                if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {
                    /*
                      AdoptNode() is not used because internal state is not reset
                      (e.g. the past names map of a HTMLFormElement), this is safe
                      in theory but we would rather not risk another attack vector.
                      The state that is cloned by importNode() is explicitly defined
                      by the specs.
                    */
                    returnNode = importNode.call(originalDocument, returnNode, true);
                }
                return returnNode;
            }
            let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
            /* Serialize doctype if allowed */
            if (WHOLE_DOCUMENT && ALLOWED_TAGS['!doctype'] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
                serializedHTML = '<!DOCTYPE ' + body.ownerDocument.doctype.name + '>\n' + serializedHTML;
            }
            /* Sanitize final string template-safe */
            if (SAFE_FOR_TEMPLATES) {
                serializedHTML = _stripTemplateExpressions(serializedHTML);
            }
            return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML;
        };
        DOMPurify.setConfig = function() {
            let cfg = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
            _parseConfig(cfg);
            SET_CONFIG = true;
            SET_CONFIG_ALLOWED_TAGS = ALLOWED_TAGS;
            SET_CONFIG_ALLOWED_ATTR = ALLOWED_ATTR;
        };
        DOMPurify.clearConfig = function() {
            CONFIG = null;
            SET_CONFIG = false;
            SET_CONFIG_ALLOWED_TAGS = null;
            SET_CONFIG_ALLOWED_ATTR = null;
            // Drop any caller-supplied Trusted Types policy so it cannot poison later
            // `RETURN_TRUSTED_TYPE` output. The internal default policy (cached, and
            // never recreated — Trusted Types throws on duplicate names) is restored by
            // the next `_parseConfig`. See GHSA-vxr8-fq34-vvx9.
            trustedTypesPolicy = defaultTrustedTypesPolicy;
            emptyHTML = '';
        };
        DOMPurify.isValidAttribute = function(tag, attr, value) {
            /* Initialize shared config vars if necessary. */
            if (!CONFIG) {
                _parseConfig({});
            }
            const lcTag = transformCaseFunc(tag);
            const lcName = transformCaseFunc(attr);
            return _isValidAttribute(lcTag, lcName, value);
        };
        DOMPurify.addHook = function(entryPoint, hookFunction) {
            if (typeof hookFunction !== 'function') {
                return;
            }
            /* Reject unknown entry points. Without this, a non-hook key (e.g.
             * '__proto__') indexes off the prototype chain rather than a real
             * hook array, and arrayPush then writes to Object.prototype. Guard
             * with an own-property check against the known hook names. */
            if (!objectHasOwnProperty(hooks, entryPoint)) {
                return;
            }
            arrayPush(hooks[entryPoint], hookFunction);
        };
        DOMPurify.removeHook = function(entryPoint, hookFunction) {
            if (!objectHasOwnProperty(hooks, entryPoint)) {
                return undefined;
            }
            if (hookFunction !== undefined) {
                const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);
                return index === -1 ? undefined : arraySplice(hooks[entryPoint], index, 1)[0];
            }
            return arrayPop(hooks[entryPoint]);
        };
        DOMPurify.removeHooks = function(entryPoint) {
            if (!objectHasOwnProperty(hooks, entryPoint)) {
                return;
            }
            hooks[entryPoint] = [];
        };
        DOMPurify.removeAllHooks = function() {
            hooks = _createHooksMap();
        };
        return DOMPurify;
    }
    var purify = createDOMPurify();

    return purify;

}));
//# sourceMappingURL=purify.js.map
"use strict";

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

function _possibleConstructorReturn(self, call) {
    if (call && (_typeof(call) === "object" || typeof call === "function")) {
        return call;
    }
    return _assertThisInitialized(self);
}

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

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

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

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

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

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

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

/*
 *
 * More info at [www.dropzonejs.com](http://www.dropzonejs.com)
 *
 * Copyright (c) 2012, Matias Meno
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */
// The Emitter class provides the ability to call `.on()` on Dropzone to listen
// to events.
// It is strongly based on component's emitter class, and I removed the
// functionality because of the dependency hell with different frameworks.
var Emitter =
    /*#__PURE__*/
    function() {
        function Emitter() {
            _classCallCheck(this, Emitter);
        }

        _createClass(Emitter, [{
            key: "on",
            // Add an event listener for given event
            value: function on(event, fn) {
                this._callbacks = this._callbacks || {}; // Create namespace for this event

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

                this._callbacks[event].push(fn);

                return this;
            }
        }, {
            key: "emit",
            value: function emit(event) {
                this._callbacks = this._callbacks || {};
                var callbacks = this._callbacks[event];

                if (callbacks) {
                    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
                        args[_key - 1] = arguments[_key];
                    }

                    var _iteratorNormalCompletion = true;
                    var _didIteratorError = false;
                    var _iteratorError = undefined;

                    try {
                        for (var _iterator = callbacks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
                            var callback = _step.value;
                            callback.apply(this, args);
                        }
                    } catch (err) {
                        _didIteratorError = true;
                        _iteratorError = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion && _iterator["return"] != null) {
                                _iterator["return"]();
                            }
                        } finally {
                            if (_didIteratorError) {
                                throw _iteratorError;
                            }
                        }
                    }
                }

                return this;
            } // Remove event listener for given event. If fn is not provided, all event
            // listeners for that event will be removed. If neither is provided, all
            // event listeners will be removed.

        }, {
            key: "off",
            value: function off(event, fn) {
                if (!this._callbacks || arguments.length === 0) {
                    this._callbacks = {};
                    return this;
                } // specific event


                var callbacks = this._callbacks[event];

                if (!callbacks) {
                    return this;
                } // remove all handlers


                if (arguments.length === 1) {
                    delete this._callbacks[event];
                    return this;
                } // remove specific handler


                for (var i = 0; i < callbacks.length; i++) {
                    var callback = callbacks[i];

                    if (callback === fn) {
                        callbacks.splice(i, 1);
                        break;
                    }
                }

                return this;
            }
        }]);

        return Emitter;
    }();

var Dropzone =
    /*#__PURE__*/
    function(_Emitter) {
        _inherits(Dropzone, _Emitter);

        _createClass(Dropzone, null, [{
            key: "initClass",
            value: function initClass() {
                // Exposing the emitter class, mainly for tests
                this.prototype.Emitter = Emitter;
                /*
                 This is a list of all available events you can register on a dropzone object.
                  You can register an event handler like this:
                  dropzone.on("dragEnter", function() { });
                  */

                this.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "addedfiles", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached", "queuecomplete"];
                this.prototype.defaultOptions = {
                    /**
                     * Has to be specified on elements other than form (or when the form
                     * doesn't have an `action` attribute). You can also
                     * provide a function that will be called with `files` and
                     * must return the url (since `v3.12.0`)
                     */
                    url: null,

                    /**
                     * Can be changed to `"put"` if necessary. You can also provide a function
                     * that will be called with `files` and must return the method (since `v3.12.0`).
                     */
                    method: "post",

                    /**
                     * Will be set on the XHRequest.
                     */
                    withCredentials: false,

                    /**
                     * The timeout for the XHR requests in milliseconds (since `v4.4.0`).
                     */
                    timeout: 30000,

                    /**
                     * How many file uploads to process in parallel (See the
                     * Enqueuing file uploads documentation section for more info)
                     */
                    parallelUploads: 2,

                    /**
                     * Whether to send multiple files in one request. If
                     * this it set to true, then the fallback file input element will
                     * have the `multiple` attribute as well. This option will
                     * also trigger additional events (like `processingmultiple`). See the events
                     * documentation section for more information.
                     */
                    uploadMultiple: false,

                    /**
                     * Whether you want files to be uploaded in chunks to your server. This can't be
                     * used in combination with `uploadMultiple`.
                     *
                     * See [chunksUploaded](#config-chunksUploaded) for the callback to finalise an upload.
                     */
                    chunking: false,

                    /**
                     * If `chunking` is enabled, this defines whether **every** file should be chunked,
                     * even if the file size is below chunkSize. This means, that the additional chunk
                     * form data will be submitted and the `chunksUploaded` callback will be invoked.
                     */
                    forceChunking: false,

                    /**
                     * If `chunking` is `true`, then this defines the chunk size in bytes.
                     */
                    chunkSize: 2000000,

                    /**
                     * If `true`, the individual chunks of a file are being uploaded simultaneously.
                     */
                    parallelChunkUploads: false,

                    /**
                     * Whether a chunk should be retried if it fails.
                     */
                    retryChunks: false,

                    /**
                     * If `retryChunks` is true, how many times should it be retried.
                     */
                    retryChunksLimit: 3,

                    /**
                     * If not `null` defines how many files this Dropzone handles. If it exceeds,
                     * the event `maxfilesexceeded` will be called. The dropzone element gets the
                     * class `dz-max-files-reached` accordingly so you can provide visual feedback.
                     */
                    maxFilesize: 256,

                    /**
                     * The name of the file param that gets transferred.
                     * **NOTE**: If you have the option  `uploadMultiple` set to `true`, then
                     * Dropzone will append `[]` to the name.
                     */
                    paramName: "file",

                    /**
                     * Whether thumbnails for images should be generated
                     */
                    createImageThumbnails: true,

                    /**
                     * In MB. When the filename exceeds this limit, the thumbnail will not be generated.
                     */
                    maxThumbnailFilesize: 10,

                    /**
                     * If `null`, the ratio of the image will be used to calculate it.
                     */
                    thumbnailWidth: 120,

                    /**
                     * The same as `thumbnailWidth`. If both are null, images will not be resized.
                     */
                    thumbnailHeight: 120,

                    /**
                     * How the images should be scaled down in case both, `thumbnailWidth` and `thumbnailHeight` are provided.
                     * Can be either `contain` or `crop`.
                     */
                    thumbnailMethod: 'crop',

                    /**
                     * If set, images will be resized to these dimensions before being **uploaded**.
                     * If only one, `resizeWidth` **or** `resizeHeight` is provided, the original aspect
                     * ratio of the file will be preserved.
                     *
                     * The `options.transformFile` function uses these options, so if the `transformFile` function
                     * is overridden, these options don't do anything.
                     */
                    resizeWidth: null,

                    /**
                     * See `resizeWidth`.
                     */
                    resizeHeight: null,

                    /**
                     * The mime type of the resized image (before it gets uploaded to the server).
                     * If `null` the original mime type will be used. To force jpeg, for example, use `image/jpeg`.
                     * See `resizeWidth` for more information.
                     */
                    resizeMimeType: null,

                    /**
                     * The quality of the resized images. See `resizeWidth`.
                     */
                    resizeQuality: 0.8,

                    /**
                     * How the images should be scaled down in case both, `resizeWidth` and `resizeHeight` are provided.
                     * Can be either `contain` or `crop`.
                     */
                    resizeMethod: 'contain',

                    /**
                     * The base that is used to calculate the filesize. You can change this to
                     * 1024 if you would rather display kibibytes, mebibytes, etc...
                     * 1024 is technically incorrect, because `1024 bytes` are `1 kibibyte` not `1 kilobyte`.
                     * You can change this to `1024` if you don't care about validity.
                     */
                    filesizeBase: 1000,

                    /**
                     * Can be used to limit the maximum number of files that will be handled by this Dropzone
                     */
                    maxFiles: null,

                    /**
                     * An optional object to send additional headers to the server. Eg:
                     * `{ "My-Awesome-Header": "header value" }`
                     */
                    headers: null,

                    /**
                     * If `true`, the dropzone element itself will be clickable, if `false`
                     * nothing will be clickable.
                     *
                     * You can also pass an HTML element, a CSS selector (for multiple elements)
                     * or an array of those. In that case, all of those elements will trigger an
                     * upload when clicked.
                     */
                    clickable: true,

                    /**
                     * Whether hidden files in directories should be ignored.
                     */
                    ignoreHiddenFiles: true,

                    /**
                     * The default implementation of `accept` checks the file's mime type or
                     * extension against this list. This is a comma separated list of mime
                     * types or file extensions.
                     *
                     * Eg.: `image/*,application/pdf,.psd`
                     *
                     * If the Dropzone is `clickable` this option will also be used as
                     * [`accept`](https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept)
                     * parameter on the hidden file input as well.
                     */
                    acceptedFiles: null,

                    /**
                     * **Deprecated!**
                     * Use acceptedFiles instead.
                     */
                    acceptedMimeTypes: null,

                    /**
                     * If false, files will be added to the queue but the queue will not be
                     * processed automatically.
                     * This can be useful if you need some additional user input before sending
                     * files (or if you want want all files sent at once).
                     * If you're ready to send the file simply call `myDropzone.processQueue()`.
                     *
                     * See the [enqueuing file uploads](#enqueuing-file-uploads) documentation
                     * section for more information.
                     */
                    autoProcessQueue: true,

                    /**
                     * If false, files added to the dropzone will not be queued by default.
                     * You'll have to call `enqueueFile(file)` manually.
                     */
                    autoQueue: true,

                    /**
                     * If `true`, this will add a link to every file preview to remove or cancel (if
                     * already uploading) the file. The `dictCancelUpload`, `dictCancelUploadConfirmation`
                     * and `dictRemoveFile` options are used for the wording.
                     */
                    addRemoveLinks: false,

                    /**
                     * Defines where to display the file previews – if `null` the
                     * Dropzone element itself is used. Can be a plain `HTMLElement` or a CSS
                     * selector. The element should have the `dropzone-previews` class so
                     * the previews are displayed properly.
                     */
                    previewsContainer: null,

                    /**
                     * This is the element the hidden input field (which is used when clicking on the
                     * dropzone to trigger file selection) will be appended to. This might
                     * be important in case you use frameworks to switch the content of your page.
                     *
                     * Can be a selector string, or an element directly.
                     */
                    hiddenInputContainer: "body",

                    /**
                     * If null, no capture type will be specified
                     * If camera, mobile devices will skip the file selection and choose camera
                     * If microphone, mobile devices will skip the file selection and choose the microphone
                     * If camcorder, mobile devices will skip the file selection and choose the camera in video mode
                     * On apple devices multiple must be set to false.  AcceptedFiles may need to
                     * be set to an appropriate mime type (e.g. "image/*", "audio/*", or "video/*").
                     */
                    capture: null,

                    /**
                     * **Deprecated**. Use `renameFile` instead.
                     */
                    renameFilename: null,

                    /**
                     * A function that is invoked before the file is uploaded to the server and renames the file.
                     * This function gets the `File` as argument and can use the `file.name`. The actual name of the
                     * file that gets used during the upload can be accessed through `file.upload.filename`.
                     */
                    renameFile: null,

                    /**
                     * If `true` the fallback will be forced. This is very useful to test your server
                     * implementations first and make sure that everything works as
                     * expected without dropzone if you experience problems, and to test
                     * how your fallbacks will look.
                     */
                    forceFallback: false,

                    /**
                     * The text used before any files are dropped.
                     */
                    dictDefaultMessage: "Drop files here to upload",

                    /**
                     * The text that replaces the default message text it the browser is not supported.
                     */
                    dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.",

                    /**
                     * The text that will be added before the fallback form.
                     * If you provide a  fallback element yourself, or if this option is `null` this will
                     * be ignored.
                     */
                    dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.",

                    /**
                     * If the filesize is too big.
                     * `{{filesize}}` and `{{maxFilesize}}` will be replaced with the respective configuration values.
                     */
                    dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",

                    /**
                     * If the file doesn't match the file type.
                     */
                    dictInvalidFileType: "You can't upload files of this type.",

                    /**
                     * If the server response was invalid.
                     * `{{statusCode}}` will be replaced with the servers status code.
                     */
                    dictResponseError: "Server responded with {{statusCode}} code.",

                    /**
                     * If `addRemoveLinks` is true, the text to be used for the cancel upload link.
                     */
                    dictCancelUpload: "Cancel upload",

                    /**
                     * The text that is displayed if an upload was manually canceled
                     */
                    dictUploadCanceled: "Upload canceled.",

                    /**
                     * If `addRemoveLinks` is true, the text to be used for confirmation when cancelling upload.
                     */
                    dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",

                    /**
                     * If `addRemoveLinks` is true, the text to be used to remove a file.
                     */
                    dictRemoveFile: "Remove file",

                    /**
                     * If this is not null, then the user will be prompted before removing a file.
                     */
                    dictRemoveFileConfirmation: null,

                    /**
                     * Displayed if `maxFiles` is st and exceeded.
                     * The string `{{maxFiles}}` will be replaced by the configuration value.
                     */
                    dictMaxFilesExceeded: "You can not upload any more files.",

                    /**
                     * Allows you to translate the different units. Starting with `tb` for terabytes and going down to
                     * `b` for bytes.
                     */
                    dictFileSizeUnits: {
                        tb: "TB",
                        gb: "GB",
                        mb: "MB",
                        kb: "KB",
                        b: "b"
                    },

                    /**
                     * Called when dropzone initialized
                     * You can add event listeners here
                     */
                    init: function init() {},

                    /**
                     * Can be an **object** of additional parameters to transfer to the server, **or** a `Function`
                     * that gets invoked with the `files`, `xhr` and, if it's a chunked upload, `chunk` arguments. In case
                     * of a function, this needs to return a map.
                     *
                     * The default implementation does nothing for normal uploads, but adds relevant information for
                     * chunked uploads.
                     *
                     * This is the same as adding hidden input fields in the form element.
                     */
                    params: function params(files, xhr, chunk) {
                        if (chunk) {
                            return {
                                dzuuid: chunk.file.upload.uuid,
                                dzchunkindex: chunk.index,
                                dztotalfilesize: chunk.file.size,
                                dzchunksize: this.options.chunkSize,
                                dztotalchunkcount: chunk.file.upload.totalChunkCount,
                                dzchunkbyteoffset: chunk.index * this.options.chunkSize
                            };
                        }
                    },

                    /**
                     * A function that gets a [file](https://developer.mozilla.org/en-US/docs/DOM/File)
                     * and a `done` function as parameters.
                     *
                     * If the done function is invoked without arguments, the file is "accepted" and will
                     * be processed. If you pass an error message, the file is rejected, and the error
                     * message will be displayed.
                     * This function will not be called if the file is too big or doesn't match the mime types.
                     */
                    accept: function accept(file, done) {
                        return done();
                    },

                    /**
                     * The callback that will be invoked when all chunks have been uploaded for a file.
                     * It gets the file for which the chunks have been uploaded as the first parameter,
                     * and the `done` function as second. `done()` needs to be invoked when everything
                     * needed to finish the upload process is done.
                     */
                    chunksUploaded: function chunksUploaded(file, done) {
                        done();
                    },

                    /**
                     * Gets called when the browser is not supported.
                     * The default implementation shows the fallback input field and adds
                     * a text.
                     */
                    fallback: function fallback() {
                        // This code should pass in IE7... :(
                        var messageElement;
                        this.element.className = "".concat(this.element.className, " dz-browser-not-supported");
                        var _iteratorNormalCompletion2 = true;
                        var _didIteratorError2 = false;
                        var _iteratorError2 = undefined;

                        try {
                            for (var _iterator2 = this.element.getElementsByTagName("div")[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
                                var child = _step2.value;

                                if (/(^| )dz-message($| )/.test(child.className)) {
                                    messageElement = child;
                                    child.className = "dz-message"; // Removes the 'dz-default' class

                                    break;
                                }
                            }
                        } catch (err) {
                            _didIteratorError2 = true;
                            _iteratorError2 = err;
                        } finally {
                            try {
                                if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
                                    _iterator2["return"]();
                                }
                            } finally {
                                if (_didIteratorError2) {
                                    throw _iteratorError2;
                                }
                            }
                        }

                        if (!messageElement) {
                            messageElement = Dropzone.createElement("<div class=\"dz-message\"><span></span></div>");
                            this.element.appendChild(messageElement);
                        }

                        var span = messageElement.getElementsByTagName("span")[0];

                        if (span) {
                            if (span.textContent != null) {
                                span.textContent = this.options.dictFallbackMessage;
                            } else if (span.innerText != null) {
                                span.innerText = this.options.dictFallbackMessage;
                            }
                        }

                        return this.element.appendChild(this.getFallbackForm());
                    },

                    /**
                     * Gets called to calculate the thumbnail dimensions.
                     *
                     * It gets `file`, `width` and `height` (both may be `null`) as parameters and must return an object containing:
                     *
                     *  - `srcWidth` & `srcHeight` (required)
                     *  - `trgWidth` & `trgHeight` (required)
                     *  - `srcX` & `srcY` (optional, default `0`)
                     *  - `trgX` & `trgY` (optional, default `0`)
                     *
                     * Those values are going to be used by `ctx.drawImage()`.
                     */
                    resize: function resize(file, width, height, resizeMethod) {
                        var info = {
                            srcX: 0,
                            srcY: 0,
                            srcWidth: file.width,
                            srcHeight: file.height
                        };
                        var srcRatio = file.width / file.height; // Automatically calculate dimensions if not specified

                        if (width == null && height == null) {
                            width = info.srcWidth;
                            height = info.srcHeight;
                        } else if (width == null) {
                            width = height * srcRatio;
                        } else if (height == null) {
                            height = width / srcRatio;
                        } // Make sure images aren't upscaled


                        width = Math.min(width, info.srcWidth);
                        height = Math.min(height, info.srcHeight);
                        var trgRatio = width / height;

                        if (info.srcWidth > width || info.srcHeight > height) {
                            // Image is bigger and needs rescaling
                            if (resizeMethod === 'crop') {
                                if (srcRatio > trgRatio) {
                                    info.srcHeight = file.height;
                                    info.srcWidth = info.srcHeight * trgRatio;
                                } else {
                                    info.srcWidth = file.width;
                                    info.srcHeight = info.srcWidth / trgRatio;
                                }
                            } else if (resizeMethod === 'contain') {
                                // Method 'contain'
                                if (srcRatio > trgRatio) {
                                    height = width / srcRatio;
                                } else {
                                    width = height * srcRatio;
                                }
                            } else {
                                throw new Error("Unknown resizeMethod '".concat(resizeMethod, "'"));
                            }
                        }

                        info.srcX = (file.width - info.srcWidth) / 2;
                        info.srcY = (file.height - info.srcHeight) / 2;
                        info.trgWidth = width;
                        info.trgHeight = height;
                        return info;
                    },

                    /**
                     * Can be used to transform the file (for example, resize an image if necessary).
                     *
                     * The default implementation uses `resizeWidth` and `resizeHeight` (if provided) and resizes
                     * images according to those dimensions.
                     *
                     * Gets the `file` as the first parameter, and a `done()` function as the second, that needs
                     * to be invoked with the file when the transformation is done.
                     */
                    transformFile: function transformFile(file, done) {
                        if ((this.options.resizeWidth || this.options.resizeHeight) && file.type.match(/image.*/)) {
                            return this.resizeImage(file, this.options.resizeWidth, this.options.resizeHeight, this.options.resizeMethod, done);
                        } else {
                            return done(file);
                        }
                    },

                    /**
                     * A string that contains the template used for each dropped
                     * file. Change it to fulfill your needs but make sure to properly
                     * provide all elements.
                     *
                     * If you want to use an actual HTML element instead of providing a String
                     * as a config option, you could create a div with the id `tpl`,
                     * put the template inside it and provide the element like this:
                     *
                     *     document
                     *       .querySelector('#tpl')
                     *       .innerHTML
                     *
                     */
                    previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n  <div class=\"dz-image\"><img data-dz-thumbnail /></div>\n  <div class=\"dz-details\">\n    <div class=\"dz-size\"><span data-dz-size></span></div>\n    <div class=\"dz-filename\"><span data-dz-name></span></div>\n  </div>\n  <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n  <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n  <div class=\"dz-success-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n      <title>Check</title>\n      <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n        <path d=\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\" stroke-opacity=\"0.198794158\" stroke=\"#747474\" fill-opacity=\"0.816519475\" fill=\"#FFFFFF\"></path>\n      </g>\n    </svg>\n  </div>\n  <div class=\"dz-error-mark\">\n    <svg width=\"54px\" height=\"54px\" viewBox=\"0 0 54 54\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n      <title>Error</title>\n      <g stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n        <g stroke=\"#747474\" stroke-opacity=\"0.198794158\" fill=\"#FFFFFF\" fill-opacity=\"0.816519475\">\n          <path d=\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\"></path>\n        </g>\n      </g>\n    </svg>\n  </div>\n</div>",
                    // END OPTIONS
                    // (Required by the dropzone documentation parser)

                    /*
                     Those functions register themselves to the events on init and handle all
                     the user interface specific stuff. Overwriting them won't break the upload
                     but can break the way it's displayed.
                     You can overwrite them if you don't like the default behavior. If you just
                     want to add an additional event handler, register it on the dropzone object
                     and don't overwrite those options.
                     */
                    // Those are self explanatory and simply concern the DragnDrop.
                    drop: function drop(e) {
                        return this.element.classList.remove("dz-drag-hover");
                    },
                    dragstart: function dragstart(e) {},
                    dragend: function dragend(e) {
                        return this.element.classList.remove("dz-drag-hover");
                    },
                    dragenter: function dragenter(e) {
                        return this.element.classList.add("dz-drag-hover");
                    },
                    dragover: function dragover(e) {
                        return this.element.classList.add("dz-drag-hover");
                    },
                    dragleave: function dragleave(e) {
                        return this.element.classList.remove("dz-drag-hover");
                    },
                    paste: function paste(e) {},
                    // Called whenever there are no files left in the dropzone anymore, and the
                    // dropzone should be displayed as if in the initial state.
                    reset: function reset() {
                        return this.element.classList.remove("dz-started");
                    },
                    // Called when a file is added to the queue
                    // Receives `file`
                    addedfile: function addedfile(file) {
                        var _this2 = this;

                        if (this.element === this.previewsContainer) {
                            this.element.classList.add("dz-started");
                        }

                        if (this.previewsContainer) {
                            file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());
                            file.previewTemplate = file.previewElement; // Backwards compatibility

                            this.previewsContainer.appendChild(file.previewElement);
                            var _iteratorNormalCompletion3 = true;
                            var _didIteratorError3 = false;
                            var _iteratorError3 = undefined;

                            try {
                                for (var _iterator3 = file.previewElement.querySelectorAll("[data-dz-name]")[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
                                    var node = _step3.value;
                                    node.textContent = file.name;
                                }
                            } catch (err) {
                                _didIteratorError3 = true;
                                _iteratorError3 = err;
                            } finally {
                                try {
                                    if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
                                        _iterator3["return"]();
                                    }
                                } finally {
                                    if (_didIteratorError3) {
                                        throw _iteratorError3;
                                    }
                                }
                            }

                            var _iteratorNormalCompletion4 = true;
                            var _didIteratorError4 = false;
                            var _iteratorError4 = undefined;

                            try {
                                for (var _iterator4 = file.previewElement.querySelectorAll("[data-dz-size]")[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
                                    node = _step4.value;
                                    node.innerHTML = this.filesize(file.size);
                                }
                            } catch (err) {
                                _didIteratorError4 = true;
                                _iteratorError4 = err;
                            } finally {
                                try {
                                    if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) {
                                        _iterator4["return"]();
                                    }
                                } finally {
                                    if (_didIteratorError4) {
                                        throw _iteratorError4;
                                    }
                                }
                            }

                            if (this.options.addRemoveLinks) {
                                file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>".concat(this.options.dictRemoveFile, "</a>"));
                                file.previewElement.appendChild(file._removeLink);
                            }

                            var removeFileEvent = function removeFileEvent(e) {
                                e.preventDefault();
                                e.stopPropagation();

                                if (file.status === Dropzone.UPLOADING) {
                                    return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation, function() {
                                        return _this2.removeFile(file);
                                    });
                                } else {
                                    if (_this2.options.dictRemoveFileConfirmation) {
                                        return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation, function() {
                                            return _this2.removeFile(file);
                                        });
                                    } else {
                                        return _this2.removeFile(file);
                                    }
                                }
                            };

                            var _iteratorNormalCompletion5 = true;
                            var _didIteratorError5 = false;
                            var _iteratorError5 = undefined;

                            try {
                                for (var _iterator5 = file.previewElement.querySelectorAll("[data-dz-remove]")[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
                                    var removeLink = _step5.value;
                                    removeLink.addEventListener("click", removeFileEvent);
                                }
                            } catch (err) {
                                _didIteratorError5 = true;
                                _iteratorError5 = err;
                            } finally {
                                try {
                                    if (!_iteratorNormalCompletion5 && _iterator5["return"] != null) {
                                        _iterator5["return"]();
                                    }
                                } finally {
                                    if (_didIteratorError5) {
                                        throw _iteratorError5;
                                    }
                                }
                            }
                        }
                    },
                    // Called whenever a file is removed.
                    removedfile: function removedfile(file) {
                        if (file.previewElement != null && file.previewElement.parentNode != null) {
                            file.previewElement.parentNode.removeChild(file.previewElement);
                        }

                        return this._updateMaxFilesReachedClass();
                    },
                    // Called when a thumbnail has been generated
                    // Receives `file` and `dataUrl`
                    thumbnail: function thumbnail(file, dataUrl) {
                        if (file.previewElement) {
                            file.previewElement.classList.remove("dz-file-preview");
                            var _iteratorNormalCompletion6 = true;
                            var _didIteratorError6 = false;
                            var _iteratorError6 = undefined;

                            try {
                                for (var _iterator6 = file.previewElement.querySelectorAll("[data-dz-thumbnail]")[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
                                    var thumbnailElement = _step6.value;
                                    thumbnailElement.alt = file.name;
                                    thumbnailElement.src = dataUrl;
                                }
                            } catch (err) {
                                _didIteratorError6 = true;
                                _iteratorError6 = err;
                            } finally {
                                try {
                                    if (!_iteratorNormalCompletion6 && _iterator6["return"] != null) {
                                        _iterator6["return"]();
                                    }
                                } finally {
                                    if (_didIteratorError6) {
                                        throw _iteratorError6;
                                    }
                                }
                            }

                            return setTimeout(function() {
                                return file.previewElement.classList.add("dz-image-preview");
                            }, 1);
                        }
                    },
                    // Called whenever an error occurs
                    // Receives `file` and `message`
                    error: function error(file, message) {
                        if (file.previewElement) {
                            file.previewElement.classList.add("dz-error");

                            if (typeof message !== "String" && message.error) {
                                message = message.error;
                            }

                            var _iteratorNormalCompletion7 = true;
                            var _didIteratorError7 = false;
                            var _iteratorError7 = undefined;

                            try {
                                for (var _iterator7 = file.previewElement.querySelectorAll("[data-dz-errormessage]")[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
                                    var node = _step7.value;
                                    node.textContent = message;
                                }
                            } catch (err) {
                                _didIteratorError7 = true;
                                _iteratorError7 = err;
                            } finally {
                                try {
                                    if (!_iteratorNormalCompletion7 && _iterator7["return"] != null) {
                                        _iterator7["return"]();
                                    }
                                } finally {
                                    if (_didIteratorError7) {
                                        throw _iteratorError7;
                                    }
                                }
                            }
                        }
                    },
                    errormultiple: function errormultiple() {},
                    // Called when a file gets processed. Since there is a cue, not all added
                    // files are processed immediately.
                    // Receives `file`
                    processing: function processing(file) {
                        if (file.previewElement) {
                            file.previewElement.classList.add("dz-processing");

                            if (file._removeLink) {
                                return file._removeLink.innerHTML = this.options.dictCancelUpload;
                            }
                        }
                    },
                    processingmultiple: function processingmultiple() {},
                    // Called whenever the upload progress gets updated.
                    // Receives `file`, `progress` (percentage 0-100) and `bytesSent`.
                    // To get the total number of bytes of the file, use `file.size`
                    uploadprogress: function uploadprogress(file, progress, bytesSent) {
                        if (file.previewElement) {
                            var _iteratorNormalCompletion8 = true;
                            var _didIteratorError8 = false;
                            var _iteratorError8 = undefined;

                            try {
                                for (var _iterator8 = file.previewElement.querySelectorAll("[data-dz-uploadprogress]")[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {
                                    var node = _step8.value;
                                    node.nodeName === 'PROGRESS' ? node.value = progress : node.style.width = "".concat(progress, "%");
                                }
                            } catch (err) {
                                _didIteratorError8 = true;
                                _iteratorError8 = err;
                            } finally {
                                try {
                                    if (!_iteratorNormalCompletion8 && _iterator8["return"] != null) {
                                        _iterator8["return"]();
                                    }
                                } finally {
                                    if (_didIteratorError8) {
                                        throw _iteratorError8;
                                    }
                                }
                            }
                        }
                    },
                    // Called whenever the total upload progress gets updated.
                    // Called with totalUploadProgress (0-100), totalBytes and totalBytesSent
                    totaluploadprogress: function totaluploadprogress() {},
                    // Called just before the file is sent. Gets the `xhr` object as second
                    // parameter, so you can modify it (for example to add a CSRF token) and a
                    // `formData` object to add additional information.
                    sending: function sending() {},
                    sendingmultiple: function sendingmultiple() {},
                    // When the complete upload is finished and successful
                    // Receives `file`
                    success: function success(file) {
                        if (file.previewElement) {
                            return file.previewElement.classList.add("dz-success");
                        }
                    },
                    successmultiple: function successmultiple() {},
                    // When the upload is canceled.
                    canceled: function canceled(file) {
                        return this.emit("error", file, this.options.dictUploadCanceled);
                    },
                    canceledmultiple: function canceledmultiple() {},
                    // When the upload is finished, either with success or an error.
                    // Receives `file`
                    complete: function complete(file) {
                        if (file._removeLink) {
                            file._removeLink.innerHTML = this.options.dictRemoveFile;
                        }

                        if (file.previewElement) {
                            return file.previewElement.classList.add("dz-complete");
                        }
                    },
                    completemultiple: function completemultiple() {},
                    maxfilesexceeded: function maxfilesexceeded() {},
                    maxfilesreached: function maxfilesreached() {},
                    queuecomplete: function queuecomplete() {},
                    addedfiles: function addedfiles() {}
                };
                this.prototype._thumbnailQueue = [];
                this.prototype._processingThumbnail = false;
            } // global utility

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

                for (var _i = 0, _objects = objects; _i < _objects.length; _i++) {
                    var object = _objects[_i];

                    for (var key in object) {
                        var val = object[key];
                        target[key] = val;
                    }
                }

                return target;
            }
        }]);

        function Dropzone(el, options) {
            var _this;

            _classCallCheck(this, Dropzone);

            _this = _possibleConstructorReturn(this, _getPrototypeOf(Dropzone).call(this));
            var fallback, left;
            _this.element = el; // For backwards compatibility since the version was in the prototype previously

            _this.version = Dropzone.version;
            _this.defaultOptions.previewTemplate = _this.defaultOptions.previewTemplate.replace(/\n*/g, "");
            _this.clickableElements = [];
            _this.listeners = [];
            _this.files = []; // All files

            if (typeof _this.element === "string") {
                _this.element = document.querySelector(_this.element);
            } // Not checking if instance of HTMLElement or Element since IE9 is extremely weird.


            if (!_this.element || _this.element.nodeType == null) {
                throw new Error("Invalid dropzone element.");
            }

            if (_this.element.dropzone) {
                throw new Error("Dropzone already attached.");
            } // Now add this dropzone to the instances.


            Dropzone.instances.push(_assertThisInitialized(_this)); // Put the dropzone inside the element itself.

            _this.element.dropzone = _assertThisInitialized(_this);
            var elementOptions = (left = Dropzone.optionsForElement(_this.element)) != null ? left : {};
            _this.options = Dropzone.extend({}, _this.defaultOptions, elementOptions, options != null ? options : {}); // If the browser failed, just call the fallback and leave

            if (_this.options.forceFallback || !Dropzone.isBrowserSupported()) {
                return _possibleConstructorReturn(_this, _this.options.fallback.call(_assertThisInitialized(_this)));
            } // @options.url = @element.getAttribute "action" unless @options.url?


            if (_this.options.url == null) {
                _this.options.url = _this.element.getAttribute("action");
            }

            if (!_this.options.url) {
                throw new Error("No URL provided.");
            }

            if (_this.options.acceptedFiles && _this.options.acceptedMimeTypes) {
                throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");
            }

            if (_this.options.uploadMultiple && _this.options.chunking) {
                throw new Error('You cannot set both: uploadMultiple and chunking.');
            } // Backwards compatibility


            if (_this.options.acceptedMimeTypes) {
                _this.options.acceptedFiles = _this.options.acceptedMimeTypes;
                delete _this.options.acceptedMimeTypes;
            } // Backwards compatibility


            if (_this.options.renameFilename != null) {
                _this.options.renameFile = function(file) {
                    return _this.options.renameFilename.call(_assertThisInitialized(_this), file.name, file);
                };
            }

            _this.options.method = _this.options.method.toUpperCase();

            if ((fallback = _this.getExistingFallback()) && fallback.parentNode) {
                // Remove the fallback
                fallback.parentNode.removeChild(fallback);
            } // Display previews in the previewsContainer element or the Dropzone element unless explicitly set to false


            if (_this.options.previewsContainer !== false) {
                if (_this.options.previewsContainer) {
                    _this.previewsContainer = Dropzone.getElement(_this.options.previewsContainer, "previewsContainer");
                } else {
                    _this.previewsContainer = _this.element;
                }
            }

            if (_this.options.clickable) {
                if (_this.options.clickable === true) {
                    _this.clickableElements = [_this.element];
                } else {
                    _this.clickableElements = Dropzone.getElements(_this.options.clickable, "clickable");
                }
            }

            _this.init();

            return _this;
        } // Returns all files that have been accepted


        _createClass(Dropzone, [{
            key: "getAcceptedFiles",
            value: function getAcceptedFiles() {
                return this.files.filter(function(file) {
                    return file.accepted;
                }).map(function(file) {
                    return file;
                });
            } // Returns all files that have been rejected
            // Not sure when that's going to be useful, but added for completeness.

        }, {
            key: "getRejectedFiles",
            value: function getRejectedFiles() {
                return this.files.filter(function(file) {
                    return !file.accepted;
                }).map(function(file) {
                    return file;
                });
            }
        }, {
            key: "getFilesWithStatus",
            value: function getFilesWithStatus(status) {
                return this.files.filter(function(file) {
                    return file.status === status;
                }).map(function(file) {
                    return file;
                });
            } // Returns all files that are in the queue

        }, {
            key: "getQueuedFiles",
            value: function getQueuedFiles() {
                return this.getFilesWithStatus(Dropzone.QUEUED);
            }
        }, {
            key: "getUploadingFiles",
            value: function getUploadingFiles() {
                return this.getFilesWithStatus(Dropzone.UPLOADING);
            }
        }, {
            key: "getAddedFiles",
            value: function getAddedFiles() {
                return this.getFilesWithStatus(Dropzone.ADDED);
            } // Files that are either queued or uploading

        }, {
            key: "getActiveFiles",
            value: function getActiveFiles() {
                return this.files.filter(function(file) {
                    return file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED;
                }).map(function(file) {
                    return file;
                });
            } // The function that gets called when Dropzone is initialized. You
            // can (and should) setup event listeners inside this function.

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

                // In case it isn't set already
                if (this.element.tagName === "form") {
                    this.element.setAttribute("enctype", "multipart/form-data");
                }

                if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
                    this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><button class=\"dz-button\" type=\"button\">".concat(this.options.dictDefaultMessage, "</button></div>")));
                }

                if (this.clickableElements.length) {
                    var setupHiddenFileInput = function setupHiddenFileInput() {
                        if (_this3.hiddenFileInput) {
                            _this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);
                        }

                        _this3.hiddenFileInput = document.createElement("input");

                        _this3.hiddenFileInput.setAttribute("type", "file");

                        if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) {
                            _this3.hiddenFileInput.setAttribute("multiple", "multiple");
                        }

                        _this3.hiddenFileInput.className = "dz-hidden-input";

                        if (_this3.options.acceptedFiles !== null) {
                            _this3.hiddenFileInput.setAttribute("accept", _this3.options.acceptedFiles);
                        }

                        if (_this3.options.capture !== null) {
                            _this3.hiddenFileInput.setAttribute("capture", _this3.options.capture);
                        } // Not setting `display="none"` because some browsers don't accept clicks
                        // on elements that aren't displayed.


                        _this3.hiddenFileInput.style.visibility = "hidden";
                        _this3.hiddenFileInput.style.position = "absolute";
                        _this3.hiddenFileInput.style.top = "0";
                        _this3.hiddenFileInput.style.left = "0";
                        _this3.hiddenFileInput.style.height = "0";
                        _this3.hiddenFileInput.style.width = "0";
                        Dropzone.getElement(_this3.options.hiddenInputContainer, 'hiddenInputContainer').appendChild(_this3.hiddenFileInput);
                        return _this3.hiddenFileInput.addEventListener("change", function() {
                            var files = _this3.hiddenFileInput.files;

                            if (files.length) {
                                var _iteratorNormalCompletion9 = true;
                                var _didIteratorError9 = false;
                                var _iteratorError9 = undefined;

                                try {
                                    for (var _iterator9 = files[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {
                                        var file = _step9.value;

                                        _this3.addFile(file);
                                    }
                                } catch (err) {
                                    _didIteratorError9 = true;
                                    _iteratorError9 = err;
                                } finally {
                                    try {
                                        if (!_iteratorNormalCompletion9 && _iterator9["return"] != null) {
                                            _iterator9["return"]();
                                        }
                                    } finally {
                                        if (_didIteratorError9) {
                                            throw _iteratorError9;
                                        }
                                    }
                                }
                            }

                            _this3.emit("addedfiles", files);

                            return setupHiddenFileInput();
                        });
                    };

                    setupHiddenFileInput();
                }

                this.URL = window.URL !== null ? window.URL : window.webkitURL; // Setup all event listeners on the Dropzone object itself.
                // They're not in @setupEventListeners() because they shouldn't be removed
                // again when the dropzone gets disabled.

                var _iteratorNormalCompletion10 = true;
                var _didIteratorError10 = false;
                var _iteratorError10 = undefined;

                try {
                    for (var _iterator10 = this.events[Symbol.iterator](), _step10; !(_iteratorNormalCompletion10 = (_step10 = _iterator10.next()).done); _iteratorNormalCompletion10 = true) {
                        var eventName = _step10.value;
                        this.on(eventName, this.options[eventName]);
                    }
                } catch (err) {
                    _didIteratorError10 = true;
                    _iteratorError10 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion10 && _iterator10["return"] != null) {
                            _iterator10["return"]();
                        }
                    } finally {
                        if (_didIteratorError10) {
                            throw _iteratorError10;
                        }
                    }
                }

                this.on("uploadprogress", function() {
                    return _this3.updateTotalUploadProgress();
                });
                this.on("removedfile", function() {
                    return _this3.updateTotalUploadProgress();
                });
                this.on("canceled", function(file) {
                    return _this3.emit("complete", file);
                }); // Emit a `queuecomplete` event if all files finished uploading.

                this.on("complete", function(file) {
                    if (_this3.getAddedFiles().length === 0 && _this3.getUploadingFiles().length === 0 && _this3.getQueuedFiles().length === 0) {
                        // This needs to be deferred so that `queuecomplete` really triggers after `complete`
                        return setTimeout(function() {
                            return _this3.emit("queuecomplete");
                        }, 0);
                    }
                });

                var containsFiles = function containsFiles(e) {
                    return e.dataTransfer.types && e.dataTransfer.types.some(function(type) {
                        return type == "Files";
                    });
                };

                var noPropagation = function noPropagation(e) {
                    // If there are no files, we don't want to stop
                    // propagation so we don't interfere with other
                    // drag and drop behaviour.
                    if (!containsFiles(e)) return;
                    e.stopPropagation();

                    if (e.preventDefault) {
                        return e.preventDefault();
                    } else {
                        return e.returnValue = false;
                    }
                }; // Create the listeners


                this.listeners = [{
                    element: this.element,
                    events: {
                        "dragstart": function dragstart(e) {
                            return _this3.emit("dragstart", e);
                        },
                        "dragenter": function dragenter(e) {
                            noPropagation(e);
                            return _this3.emit("dragenter", e);
                        },
                        "dragover": function dragover(e) {
                            // Makes it possible to drag files from chrome's download bar
                            // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar
                            // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception)
                            var efct;

                            try {
                                efct = e.dataTransfer.effectAllowed;
                            } catch (error) {}

                            e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';
                            noPropagation(e);
                            return _this3.emit("dragover", e);
                        },
                        "dragleave": function dragleave(e) {
                            return _this3.emit("dragleave", e);
                        },
                        "drop": function drop(e) {
                            noPropagation(e);
                            return _this3.drop(e);
                        },
                        "dragend": function dragend(e) {
                            return _this3.emit("dragend", e);
                        }
                    } // This is disabled right now, because the browsers don't implement it properly.
                    // "paste": (e) =>
                    //   noPropagation e
                    //   @paste e

                }];
                this.clickableElements.forEach(function(clickableElement) {
                    return _this3.listeners.push({
                        element: clickableElement,
                        events: {
                            "click": function click(evt) {
                                // Only the actual dropzone or the message element should trigger file selection
                                if (clickableElement !== _this3.element || evt.target === _this3.element || Dropzone.elementInside(evt.target, _this3.element.querySelector(".dz-message"))) {
                                    _this3.hiddenFileInput.click(); // Forward the click

                                }

                                return true;
                            }
                        }
                    });
                });
                this.enable();
                return this.options.init.call(this);
            } // Not fully tested yet

        }, {
            key: "destroy",
            value: function destroy() {
                this.disable();
                this.removeAllFiles(true);

                if (this.hiddenFileInput != null ? this.hiddenFileInput.parentNode : undefined) {
                    this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);
                    this.hiddenFileInput = null;
                }

                delete this.element.dropzone;
                return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);
            }
        }, {
            key: "updateTotalUploadProgress",
            value: function updateTotalUploadProgress() {
                var totalUploadProgress;
                var totalBytesSent = 0;
                var totalBytes = 0;
                var activeFiles = this.getActiveFiles();

                if (activeFiles.length) {
                    var _iteratorNormalCompletion11 = true;
                    var _didIteratorError11 = false;
                    var _iteratorError11 = undefined;

                    try {
                        for (var _iterator11 = this.getActiveFiles()[Symbol.iterator](), _step11; !(_iteratorNormalCompletion11 = (_step11 = _iterator11.next()).done); _iteratorNormalCompletion11 = true) {
                            var file = _step11.value;
                            totalBytesSent += file.upload.bytesSent;
                            totalBytes += file.upload.total;
                        }
                    } catch (err) {
                        _didIteratorError11 = true;
                        _iteratorError11 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion11 && _iterator11["return"] != null) {
                                _iterator11["return"]();
                            }
                        } finally {
                            if (_didIteratorError11) {
                                throw _iteratorError11;
                            }
                        }
                    }

                    totalUploadProgress = 100 * totalBytesSent / totalBytes;
                } else {
                    totalUploadProgress = 100;
                }

                return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent);
            } // @options.paramName can be a function taking one parameter rather than a string.
            // A parameter name for a file is obtained simply by calling this with an index number.

        }, {
            key: "_getParamName",
            value: function _getParamName(n) {
                if (typeof this.options.paramName === "function") {
                    return this.options.paramName(n);
                } else {
                    return "".concat(this.options.paramName).concat(this.options.uploadMultiple ? "[".concat(n, "]") : "");
                }
            } // If @options.renameFile is a function,
            // the function will be used to rename the file.name before appending it to the formData

        }, {
            key: "_renameFile",
            value: function _renameFile(file) {
                if (typeof this.options.renameFile !== "function") {
                    return file.name;
                }

                return this.options.renameFile(file);
            } // Returns a form that can be used as fallback if the browser does not support DragnDrop
            //
            // If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided.
            // This code has to pass in IE7 :(

        }, {
            key: "getFallbackForm",
            value: function getFallbackForm() {
                var existingFallback, form;

                if (existingFallback = this.getExistingFallback()) {
                    return existingFallback;
                }

                var fieldsString = "<div class=\"dz-fallback\">";

                if (this.options.dictFallbackText) {
                    fieldsString += "<p>".concat(this.options.dictFallbackText, "</p>");
                }

                fieldsString += "<input type=\"file\" name=\"".concat(this._getParamName(0), "\" ").concat(this.options.uploadMultiple ? 'multiple="multiple"' : undefined, " /><input type=\"submit\" value=\"Upload!\"></div>");
                var fields = Dropzone.createElement(fieldsString);

                if (this.element.tagName !== "FORM") {
                    form = Dropzone.createElement("<form action=\"".concat(this.options.url, "\" enctype=\"multipart/form-data\" method=\"").concat(this.options.method, "\"></form>"));
                    form.appendChild(fields);
                } else {
                    // Make sure that the enctype and method attributes are set properly
                    this.element.setAttribute("enctype", "multipart/form-data");
                    this.element.setAttribute("method", this.options.method);
                }

                return form != null ? form : fields;
            } // Returns the fallback elements if they exist already
            //
            // This code has to pass in IE7 :(

        }, {
            key: "getExistingFallback",
            value: function getExistingFallback() {
                var getFallback = function getFallback(elements) {
                    var _iteratorNormalCompletion12 = true;
                    var _didIteratorError12 = false;
                    var _iteratorError12 = undefined;

                    try {
                        for (var _iterator12 = elements[Symbol.iterator](), _step12; !(_iteratorNormalCompletion12 = (_step12 = _iterator12.next()).done); _iteratorNormalCompletion12 = true) {
                            var el = _step12.value;

                            if (/(^| )fallback($| )/.test(el.className)) {
                                return el;
                            }
                        }
                    } catch (err) {
                        _didIteratorError12 = true;
                        _iteratorError12 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion12 && _iterator12["return"] != null) {
                                _iterator12["return"]();
                            }
                        } finally {
                            if (_didIteratorError12) {
                                throw _iteratorError12;
                            }
                        }
                    }
                };

                for (var _i2 = 0, _arr = ["div", "form"]; _i2 < _arr.length; _i2++) {
                    var tagName = _arr[_i2];
                    var fallback;

                    if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {
                        return fallback;
                    }
                }
            } // Activates all listeners stored in @listeners

        }, {
            key: "setupEventListeners",
            value: function setupEventListeners() {
                return this.listeners.map(function(elementListeners) {
                    return function() {
                        var result = [];

                        for (var event in elementListeners.events) {
                            var listener = elementListeners.events[event];
                            result.push(elementListeners.element.addEventListener(event, listener, false));
                        }

                        return result;
                    }();
                });
            } // Deactivates all listeners stored in @listeners

        }, {
            key: "removeEventListeners",
            value: function removeEventListeners() {
                return this.listeners.map(function(elementListeners) {
                    return function() {
                        var result = [];

                        for (var event in elementListeners.events) {
                            var listener = elementListeners.events[event];
                            result.push(elementListeners.element.removeEventListener(event, listener, false));
                        }

                        return result;
                    }();
                });
            } // Removes all event listeners and cancels all files in the queue or being processed.

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

                this.clickableElements.forEach(function(element) {
                    return element.classList.remove("dz-clickable");
                });
                this.removeEventListeners();
                this.disabled = true;
                return this.files.map(function(file) {
                    return _this4.cancelUpload(file);
                });
            }
        }, {
            key: "enable",
            value: function enable() {
                delete this.disabled;
                this.clickableElements.forEach(function(element) {
                    return element.classList.add("dz-clickable");
                });
                return this.setupEventListeners();
            } // Returns a nicely formatted filesize

        }, {
            key: "filesize",
            value: function filesize(size) {
                var selectedSize = 0;
                var selectedUnit = "b";

                if (size > 0) {
                    var units = ['tb', 'gb', 'mb', 'kb', 'b'];

                    for (var i = 0; i < units.length; i++) {
                        var unit = units[i];
                        var cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;

                        if (size >= cutoff) {
                            selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);
                            selectedUnit = unit;
                            break;
                        }
                    }

                    selectedSize = Math.round(10 * selectedSize) / 10; // Cutting of digits
                }

                return "<strong>".concat(selectedSize, "</strong> ").concat(this.options.dictFileSizeUnits[selectedUnit]);
            } // Adds or removes the `dz-max-files-reached` class from the form.

        }, {
            key: "_updateMaxFilesReachedClass",
            value: function _updateMaxFilesReachedClass() {
                if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
                    if (this.getAcceptedFiles().length === this.options.maxFiles) {
                        this.emit('maxfilesreached', this.files);
                    }

                    return this.element.classList.add("dz-max-files-reached");
                } else {
                    return this.element.classList.remove("dz-max-files-reached");
                }
            }
        }, {
            key: "drop",
            value: function drop(e) {
                if (!e.dataTransfer) {
                    return;
                }

                this.emit("drop", e); // Convert the FileList to an Array
                // This is necessary for IE11

                var files = [];

                for (var i = 0; i < e.dataTransfer.files.length; i++) {
                    files[i] = e.dataTransfer.files[i];
                } // Even if it's a folder, files.length will contain the folders.


                if (files.length) {
                    var items = e.dataTransfer.items;

                    if (items && items.length && items[0].webkitGetAsEntry != null) {
                        // The browser supports dropping of folders, so handle items instead of files
                        this._addFilesFromItems(items);
                    } else {
                        this.handleFiles(files);
                    }
                }

                this.emit("addedfiles", files);
            }
        }, {
            key: "paste",
            value: function paste(e) {
                if (__guard__(e != null ? e.clipboardData : undefined, function(x) {
                        return x.items;
                    }) == null) {
                    return;
                }

                this.emit("paste", e);
                var items = e.clipboardData.items;

                if (items.length) {
                    return this._addFilesFromItems(items);
                }
            }
        }, {
            key: "handleFiles",
            value: function handleFiles(files) {
                var _iteratorNormalCompletion13 = true;
                var _didIteratorError13 = false;
                var _iteratorError13 = undefined;

                try {
                    for (var _iterator13 = files[Symbol.iterator](), _step13; !(_iteratorNormalCompletion13 = (_step13 = _iterator13.next()).done); _iteratorNormalCompletion13 = true) {
                        var file = _step13.value;
                        this.addFile(file);
                    }
                } catch (err) {
                    _didIteratorError13 = true;
                    _iteratorError13 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion13 && _iterator13["return"] != null) {
                            _iterator13["return"]();
                        }
                    } finally {
                        if (_didIteratorError13) {
                            throw _iteratorError13;
                        }
                    }
                }
            } // When a folder is dropped (or files are pasted), items must be handled
            // instead of files.

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

                return function() {
                    var result = [];
                    var _iteratorNormalCompletion14 = true;
                    var _didIteratorError14 = false;
                    var _iteratorError14 = undefined;

                    try {
                        for (var _iterator14 = items[Symbol.iterator](), _step14; !(_iteratorNormalCompletion14 = (_step14 = _iterator14.next()).done); _iteratorNormalCompletion14 = true) {
                            var item = _step14.value;
                            var entry;

                            if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) {
                                if (entry.isFile) {
                                    result.push(_this5.addFile(item.getAsFile()));
                                } else if (entry.isDirectory) {
                                    // Append all files from that directory to files
                                    result.push(_this5._addFilesFromDirectory(entry, entry.name));
                                } else {
                                    result.push(undefined);
                                }
                            } else if (item.getAsFile != null) {
                                if (item.kind == null || item.kind === "file") {
                                    result.push(_this5.addFile(item.getAsFile()));
                                } else {
                                    result.push(undefined);
                                }
                            } else {
                                result.push(undefined);
                            }
                        }
                    } catch (err) {
                        _didIteratorError14 = true;
                        _iteratorError14 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion14 && _iterator14["return"] != null) {
                                _iterator14["return"]();
                            }
                        } finally {
                            if (_didIteratorError14) {
                                throw _iteratorError14;
                            }
                        }
                    }

                    return result;
                }();
            } // Goes through the directory, and adds each file it finds recursively

        }, {
            key: "_addFilesFromDirectory",
            value: function _addFilesFromDirectory(directory, path) {
                var _this6 = this;

                var dirReader = directory.createReader();

                var errorHandler = function errorHandler(error) {
                    return __guardMethod__(console, 'log', function(o) {
                        return o.log(error);
                    });
                };

                var readEntries = function readEntries() {
                    return dirReader.readEntries(function(entries) {
                        if (entries.length > 0) {
                            var _iteratorNormalCompletion15 = true;
                            var _didIteratorError15 = false;
                            var _iteratorError15 = undefined;

                            try {
                                for (var _iterator15 = entries[Symbol.iterator](), _step15; !(_iteratorNormalCompletion15 = (_step15 = _iterator15.next()).done); _iteratorNormalCompletion15 = true) {
                                    var entry = _step15.value;

                                    if (entry.isFile) {
                                        entry.file(function(file) {
                                            if (_this6.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {
                                                return;
                                            }

                                            file.fullPath = "".concat(path, "/").concat(file.name);
                                            return _this6.addFile(file);
                                        });
                                    } else if (entry.isDirectory) {
                                        _this6._addFilesFromDirectory(entry, "".concat(path, "/").concat(entry.name));
                                    }
                                } // Recursively call readEntries() again, since browser only handle
                                // the first 100 entries.
                                // See: https://developer.mozilla.org/en-US/docs/Web/API/DirectoryReader#readEntries

                            } catch (err) {
                                _didIteratorError15 = true;
                                _iteratorError15 = err;
                            } finally {
                                try {
                                    if (!_iteratorNormalCompletion15 && _iterator15["return"] != null) {
                                        _iterator15["return"]();
                                    }
                                } finally {
                                    if (_didIteratorError15) {
                                        throw _iteratorError15;
                                    }
                                }
                            }

                            readEntries();
                        }

                        return null;
                    }, errorHandler);
                };

                return readEntries();
            } // If `done()` is called without argument the file is accepted
            // If you call it with an error message, the file is rejected
            // (This allows for asynchronous validation)
            //
            // This function checks the filesize, and if the file.type passes the
            // `acceptedFiles` check.

        }, {
            key: "accept",
            value: function accept(file, done) {
                if (this.options.maxFilesize && file.size > this.options.maxFilesize * 1024 * 1024) {
                    done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize));
                } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {
                    done(this.options.dictInvalidFileType);
                } else if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {
                    done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
                    this.emit("maxfilesexceeded", file);
                } else {
                    this.options.accept.call(this, file, done);
                }
            }
        }, {
            key: "addFile",
            value: function addFile(file) {
                var _this7 = this;

                file.upload = {
                    uuid: Dropzone.uuidv4(),
                    progress: 0,
                    // Setting the total upload size to file.size for the beginning
                    // It's actual different than the size to be transmitted.
                    total: file.size,
                    bytesSent: 0,
                    filename: this._renameFile(file) // Not setting chunking information here, because the acutal data — and
                    // thus the chunks — might change if `options.transformFile` is set
                    // and does something to the data.

                };
                this.files.push(file);
                file.status = Dropzone.ADDED;
                this.emit("addedfile", file);

                this._enqueueThumbnail(file);

                this.accept(file, function(error) {
                    if (error) {
                        file.accepted = false;

                        _this7._errorProcessing([file], error); // Will set the file.status

                    } else {
                        file.accepted = true;

                        if (_this7.options.autoQueue) {
                            _this7.enqueueFile(file);
                        } // Will set .accepted = true

                    }

                    _this7._updateMaxFilesReachedClass();
                });
            } // Wrapper for enqueueFile

        }, {
            key: "enqueueFiles",
            value: function enqueueFiles(files) {
                var _iteratorNormalCompletion16 = true;
                var _didIteratorError16 = false;
                var _iteratorError16 = undefined;

                try {
                    for (var _iterator16 = files[Symbol.iterator](), _step16; !(_iteratorNormalCompletion16 = (_step16 = _iterator16.next()).done); _iteratorNormalCompletion16 = true) {
                        var file = _step16.value;
                        this.enqueueFile(file);
                    }
                } catch (err) {
                    _didIteratorError16 = true;
                    _iteratorError16 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion16 && _iterator16["return"] != null) {
                            _iterator16["return"]();
                        }
                    } finally {
                        if (_didIteratorError16) {
                            throw _iteratorError16;
                        }
                    }
                }

                return null;
            }
        }, {
            key: "enqueueFile",
            value: function enqueueFile(file) {
                var _this8 = this;

                if (file.status === Dropzone.ADDED && file.accepted === true) {
                    file.status = Dropzone.QUEUED;

                    if (this.options.autoProcessQueue) {
                        return setTimeout(function() {
                            return _this8.processQueue();
                        }, 0); // Deferring the call
                    }
                } else {
                    throw new Error("This file can't be queued because it has already been processed or was rejected.");
                }
            }
        }, {
            key: "_enqueueThumbnail",
            value: function _enqueueThumbnail(file) {
                var _this9 = this;

                if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {
                    this._thumbnailQueue.push(file);

                    return setTimeout(function() {
                        return _this9._processThumbnailQueue();
                    }, 0); // Deferring the call
                }
            }
        }, {
            key: "_processThumbnailQueue",
            value: function _processThumbnailQueue() {
                var _this10 = this;

                if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
                    return;
                }

                this._processingThumbnail = true;

                var file = this._thumbnailQueue.shift();

                return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, function(dataUrl) {
                    _this10.emit("thumbnail", file, dataUrl);

                    _this10._processingThumbnail = false;
                    return _this10._processThumbnailQueue();
                });
            } // Can be called by the user to remove a file

        }, {
            key: "removeFile",
            value: function removeFile(file) {
                if (file.status === Dropzone.UPLOADING) {
                    this.cancelUpload(file);
                }

                this.files = without(this.files, file);
                this.emit("removedfile", file);

                if (this.files.length === 0) {
                    return this.emit("reset");
                }
            } // Removes all files that aren't currently processed from the list

        }, {
            key: "removeAllFiles",
            value: function removeAllFiles(cancelIfNecessary) {
                // Create a copy of files since removeFile() changes the @files array.
                if (cancelIfNecessary == null) {
                    cancelIfNecessary = false;
                }

                var _iteratorNormalCompletion17 = true;
                var _didIteratorError17 = false;
                var _iteratorError17 = undefined;

                try {
                    for (var _iterator17 = this.files.slice()[Symbol.iterator](), _step17; !(_iteratorNormalCompletion17 = (_step17 = _iterator17.next()).done); _iteratorNormalCompletion17 = true) {
                        var file = _step17.value;

                        if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {
                            this.removeFile(file);
                        }
                    }
                } catch (err) {
                    _didIteratorError17 = true;
                    _iteratorError17 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion17 && _iterator17["return"] != null) {
                            _iterator17["return"]();
                        }
                    } finally {
                        if (_didIteratorError17) {
                            throw _iteratorError17;
                        }
                    }
                }

                return null;
            } // Resizes an image before it gets sent to the server. This function is the default behavior of
            // `options.transformFile` if `resizeWidth` or `resizeHeight` are set. The callback is invoked with
            // the resized blob.

        }, {
            key: "resizeImage",
            value: function resizeImage(file, width, height, resizeMethod, callback) {
                var _this11 = this;

                return this.createThumbnail(file, width, height, resizeMethod, true, function(dataUrl, canvas) {
                    if (canvas == null) {
                        // The image has not been resized
                        return callback(file);
                    } else {
                        var resizeMimeType = _this11.options.resizeMimeType;

                        if (resizeMimeType == null) {
                            resizeMimeType = file.type;
                        }

                        var resizedDataURL = canvas.toDataURL(resizeMimeType, _this11.options.resizeQuality);

                        if (resizeMimeType === 'image/jpeg' || resizeMimeType === 'image/jpg') {
                            // Now add the original EXIF information
                            resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL);
                        }

                        return callback(Dropzone.dataURItoBlob(resizedDataURL));
                    }
                });
            }
        }, {
            key: "createThumbnail",
            value: function createThumbnail(file, width, height, resizeMethod, fixOrientation, callback) {
                var _this12 = this;

                var fileReader = new FileReader();

                fileReader.onload = function() {
                    file.dataURL = fileReader.result; // Don't bother creating a thumbnail for SVG images since they're vector

                    if (file.type === "image/svg+xml") {
                        if (callback != null) {
                            callback(fileReader.result);
                        }

                        return;
                    }

                    _this12.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback);
                };

                fileReader.readAsDataURL(file);
            } // `mockFile` needs to have these attributes:
            // 
            //     { name: 'name', size: 12345, imageUrl: '' }
            //
            // `callback` will be invoked when the image has been downloaded and displayed.
            // `crossOrigin` will be added to the `img` tag when accessing the file.

        }, {
            key: "displayExistingFile",
            value: function displayExistingFile(mockFile, imageUrl, callback, crossOrigin) {
                var _this13 = this;

                var resizeThumbnail = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
                this.emit("addedfile", mockFile);
                this.emit("complete", mockFile);

                if (!resizeThumbnail) {
                    this.emit("thumbnail", mockFile, imageUrl);
                    if (callback) callback();
                } else {
                    var onDone = function onDone(thumbnail) {
                        _this13.emit('thumbnail', mockFile, thumbnail);

                        if (callback) callback();
                    };

                    mockFile.dataURL = imageUrl;
                    this.createThumbnailFromUrl(mockFile, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.resizeMethod, this.options.fixOrientation, onDone, crossOrigin);
                }
            }
        }, {
            key: "createThumbnailFromUrl",
            value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) {
                var _this14 = this;

                // Not using `new Image` here because of a bug in latest Chrome versions.
                // See https://github.com/enyo/dropzone/pull/226
                var img = document.createElement("img");

                if (crossOrigin) {
                    img.crossOrigin = crossOrigin;
                }

                img.onload = function() {
                    var loadExif = function loadExif(callback) {
                        return callback(1);
                    };

                    if (typeof EXIF !== 'undefined' && EXIF !== null && fixOrientation) {
                        loadExif = function loadExif(callback) {
                            return EXIF.getData(img, function() {
                                return callback(EXIF.getTag(this, 'Orientation'));
                            });
                        };
                    }

                    return loadExif(function(orientation) {
                        file.width = img.width;
                        file.height = img.height;

                        var resizeInfo = _this14.options.resize.call(_this14, file, width, height, resizeMethod);

                        var canvas = document.createElement("canvas");
                        var ctx = canvas.getContext("2d");
                        canvas.width = resizeInfo.trgWidth;
                        canvas.height = resizeInfo.trgHeight;

                        if (orientation > 4) {
                            canvas.width = resizeInfo.trgHeight;
                            canvas.height = resizeInfo.trgWidth;
                        }

                        switch (orientation) {
                            case 2:
                                // horizontal flip
                                ctx.translate(canvas.width, 0);
                                ctx.scale(-1, 1);
                                break;

                            case 3:
                                // 180° rotate left
                                ctx.translate(canvas.width, canvas.height);
                                ctx.rotate(Math.PI);
                                break;

                            case 4:
                                // vertical flip
                                ctx.translate(0, canvas.height);
                                ctx.scale(1, -1);
                                break;

                            case 5:
                                // vertical flip + 90 rotate right
                                ctx.rotate(0.5 * Math.PI);
                                ctx.scale(1, -1);
                                break;

                            case 6:
                                // 90° rotate right
                                ctx.rotate(0.5 * Math.PI);
                                ctx.translate(0, -canvas.width);
                                break;

                            case 7:
                                // horizontal flip + 90 rotate right
                                ctx.rotate(0.5 * Math.PI);
                                ctx.translate(canvas.height, -canvas.width);
                                ctx.scale(-1, 1);
                                break;

                            case 8:
                                // 90° rotate left
                                ctx.rotate(-0.5 * Math.PI);
                                ctx.translate(-canvas.height, 0);
                                break;
                        } // This is a bugfix for iOS' scaling bug.


                        drawImageIOSFix(ctx, img, resizeInfo.srcX != null ? resizeInfo.srcX : 0, resizeInfo.srcY != null ? resizeInfo.srcY : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, resizeInfo.trgX != null ? resizeInfo.trgX : 0, resizeInfo.trgY != null ? resizeInfo.trgY : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);
                        var thumbnail = canvas.toDataURL("image/png");

                        if (callback != null) {
                            return callback(thumbnail, canvas);
                        }
                    });
                };

                if (callback != null) {
                    img.onerror = callback;
                }

                return img.src = file.dataURL;
            } // Goes through the queue and processes files if there aren't too many already.

        }, {
            key: "processQueue",
            value: function processQueue() {
                var parallelUploads = this.options.parallelUploads;
                var processingLength = this.getUploadingFiles().length;
                var i = processingLength; // There are already at least as many files uploading than should be

                if (processingLength >= parallelUploads) {
                    return;
                }

                var queuedFiles = this.getQueuedFiles();

                if (!(queuedFiles.length > 0)) {
                    return;
                }

                if (this.options.uploadMultiple) {
                    // The files should be uploaded in one request
                    return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));
                } else {
                    while (i < parallelUploads) {
                        if (!queuedFiles.length) {
                            return;
                        } // Nothing left to process


                        this.processFile(queuedFiles.shift());
                        i++;
                    }
                }
            } // Wrapper for `processFiles`

        }, {
            key: "processFile",
            value: function processFile(file) {
                return this.processFiles([file]);
            } // Loads the file, then calls finishedLoading()

        }, {
            key: "processFiles",
            value: function processFiles(files) {
                var _iteratorNormalCompletion18 = true;
                var _didIteratorError18 = false;
                var _iteratorError18 = undefined;

                try {
                    for (var _iterator18 = files[Symbol.iterator](), _step18; !(_iteratorNormalCompletion18 = (_step18 = _iterator18.next()).done); _iteratorNormalCompletion18 = true) {
                        var file = _step18.value;
                        file.processing = true; // Backwards compatibility

                        file.status = Dropzone.UPLOADING;
                        this.emit("processing", file);
                    }
                } catch (err) {
                    _didIteratorError18 = true;
                    _iteratorError18 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion18 && _iterator18["return"] != null) {
                            _iterator18["return"]();
                        }
                    } finally {
                        if (_didIteratorError18) {
                            throw _iteratorError18;
                        }
                    }
                }

                if (this.options.uploadMultiple) {
                    this.emit("processingmultiple", files);
                }

                return this.uploadFiles(files);
            }
        }, {
            key: "_getFilesWithXhr",
            value: function _getFilesWithXhr(xhr) {
                var files;
                return files = this.files.filter(function(file) {
                    return file.xhr === xhr;
                }).map(function(file) {
                    return file;
                });
            } // Cancels the file upload and sets the status to CANCELED
            // **if** the file is actually being uploaded.
            // If it's still in the queue, the file is being removed from it and the status
            // set to CANCELED.

        }, {
            key: "cancelUpload",
            value: function cancelUpload(file) {
                if (file.status === Dropzone.UPLOADING) {
                    var groupedFiles = this._getFilesWithXhr(file.xhr);

                    var _iteratorNormalCompletion19 = true;
                    var _didIteratorError19 = false;
                    var _iteratorError19 = undefined;

                    try {
                        for (var _iterator19 = groupedFiles[Symbol.iterator](), _step19; !(_iteratorNormalCompletion19 = (_step19 = _iterator19.next()).done); _iteratorNormalCompletion19 = true) {
                            var groupedFile = _step19.value;
                            groupedFile.status = Dropzone.CANCELED;
                        }
                    } catch (err) {
                        _didIteratorError19 = true;
                        _iteratorError19 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion19 && _iterator19["return"] != null) {
                                _iterator19["return"]();
                            }
                        } finally {
                            if (_didIteratorError19) {
                                throw _iteratorError19;
                            }
                        }
                    }

                    if (typeof file.xhr !== 'undefined') {
                        file.xhr.abort();
                    }

                    var _iteratorNormalCompletion20 = true;
                    var _didIteratorError20 = false;
                    var _iteratorError20 = undefined;

                    try {
                        for (var _iterator20 = groupedFiles[Symbol.iterator](), _step20; !(_iteratorNormalCompletion20 = (_step20 = _iterator20.next()).done); _iteratorNormalCompletion20 = true) {
                            var _groupedFile = _step20.value;
                            this.emit("canceled", _groupedFile);
                        }
                    } catch (err) {
                        _didIteratorError20 = true;
                        _iteratorError20 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion20 && _iterator20["return"] != null) {
                                _iterator20["return"]();
                            }
                        } finally {
                            if (_didIteratorError20) {
                                throw _iteratorError20;
                            }
                        }
                    }

                    if (this.options.uploadMultiple) {
                        this.emit("canceledmultiple", groupedFiles);
                    }
                } else if (file.status === Dropzone.ADDED || file.status === Dropzone.QUEUED) {
                    file.status = Dropzone.CANCELED;
                    this.emit("canceled", file);

                    if (this.options.uploadMultiple) {
                        this.emit("canceledmultiple", [file]);
                    }
                }

                if (this.options.autoProcessQueue) {
                    return this.processQueue();
                }
            }
        }, {
            key: "resolveOption",
            value: function resolveOption(option) {
                if (typeof option === 'function') {
                    for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
                        args[_key3 - 1] = arguments[_key3];
                    }

                    return option.apply(this, args);
                }

                return option;
            }
        }, {
            key: "uploadFile",
            value: function uploadFile(file) {
                return this.uploadFiles([file]);
            }
        }, {
            key: "uploadFiles",
            value: function uploadFiles(files) {
                var _this15 = this;

                this._transformFiles(files, function(transformedFiles) {
                    if (_this15.options.chunking) {
                        // Chunking is not allowed to be used with `uploadMultiple` so we know
                        // that there is only __one__file.
                        var transformedFile = transformedFiles[0];
                        files[0].upload.chunked = _this15.options.chunking && (_this15.options.forceChunking || transformedFile.size > _this15.options.chunkSize);
                        files[0].upload.totalChunkCount = Math.ceil(transformedFile.size / _this15.options.chunkSize);
                    }

                    if (files[0].upload.chunked) {
                        // This file should be sent in chunks!
                        // If the chunking option is set, we **know** that there can only be **one** file, since
                        // uploadMultiple is not allowed with this option.
                        var file = files[0];
                        var _transformedFile = transformedFiles[0];
                        var startedChunkCount = 0;
                        file.upload.chunks = [];

                        var handleNextChunk = function handleNextChunk() {
                            var chunkIndex = 0; // Find the next item in file.upload.chunks that is not defined yet.

                            while (file.upload.chunks[chunkIndex] !== undefined) {
                                chunkIndex++;
                            } // This means, that all chunks have already been started.


                            if (chunkIndex >= file.upload.totalChunkCount) return;
                            startedChunkCount++;
                            var start = chunkIndex * _this15.options.chunkSize;
                            var end = Math.min(start + _this15.options.chunkSize, file.size);
                            var dataBlock = {
                                name: _this15._getParamName(0),
                                data: _transformedFile.webkitSlice ? _transformedFile.webkitSlice(start, end) : _transformedFile.slice(start, end),
                                filename: file.upload.filename,
                                chunkIndex: chunkIndex
                            };
                            file.upload.chunks[chunkIndex] = {
                                file: file,
                                index: chunkIndex,
                                dataBlock: dataBlock,
                                // In case we want to retry.
                                status: Dropzone.UPLOADING,
                                progress: 0,
                                retries: 0 // The number of times this block has been retried.

                            };

                            _this15._uploadData(files, [dataBlock]);
                        };

                        file.upload.finishedChunkUpload = function(chunk) {
                            var allFinished = true;
                            chunk.status = Dropzone.SUCCESS; // Clear the data from the chunk

                            chunk.dataBlock = null; // Leaving this reference to xhr intact here will cause memory leaks in some browsers

                            chunk.xhr = null;

                            for (var i = 0; i < file.upload.totalChunkCount; i++) {
                                if (file.upload.chunks[i] === undefined) {
                                    return handleNextChunk();
                                }

                                if (file.upload.chunks[i].status !== Dropzone.SUCCESS) {
                                    allFinished = false;
                                }
                            }

                            if (allFinished) {
                                _this15.options.chunksUploaded(file, function() {
                                    _this15._finished(files, '', null);
                                });
                            }
                        };

                        if (_this15.options.parallelChunkUploads) {
                            for (var i = 0; i < file.upload.totalChunkCount; i++) {
                                handleNextChunk();
                            }
                        } else {
                            handleNextChunk();
                        }
                    } else {
                        var dataBlocks = [];

                        for (var _i3 = 0; _i3 < files.length; _i3++) {
                            dataBlocks[_i3] = {
                                name: _this15._getParamName(_i3),
                                data: transformedFiles[_i3],
                                filename: files[_i3].upload.filename
                            };
                        }

                        _this15._uploadData(files, dataBlocks);
                    }
                });
            } /// Returns the right chunk for given file and xhr

        }, {
            key: "_getChunk",
            value: function _getChunk(file, xhr) {
                for (var i = 0; i < file.upload.totalChunkCount; i++) {
                    if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].xhr === xhr) {
                        return file.upload.chunks[i];
                    }
                }
            } // This function actually uploads the file(s) to the server.
            // If dataBlocks contains the actual data to upload (meaning, that this could either be transformed
            // files, or individual chunks for chunked upload).

        }, {
            key: "_uploadData",
            value: function _uploadData(files, dataBlocks) {
                var _this16 = this;

                var xhr = new XMLHttpRequest(); // Put the xhr object in the file objects to be able to reference it later.

                var _iteratorNormalCompletion21 = true;
                var _didIteratorError21 = false;
                var _iteratorError21 = undefined;

                try {
                    for (var _iterator21 = files[Symbol.iterator](), _step21; !(_iteratorNormalCompletion21 = (_step21 = _iterator21.next()).done); _iteratorNormalCompletion21 = true) {
                        var file = _step21.value;
                        file.xhr = xhr;
                    }
                } catch (err) {
                    _didIteratorError21 = true;
                    _iteratorError21 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion21 && _iterator21["return"] != null) {
                            _iterator21["return"]();
                        }
                    } finally {
                        if (_didIteratorError21) {
                            throw _iteratorError21;
                        }
                    }
                }

                if (files[0].upload.chunked) {
                    // Put the xhr object in the right chunk object, so it can be associated later, and found with _getChunk
                    files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr = xhr;
                }

                var method = this.resolveOption(this.options.method, files);
                var url = this.resolveOption(this.options.url, files);
                xhr.open(method, url, true); // Setting the timeout after open because of IE11 issue: https://gitlab.com/meno/dropzone/issues/8

                xhr.timeout = this.resolveOption(this.options.timeout, files); // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179

                xhr.withCredentials = !!this.options.withCredentials;

                xhr.onload = function(e) {
                    _this16._finishedUploading(files, xhr, e);
                };

                xhr.ontimeout = function() {
                    _this16._handleUploadError(files, xhr, "Request timedout after ".concat(_this16.options.timeout, " seconds"));
                };

                xhr.onerror = function() {
                    _this16._handleUploadError(files, xhr);
                }; // Some browsers do not have the .upload property


                var progressObj = xhr.upload != null ? xhr.upload : xhr;

                progressObj.onprogress = function(e) {
                    return _this16._updateFilesUploadProgress(files, xhr, e);
                };

                var headers = {
                    "Accept": "application/json",
                    "Cache-Control": "no-cache",
                    "X-Requested-With": "XMLHttpRequest"
                };

                if (this.options.headers) {
                    Dropzone.extend(headers, this.options.headers);
                }

                for (var headerName in headers) {
                    var headerValue = headers[headerName];

                    if (headerValue) {
                        xhr.setRequestHeader(headerName, headerValue);
                    }
                }

                var formData = new FormData(); // Adding all @options parameters

                if (this.options.params) {
                    var additionalParams = this.options.params;

                    if (typeof additionalParams === 'function') {
                        additionalParams = additionalParams.call(this, files, xhr, files[0].upload.chunked ? this._getChunk(files[0], xhr) : null);
                    }

                    for (var key in additionalParams) {
                        var value = additionalParams[key];
                        formData.append(key, value);
                    }
                } // Let the user add additional data if necessary


                var _iteratorNormalCompletion22 = true;
                var _didIteratorError22 = false;
                var _iteratorError22 = undefined;

                try {
                    for (var _iterator22 = files[Symbol.iterator](), _step22; !(_iteratorNormalCompletion22 = (_step22 = _iterator22.next()).done); _iteratorNormalCompletion22 = true) {
                        var _file = _step22.value;
                        this.emit("sending", _file, xhr, formData);
                    }
                } catch (err) {
                    _didIteratorError22 = true;
                    _iteratorError22 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion22 && _iterator22["return"] != null) {
                            _iterator22["return"]();
                        }
                    } finally {
                        if (_didIteratorError22) {
                            throw _iteratorError22;
                        }
                    }
                }

                if (this.options.uploadMultiple) {
                    this.emit("sendingmultiple", files, xhr, formData);
                }

                this._addFormElementData(formData); // Finally add the files
                // Has to be last because some servers (eg: S3) expect the file to be the last parameter


                for (var i = 0; i < dataBlocks.length; i++) {
                    var dataBlock = dataBlocks[i];
                    formData.append(dataBlock.name, dataBlock.data, dataBlock.filename);
                }

                this.submitRequest(xhr, formData, files);
            } // Transforms all files with this.options.transformFile and invokes done with the transformed files when done.

        }, {
            key: "_transformFiles",
            value: function _transformFiles(files, done) {
                var _this17 = this;

                var transformedFiles = []; // Clumsy way of handling asynchronous calls, until I get to add a proper Future library.

                var doneCounter = 0;

                var _loop = function _loop(i) {
                    _this17.options.transformFile.call(_this17, files[i], function(transformedFile) {
                        transformedFiles[i] = transformedFile;

                        if (++doneCounter === files.length) {
                            done(transformedFiles);
                        }
                    });
                };

                for (var i = 0; i < files.length; i++) {
                    _loop(i);
                }
            } // Takes care of adding other input elements of the form to the AJAX request

        }, {
            key: "_addFormElementData",
            value: function _addFormElementData(formData) {
                // Take care of other input elements
                if (this.element.tagName === "FORM") {
                    var _iteratorNormalCompletion23 = true;
                    var _didIteratorError23 = false;
                    var _iteratorError23 = undefined;

                    try {
                        for (var _iterator23 = this.element.querySelectorAll("input, textarea, select, button")[Symbol.iterator](), _step23; !(_iteratorNormalCompletion23 = (_step23 = _iterator23.next()).done); _iteratorNormalCompletion23 = true) {
                            var input = _step23.value;
                            var inputName = input.getAttribute("name");
                            var inputType = input.getAttribute("type");
                            if (inputType) inputType = inputType.toLowerCase(); // If the input doesn't have a name, we can't use it.

                            if (typeof inputName === 'undefined' || inputName === null) continue;

                            if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
                                // Possibly multiple values
                                var _iteratorNormalCompletion24 = true;
                                var _didIteratorError24 = false;
                                var _iteratorError24 = undefined;

                                try {
                                    for (var _iterator24 = input.options[Symbol.iterator](), _step24; !(_iteratorNormalCompletion24 = (_step24 = _iterator24.next()).done); _iteratorNormalCompletion24 = true) {
                                        var option = _step24.value;

                                        if (option.selected) {
                                            formData.append(inputName, option.value);
                                        }
                                    }
                                } catch (err) {
                                    _didIteratorError24 = true;
                                    _iteratorError24 = err;
                                } finally {
                                    try {
                                        if (!_iteratorNormalCompletion24 && _iterator24["return"] != null) {
                                            _iterator24["return"]();
                                        }
                                    } finally {
                                        if (_didIteratorError24) {
                                            throw _iteratorError24;
                                        }
                                    }
                                }
                            } else if (!inputType || inputType !== "checkbox" && inputType !== "radio" || input.checked) {
                                formData.append(inputName, input.value);
                            }
                        }
                    } catch (err) {
                        _didIteratorError23 = true;
                        _iteratorError23 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion23 && _iterator23["return"] != null) {
                                _iterator23["return"]();
                            }
                        } finally {
                            if (_didIteratorError23) {
                                throw _iteratorError23;
                            }
                        }
                    }
                }
            } // Invoked when there is new progress information about given files.
            // If e is not provided, it is assumed that the upload is finished.

        }, {
            key: "_updateFilesUploadProgress",
            value: function _updateFilesUploadProgress(files, xhr, e) {
                var progress;

                if (typeof e !== 'undefined') {
                    progress = 100 * e.loaded / e.total;

                    if (files[0].upload.chunked) {
                        var file = files[0]; // Since this is a chunked upload, we need to update the appropriate chunk progress.

                        var chunk = this._getChunk(file, xhr);

                        chunk.progress = progress;
                        chunk.total = e.total;
                        chunk.bytesSent = e.loaded;
                        var fileProgress = 0,
                            fileTotal,
                            fileBytesSent;
                        file.upload.progress = 0;
                        file.upload.total = 0;
                        file.upload.bytesSent = 0;

                        for (var i = 0; i < file.upload.totalChunkCount; i++) {
                            if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].progress !== undefined) {
                                file.upload.progress += file.upload.chunks[i].progress;
                                file.upload.total += file.upload.chunks[i].total;
                                file.upload.bytesSent += file.upload.chunks[i].bytesSent;
                            }
                        }

                        file.upload.progress = file.upload.progress / file.upload.totalChunkCount;
                    } else {
                        var _iteratorNormalCompletion25 = true;
                        var _didIteratorError25 = false;
                        var _iteratorError25 = undefined;

                        try {
                            for (var _iterator25 = files[Symbol.iterator](), _step25; !(_iteratorNormalCompletion25 = (_step25 = _iterator25.next()).done); _iteratorNormalCompletion25 = true) {
                                var _file2 = _step25.value;
                                _file2.upload.progress = progress;
                                _file2.upload.total = e.total;
                                _file2.upload.bytesSent = e.loaded;
                            }
                        } catch (err) {
                            _didIteratorError25 = true;
                            _iteratorError25 = err;
                        } finally {
                            try {
                                if (!_iteratorNormalCompletion25 && _iterator25["return"] != null) {
                                    _iterator25["return"]();
                                }
                            } finally {
                                if (_didIteratorError25) {
                                    throw _iteratorError25;
                                }
                            }
                        }
                    }

                    var _iteratorNormalCompletion26 = true;
                    var _didIteratorError26 = false;
                    var _iteratorError26 = undefined;

                    try {
                        for (var _iterator26 = files[Symbol.iterator](), _step26; !(_iteratorNormalCompletion26 = (_step26 = _iterator26.next()).done); _iteratorNormalCompletion26 = true) {
                            var _file3 = _step26.value;
                            this.emit("uploadprogress", _file3, _file3.upload.progress, _file3.upload.bytesSent);
                        }
                    } catch (err) {
                        _didIteratorError26 = true;
                        _iteratorError26 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion26 && _iterator26["return"] != null) {
                                _iterator26["return"]();
                            }
                        } finally {
                            if (_didIteratorError26) {
                                throw _iteratorError26;
                            }
                        }
                    }
                } else {
                    // Called when the file finished uploading
                    var allFilesFinished = true;
                    progress = 100;
                    var _iteratorNormalCompletion27 = true;
                    var _didIteratorError27 = false;
                    var _iteratorError27 = undefined;

                    try {
                        for (var _iterator27 = files[Symbol.iterator](), _step27; !(_iteratorNormalCompletion27 = (_step27 = _iterator27.next()).done); _iteratorNormalCompletion27 = true) {
                            var _file4 = _step27.value;

                            if (_file4.upload.progress !== 100 || _file4.upload.bytesSent !== _file4.upload.total) {
                                allFilesFinished = false;
                            }

                            _file4.upload.progress = progress;
                            _file4.upload.bytesSent = _file4.upload.total;
                        } // Nothing to do, all files already at 100%

                    } catch (err) {
                        _didIteratorError27 = true;
                        _iteratorError27 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion27 && _iterator27["return"] != null) {
                                _iterator27["return"]();
                            }
                        } finally {
                            if (_didIteratorError27) {
                                throw _iteratorError27;
                            }
                        }
                    }

                    if (allFilesFinished) {
                        return;
                    }

                    var _iteratorNormalCompletion28 = true;
                    var _didIteratorError28 = false;
                    var _iteratorError28 = undefined;

                    try {
                        for (var _iterator28 = files[Symbol.iterator](), _step28; !(_iteratorNormalCompletion28 = (_step28 = _iterator28.next()).done); _iteratorNormalCompletion28 = true) {
                            var _file5 = _step28.value;
                            this.emit("uploadprogress", _file5, progress, _file5.upload.bytesSent);
                        }
                    } catch (err) {
                        _didIteratorError28 = true;
                        _iteratorError28 = err;
                    } finally {
                        try {
                            if (!_iteratorNormalCompletion28 && _iterator28["return"] != null) {
                                _iterator28["return"]();
                            }
                        } finally {
                            if (_didIteratorError28) {
                                throw _iteratorError28;
                            }
                        }
                    }
                }
            }
        }, {
            key: "_finishedUploading",
            value: function _finishedUploading(files, xhr, e) {
                var response;

                if (files[0].status === Dropzone.CANCELED) {
                    return;
                }

                if (xhr.readyState !== 4) {
                    return;
                }

                if (xhr.responseType !== 'arraybuffer' && xhr.responseType !== 'blob') {
                    response = xhr.responseText;

                    if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) {
                        try {
                            response = JSON.parse(response);
                        } catch (error) {
                            e = error;
                            response = "Invalid JSON response from server.";
                        }
                    }
                }

                this._updateFilesUploadProgress(files);

                if (!(200 <= xhr.status && xhr.status < 300)) {
                    this._handleUploadError(files, xhr, response);
                } else {
                    if (files[0].upload.chunked) {
                        files[0].upload.finishedChunkUpload(this._getChunk(files[0], xhr));
                    } else {
                        this._finished(files, response, e);
                    }
                }
            }
        }, {
            key: "_handleUploadError",
            value: function _handleUploadError(files, xhr, response) {
                if (files[0].status === Dropzone.CANCELED) {
                    return;
                }

                if (files[0].upload.chunked && this.options.retryChunks) {
                    var chunk = this._getChunk(files[0], xhr);

                    if (chunk.retries++ < this.options.retryChunksLimit) {
                        this._uploadData(files, [chunk.dataBlock]);

                        return;
                    } else {
                        console.warn('Retried this chunk too often. Giving up.');
                    }
                }

                this._errorProcessing(files, response || this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr);
            }
        }, {
            key: "submitRequest",
            value: function submitRequest(xhr, formData, files) {
                xhr.send(formData);
            } // Called internally when processing is finished.
            // Individual callbacks have to be called in the appropriate sections.

        }, {
            key: "_finished",
            value: function _finished(files, responseText, e) {
                var _iteratorNormalCompletion29 = true;
                var _didIteratorError29 = false;
                var _iteratorError29 = undefined;

                try {
                    for (var _iterator29 = files[Symbol.iterator](), _step29; !(_iteratorNormalCompletion29 = (_step29 = _iterator29.next()).done); _iteratorNormalCompletion29 = true) {
                        var file = _step29.value;
                        file.status = Dropzone.SUCCESS;
                        this.emit("success", file, responseText, e);
                        this.emit("complete", file);
                    }
                } catch (err) {
                    _didIteratorError29 = true;
                    _iteratorError29 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion29 && _iterator29["return"] != null) {
                            _iterator29["return"]();
                        }
                    } finally {
                        if (_didIteratorError29) {
                            throw _iteratorError29;
                        }
                    }
                }

                if (this.options.uploadMultiple) {
                    this.emit("successmultiple", files, responseText, e);
                    this.emit("completemultiple", files);
                }

                if (this.options.autoProcessQueue) {
                    return this.processQueue();
                }
            } // Called internally when processing is finished.
            // Individual callbacks have to be called in the appropriate sections.

        }, {
            key: "_errorProcessing",
            value: function _errorProcessing(files, message, xhr) {
                var _iteratorNormalCompletion30 = true;
                var _didIteratorError30 = false;
                var _iteratorError30 = undefined;

                try {
                    for (var _iterator30 = files[Symbol.iterator](), _step30; !(_iteratorNormalCompletion30 = (_step30 = _iterator30.next()).done); _iteratorNormalCompletion30 = true) {
                        var file = _step30.value;
                        file.status = Dropzone.ERROR;
                        this.emit("error", file, message, xhr);
                        this.emit("complete", file);
                    }
                } catch (err) {
                    _didIteratorError30 = true;
                    _iteratorError30 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion30 && _iterator30["return"] != null) {
                            _iterator30["return"]();
                        }
                    } finally {
                        if (_didIteratorError30) {
                            throw _iteratorError30;
                        }
                    }
                }

                if (this.options.uploadMultiple) {
                    this.emit("errormultiple", files, message, xhr);
                    this.emit("completemultiple", files);
                }

                if (this.options.autoProcessQueue) {
                    return this.processQueue();
                }
            }
        }], [{
            key: "uuidv4",
            value: function uuidv4() {
                return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                    var r = Math.random() * 16 | 0,
                        v = c === 'x' ? r : r & 0x3 | 0x8;
                    return v.toString(16);
                });
            }
        }]);

        return Dropzone;
    }(Emitter);

Dropzone.initClass();
Dropzone.version = "5.7.0"; // This is a map of options for your different dropzones. Add configurations
// to this object for your different dropzone elemens.
//
// Example:
//
//     Dropzone.options.myDropzoneElementId = { maxFilesize: 1 };
//
// To disable autoDiscover for a specific element, you can set `false` as an option:
//
//     Dropzone.options.myDisabledElementId = false;
//
// And in html:
//
//     <form action="/upload" id="my-dropzone-element-id" class="dropzone"></form>

Dropzone.options = {}; // Returns the options for an element or undefined if none available.

Dropzone.optionsForElement = function(element) {
    // Get the `Dropzone.options.elementId` for this element if it exists
    if (element.getAttribute("id")) {
        return Dropzone.options[camelize(element.getAttribute("id"))];
    } else {
        return undefined;
    }
}; // Holds a list of all dropzone instances


Dropzone.instances = []; // Returns the dropzone for given element if any

Dropzone.forElement = function(element) {
    if (typeof element === "string") {
        element = document.querySelector(element);
    }

    if ((element != null ? element.dropzone : undefined) == null) {
        throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");
    }

    return element.dropzone;
}; // Set to false if you don't want Dropzone to automatically find and attach to .dropzone elements.


Dropzone.autoDiscover = true; // Looks for all .dropzone elements and creates a dropzone for them

Dropzone.discover = function() {
    var dropzones;

    if (document.querySelectorAll) {
        dropzones = document.querySelectorAll(".dropzone");
    } else {
        dropzones = []; // IE :(

        var checkElements = function checkElements(elements) {
            return function() {
                var result = [];
                var _iteratorNormalCompletion31 = true;
                var _didIteratorError31 = false;
                var _iteratorError31 = undefined;

                try {
                    for (var _iterator31 = elements[Symbol.iterator](), _step31; !(_iteratorNormalCompletion31 = (_step31 = _iterator31.next()).done); _iteratorNormalCompletion31 = true) {
                        var el = _step31.value;

                        if (/(^| )dropzone($| )/.test(el.className)) {
                            result.push(dropzones.push(el));
                        } else {
                            result.push(undefined);
                        }
                    }
                } catch (err) {
                    _didIteratorError31 = true;
                    _iteratorError31 = err;
                } finally {
                    try {
                        if (!_iteratorNormalCompletion31 && _iterator31["return"] != null) {
                            _iterator31["return"]();
                        }
                    } finally {
                        if (_didIteratorError31) {
                            throw _iteratorError31;
                        }
                    }
                }

                return result;
            }();
        };

        checkElements(document.getElementsByTagName("div"));
        checkElements(document.getElementsByTagName("form"));
    }

    return function() {
        var result = [];
        var _iteratorNormalCompletion32 = true;
        var _didIteratorError32 = false;
        var _iteratorError32 = undefined;

        try {
            for (var _iterator32 = dropzones[Symbol.iterator](), _step32; !(_iteratorNormalCompletion32 = (_step32 = _iterator32.next()).done); _iteratorNormalCompletion32 = true) {
                var dropzone = _step32.value;

                // Create a dropzone unless auto discover has been disabled for specific element
                if (Dropzone.optionsForElement(dropzone) !== false) {
                    result.push(new Dropzone(dropzone));
                } else {
                    result.push(undefined);
                }
            }
        } catch (err) {
            _didIteratorError32 = true;
            _iteratorError32 = err;
        } finally {
            try {
                if (!_iteratorNormalCompletion32 && _iterator32["return"] != null) {
                    _iterator32["return"]();
                }
            } finally {
                if (_didIteratorError32) {
                    throw _iteratorError32;
                }
            }
        }

        return result;
    }();
}; // Since the whole Drag'n'Drop API is pretty new, some browsers implement it,
// but not correctly.
// So I created a blacklist of userAgents. Yes, yes. Browser sniffing, I know.
// But what to do when browsers *theoretically* support an API, but crash
// when using it.
//
// This is a list of regular expressions tested against navigator.userAgent
//
// ** It should only be used on browser that *do* support the API, but
// incorrectly **
//


Dropzone.blacklistedBrowsers = [ // The mac os and windows phone version of opera 12 seems to have a problem with the File drag'n'drop API.
    /opera.*(Macintosh|Windows Phone).*version\/12/i
]; // Checks if the browser is supported

Dropzone.isBrowserSupported = function() {
    var capableBrowser = true;

    if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {
        if (!("classList" in document.createElement("a"))) {
            capableBrowser = false;
        } else {
            // The browser supports the API, but may be blacklisted.
            var _iteratorNormalCompletion33 = true;
            var _didIteratorError33 = false;
            var _iteratorError33 = undefined;

            try {
                for (var _iterator33 = Dropzone.blacklistedBrowsers[Symbol.iterator](), _step33; !(_iteratorNormalCompletion33 = (_step33 = _iterator33.next()).done); _iteratorNormalCompletion33 = true) {
                    var regex = _step33.value;

                    if (regex.test(navigator.userAgent)) {
                        capableBrowser = false;
                        continue;
                    }
                }
            } catch (err) {
                _didIteratorError33 = true;
                _iteratorError33 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion33 && _iterator33["return"] != null) {
                        _iterator33["return"]();
                    }
                } finally {
                    if (_didIteratorError33) {
                        throw _iteratorError33;
                    }
                }
            }
        }
    } else {
        capableBrowser = false;
    }

    return capableBrowser;
};

Dropzone.dataURItoBlob = function(dataURI) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
    var byteString = atob(dataURI.split(',')[1]); // separate out the mime component

    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; // write the bytes of the string to an ArrayBuffer

    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);

    for (var i = 0, end = byteString.length, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) {
        ia[i] = byteString.charCodeAt(i);
    } // write the ArrayBuffer to a blob


    return new Blob([ab], {
        type: mimeString
    });
}; // Returns an array without the rejected item


var without = function without(list, rejectedItem) {
    return list.filter(function(item) {
        return item !== rejectedItem;
    }).map(function(item) {
        return item;
    });
}; // abc-def_ghi -> abcDefGhi


var camelize = function camelize(str) {
    return str.replace(/[\-_](\w)/g, function(match) {
        return match.charAt(1).toUpperCase();
    });
}; // Creates an element from string


Dropzone.createElement = function(string) {
    var div = document.createElement("div");
    div.innerHTML = string;
    return div.childNodes[0];
}; // Tests if given element is inside (or simply is) the container


Dropzone.elementInside = function(element, container) {
    if (element === container) {
        return true;
    } // Coffeescript doesn't support do/while loops


    while (element = element.parentNode) {
        if (element === container) {
            return true;
        }
    }

    return false;
};

Dropzone.getElement = function(el, name) {
    var element;

    if (typeof el === "string") {
        element = document.querySelector(el);
    } else if (el.nodeType != null) {
        element = el;
    }

    if (element == null) {
        throw new Error("Invalid `".concat(name, "` option provided. Please provide a CSS selector or a plain HTML element."));
    }

    return element;
};

Dropzone.getElements = function(els, name) {
    var el, elements;

    if (els instanceof Array) {
        elements = [];

        try {
            var _iteratorNormalCompletion34 = true;
            var _didIteratorError34 = false;
            var _iteratorError34 = undefined;

            try {
                for (var _iterator34 = els[Symbol.iterator](), _step34; !(_iteratorNormalCompletion34 = (_step34 = _iterator34.next()).done); _iteratorNormalCompletion34 = true) {
                    el = _step34.value;
                    elements.push(this.getElement(el, name));
                }
            } catch (err) {
                _didIteratorError34 = true;
                _iteratorError34 = err;
            } finally {
                try {
                    if (!_iteratorNormalCompletion34 && _iterator34["return"] != null) {
                        _iterator34["return"]();
                    }
                } finally {
                    if (_didIteratorError34) {
                        throw _iteratorError34;
                    }
                }
            }
        } catch (e) {
            elements = null;
        }
    } else if (typeof els === "string") {
        elements = [];
        var _iteratorNormalCompletion35 = true;
        var _didIteratorError35 = false;
        var _iteratorError35 = undefined;

        try {
            for (var _iterator35 = document.querySelectorAll(els)[Symbol.iterator](), _step35; !(_iteratorNormalCompletion35 = (_step35 = _iterator35.next()).done); _iteratorNormalCompletion35 = true) {
                el = _step35.value;
                elements.push(el);
            }
        } catch (err) {
            _didIteratorError35 = true;
            _iteratorError35 = err;
        } finally {
            try {
                if (!_iteratorNormalCompletion35 && _iterator35["return"] != null) {
                    _iterator35["return"]();
                }
            } finally {
                if (_didIteratorError35) {
                    throw _iteratorError35;
                }
            }
        }
    } else if (els.nodeType != null) {
        elements = [els];
    }

    if (elements == null || !elements.length) {
        throw new Error("Invalid `".concat(name, "` option provided. Please provide a CSS selector, a plain HTML element or a list of those."));
    }

    return elements;
}; // Asks the user the question and calls accepted or rejected accordingly
//
// The default implementation just uses `window.confirm` and then calls the
// appropriate callback.


Dropzone.confirm = function(question, accepted, rejected) {
    if (window.confirm(question)) {
        return accepted();
    } else if (rejected != null) {
        return rejected();
    }
}; // Validates the mime type like this:
//
// https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept


Dropzone.isValidFile = function(file, acceptedFiles) {
    if (!acceptedFiles) {
        return true;
    } // If there are no accepted mime types, it's OK


    acceptedFiles = acceptedFiles.split(",");
    var mimeType = file.type;
    var baseMimeType = mimeType.replace(/\/.*$/, "");
    var _iteratorNormalCompletion36 = true;
    var _didIteratorError36 = false;
    var _iteratorError36 = undefined;

    try {
        for (var _iterator36 = acceptedFiles[Symbol.iterator](), _step36; !(_iteratorNormalCompletion36 = (_step36 = _iterator36.next()).done); _iteratorNormalCompletion36 = true) {
            var validType = _step36.value;
            validType = validType.trim();

            if (validType.charAt(0) === ".") {
                if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
                    return true;
                }
            } else if (/\/\*$/.test(validType)) {
                // This is something like a image/* mime type
                if (baseMimeType === validType.replace(/\/.*$/, "")) {
                    return true;
                }
            } else {
                if (mimeType === validType) {
                    return true;
                }
            }
        }
    } catch (err) {
        _didIteratorError36 = true;
        _iteratorError36 = err;
    } finally {
        try {
            if (!_iteratorNormalCompletion36 && _iterator36["return"] != null) {
                _iterator36["return"]();
            }
        } finally {
            if (_didIteratorError36) {
                throw _iteratorError36;
            }
        }
    }

    return false;
}; // Augment jQuery


if (typeof jQuery !== 'undefined' && jQuery !== null) {
    jQuery.fn.dropzone = function(options) {
        return this.each(function() {
            return new Dropzone(this, options);
        });
    };
}

if (typeof module !== 'undefined' && module !== null) {
    module.exports = Dropzone;
} else {
    window.Dropzone = Dropzone;
} // Dropzone file status codes


Dropzone.ADDED = "added";
Dropzone.QUEUED = "queued"; // For backwards compatibility. Now, if a file is accepted, it's either queued
// or uploading.

Dropzone.ACCEPTED = Dropzone.QUEUED;
Dropzone.UPLOADING = "uploading";
Dropzone.PROCESSING = Dropzone.UPLOADING; // alias

Dropzone.CANCELED = "canceled";
Dropzone.ERROR = "error";
Dropzone.SUCCESS = "success";
/*

 Bugfix for iOS 6 and 7
 Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
 based on the work of https://github.com/stomita/ios-imagefile-megapixel

 */
// Detecting vertical squash in loaded image.
// Fixes a bug which squash image vertically while drawing into canvas for some images.
// This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel

var detectVerticalSquash = function detectVerticalSquash(img) {
    var iw = img.naturalWidth;
    var ih = img.naturalHeight;
    var canvas = document.createElement("canvas");
    canvas.width = 1;
    canvas.height = ih;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    var _ctx$getImageData = ctx.getImageData(1, 0, 1, ih),
        data = _ctx$getImageData.data; // search image edge pixel position in case it is squashed vertically.


    var sy = 0;
    var ey = ih;
    var py = ih;

    while (py > sy) {
        var alpha = data[(py - 1) * 4 + 3];

        if (alpha === 0) {
            ey = py;
        } else {
            sy = py;
        }

        py = ey + sy >> 1;
    }

    var ratio = py / ih;

    if (ratio === 0) {
        return 1;
    } else {
        return ratio;
    }
}; // A replacement for context.drawImage
// (args are for source and destination).


var drawImageIOSFix = function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
    var vertSquashRatio = detectVerticalSquash(img);
    return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
}; // Based on MinifyJpeg
// Source: http://www.perry.cz/files/ExifRestorer.js
// http://elicon.blog57.fc2.com/blog-entry-206.html


var ExifRestore =
    /*#__PURE__*/
    function() {
        function ExifRestore() {
            _classCallCheck(this, ExifRestore);
        }

        _createClass(ExifRestore, null, [{
            key: "initClass",
            value: function initClass() {
                this.KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
            }
        }, {
            key: "encode64",
            value: function encode64(input) {
                var output = '';
                var chr1 = undefined;
                var chr2 = undefined;
                var chr3 = '';
                var enc1 = undefined;
                var enc2 = undefined;
                var enc3 = undefined;
                var enc4 = '';
                var i = 0;

                while (true) {
                    chr1 = input[i++];
                    chr2 = input[i++];
                    chr3 = input[i++];
                    enc1 = chr1 >> 2;
                    enc2 = (chr1 & 3) << 4 | chr2 >> 4;
                    enc3 = (chr2 & 15) << 2 | chr3 >> 6;
                    enc4 = chr3 & 63;

                    if (isNaN(chr2)) {
                        enc3 = enc4 = 64;
                    } else if (isNaN(chr3)) {
                        enc4 = 64;
                    }

                    output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4);
                    chr1 = chr2 = chr3 = '';
                    enc1 = enc2 = enc3 = enc4 = '';

                    if (!(i < input.length)) {
                        break;
                    }
                }

                return output;
            }
        }, {
            key: "restore",
            value: function restore(origFileBase64, resizedFileBase64) {
                if (!origFileBase64.match('data:image/jpeg;base64,')) {
                    return resizedFileBase64;
                }

                var rawImage = this.decode64(origFileBase64.replace('data:image/jpeg;base64,', ''));
                var segments = this.slice2Segments(rawImage);
                var image = this.exifManipulation(resizedFileBase64, segments);
                return "data:image/jpeg;base64,".concat(this.encode64(image));
            }
        }, {
            key: "exifManipulation",
            value: function exifManipulation(resizedFileBase64, segments) {
                var exifArray = this.getExifArray(segments);
                var newImageArray = this.insertExif(resizedFileBase64, exifArray);
                var aBuffer = new Uint8Array(newImageArray);
                return aBuffer;
            }
        }, {
            key: "getExifArray",
            value: function getExifArray(segments) {
                var seg = undefined;
                var x = 0;

                while (x < segments.length) {
                    seg = segments[x];

                    if (seg[0] === 255 & seg[1] === 225) {
                        return seg;
                    }

                    x++;
                }

                return [];
            }
        }, {
            key: "insertExif",
            value: function insertExif(resizedFileBase64, exifArray) {
                var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', '');
                var buf = this.decode64(imageData);
                var separatePoint = buf.indexOf(255, 3);
                var mae = buf.slice(0, separatePoint);
                var ato = buf.slice(separatePoint);
                var array = mae;
                array = array.concat(exifArray);
                array = array.concat(ato);
                return array;
            }
        }, {
            key: "slice2Segments",
            value: function slice2Segments(rawImageArray) {
                var head = 0;
                var segments = [];

                while (true) {
                    var length;

                    if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {
                        break;
                    }

                    if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {
                        head += 2;
                    } else {
                        length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3];
                        var endPoint = head + length + 2;
                        var seg = rawImageArray.slice(head, endPoint);
                        segments.push(seg);
                        head = endPoint;
                    }

                    if (head > rawImageArray.length) {
                        break;
                    }
                }

                return segments;
            }
        }, {
            key: "decode64",
            value: function decode64(input) {
                var output = '';
                var chr1 = undefined;
                var chr2 = undefined;
                var chr3 = '';
                var enc1 = undefined;
                var enc2 = undefined;
                var enc3 = undefined;
                var enc4 = '';
                var i = 0;
                var buf = []; // remove all characters that are not A-Z, a-z, 0-9, +, /, or =

                var base64test = /[^A-Za-z0-9\+\/\=]/g;

                if (base64test.exec(input)) {
                    console.warn('There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, \'+\', \'/\',and \'=\'\nExpect errors in decoding.');
                }

                input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '');

                while (true) {
                    enc1 = this.KEY_STR.indexOf(input.charAt(i++));
                    enc2 = this.KEY_STR.indexOf(input.charAt(i++));
                    enc3 = this.KEY_STR.indexOf(input.charAt(i++));
                    enc4 = this.KEY_STR.indexOf(input.charAt(i++));
                    chr1 = enc1 << 2 | enc2 >> 4;
                    chr2 = (enc2 & 15) << 4 | enc3 >> 2;
                    chr3 = (enc3 & 3) << 6 | enc4;
                    buf.push(chr1);

                    if (enc3 !== 64) {
                        buf.push(chr2);
                    }

                    if (enc4 !== 64) {
                        buf.push(chr3);
                    }

                    chr1 = chr2 = chr3 = '';
                    enc1 = enc2 = enc3 = enc4 = '';

                    if (!(i < input.length)) {
                        break;
                    }
                }

                return buf;
            }
        }]);

        return ExifRestore;
    }();

ExifRestore.initClass();
/*
 * contentloaded.js
 *
 * Author: Diego Perini (diego.perini at gmail.com)
 * Summary: cross-browser wrapper for DOMContentLoaded
 * Updated: 20101020
 * License: MIT
 * Version: 1.2
 *
 * URL:
 * http://javascript.nwbox.com/ContentLoaded/
 * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
 */
// @win window reference
// @fn function reference

var contentLoaded = function contentLoaded(win, fn) {
    var done = false;
    var top = true;
    var doc = win.document;
    var root = doc.documentElement;
    var add = doc.addEventListener ? "addEventListener" : "attachEvent";
    var rem = doc.addEventListener ? "removeEventListener" : "detachEvent";
    var pre = doc.addEventListener ? "" : "on";

    var init = function init(e) {
        if (e.type === "readystatechange" && doc.readyState !== "complete") {
            return;
        }

        (e.type === "load" ? win : doc)[rem](pre + e.type, init, false);

        if (!done && (done = true)) {
            return fn.call(win, e.type || e);
        }
    };

    var poll = function poll() {
        try {
            root.doScroll("left");
        } catch (e) {
            setTimeout(poll, 50);
            return;
        }

        return init("poll");
    };

    if (doc.readyState !== "complete") {
        if (doc.createEventObject && root.doScroll) {
            try {
                top = !win.frameElement;
            } catch (error) {}

            if (top) {
                poll();
            }
        }

        doc[add](pre + "DOMContentLoaded", init, false);
        doc[add](pre + "readystatechange", init, false);
        return win[add](pre + "load", init, false);
    }
}; // As a single function to be able to write tests.


Dropzone._autoDiscoverFunction = function() {
    if (Dropzone.autoDiscover) {
        return Dropzone.discover();
    }
};

contentLoaded(window, Dropzone._autoDiscoverFunction);

function __guard__(value, transform) {
    return typeof value !== 'undefined' && value !== null ? transform(value) : undefined;
}

function __guardMethod__(obj, methodName, transform) {
    if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') {
        return transform(obj, methodName);
    } else {
        return undefined;
    }
}
/*!
FullCalendar Standard Bundle v6.1.21
Docs & License: https://fullcalendar.io/docs/initialize-globals
(c) 2024 Adam Shaw
*/
var FullCalendar = (function(exports) {
    'use strict';

    var n, l$1, u$1, i$1, t, r$1, o, f$1, e$1, c$1 = {},
        s = [],
        a$1 = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;

    function h(n, l) {
        for (var u in l) n[u] = l[u];
        return n
    }

    function v$1(n) {
        var l = n.parentNode;
        l && l.removeChild(n);
    }

    function y(l, u, i) {
        var t, r, o, f = {};
        for (o in u) "key" == o ? t = u[o] : "ref" == o ? r = u[o] : f[o] = u[o];
        if (arguments.length > 2 && (f.children = arguments.length > 3 ? n.call(arguments, 2) : i), "function" == typeof l && null != l.defaultProps)
            for (o in l.defaultProps) void 0 === f[o] && (f[o] = l.defaultProps[o]);
        return p(l, f, t, r, null)
    }

    function p(n, i, t, r, o) {
        var f = {
            type: n,
            props: i,
            key: t,
            ref: r,
            __k: null,
            __: null,
            __b: 0,
            __e: null,
            __d: void 0,
            __c: null,
            __h: null,
            constructor: void 0,
            __v: null == o ? ++u$1 : o
        };
        return null == o && null != l$1.vnode && l$1.vnode(f), f
    }

    function d() {
        return {
            current: null
        }
    }

    function _(n) {
        return n.children
    }

    function k$1(n, l, u, i, t) {
        var r;
        for (r in u) "children" === r || "key" === r || r in l || g$2(n, r, null, u[r], i);
        for (r in l) t && "function" != typeof l[r] || "children" === r || "key" === r || "value" === r || "checked" === r || u[r] === l[r] || g$2(n, r, l[r], u[r], i);
    }

    function b$1(n, l, u) {
        "-" === l[0] ? n.setProperty(l, null == u ? "" : u) : n[l] = null == u ? "" : "number" != typeof u || a$1.test(l) ? u : u + "px";
    }

    function g$2(n, l, u, i, t) {
        var r;
        n: if ("style" === l)
            if ("string" == typeof u) n.style.cssText = u;
            else {
                if ("string" == typeof i && (n.style.cssText = i = ""), i)
                    for (l in i) u && l in u || b$1(n.style, l, "");
                if (u)
                    for (l in u) i && u[l] === i[l] || b$1(n.style, l, u[l]);
            }
        else if ("o" === l[0] && "n" === l[1]) r = l !== (l = l.replace(/Capture$/, "")), l = l.toLowerCase() in n ? l.toLowerCase().slice(2) : l.slice(2), n.l || (n.l = {}), n.l[l + r] = u, u ? i || n.addEventListener(l, r ? w$2 : m$1, r) : n.removeEventListener(l, r ? w$2 : m$1, r);
        else if ("dangerouslySetInnerHTML" !== l) {
            if (t) l = l.replace(/xlink(H|:h)/, "h").replace(/sName$/, "s");
            else if ("width" !== l && "height" !== l && "href" !== l && "list" !== l && "form" !== l && "tabIndex" !== l && "download" !== l && l in n) try {
                n[l] = null == u ? "" : u;
                break n
            } catch (n) {}
            "function" == typeof u || (null == u || !1 === u && -1 == l.indexOf("-") ? n.removeAttribute(l) : n.setAttribute(l, u));
        }
    }

    function m$1(n) {
        t = !0;
        try {
            return this.l[n.type + !1](l$1.event ? l$1.event(n) : n)
        } finally {
            t = !1;
        }
    }

    function w$2(n) {
        t = !0;
        try {
            return this.l[n.type + !0](l$1.event ? l$1.event(n) : n)
        } finally {
            t = !1;
        }
    }

    function x$1(n, l) {
        this.props = n, this.context = l;
    }

    function A(n, l) {
        if (null == l) return n.__ ? A(n.__, n.__.__k.indexOf(n) + 1) : null;
        for (var u; l < n.__k.length; l++)
            if (null != (u = n.__k[l]) && null != u.__e) return u.__e;
        return "function" == typeof n.type ? A(n) : null
    }

    function P$1(n) {
        var l, u;
        if (null != (n = n.__) && null != n.__c) {
            for (n.__e = n.__c.base = null, l = 0; l < n.__k.length; l++)
                if (null != (u = n.__k[l]) && null != u.__e) {
                    n.__e = n.__c.base = u.__e;
                    break
                } return P$1(n)
        }
    }

    function C$1(n) {
        t ? setTimeout(n) : f$1(n);
    }

    function T$1(n) {
        (!n.__d && (n.__d = !0) && r$1.push(n) && !$$1.__r++ || o !== l$1.debounceRendering) && ((o = l$1.debounceRendering) || C$1)($$1);
    }

    function $$1() {
        var n, l, u, i, t, o, f, e;
        for (r$1.sort(function(n, l) {
                return n.__v.__b - l.__v.__b
            }); n = r$1.shift();) n.__d && (l = r$1.length, i = void 0, t = void 0, f = (o = (u = n).__v).__e, (e = u.__P) && (i = [], (t = h({}, o)).__v = o.__v + 1, M(e, o, t, u.__n, void 0 !== e.ownerSVGElement, null != o.__h ? [f] : null, i, null == f ? A(o) : f, o.__h), N(i, o), o.__e != f && P$1(o)), r$1.length > l && r$1.sort(function(n, l) {
            return n.__v.__b - l.__v.__b
        }));
        $$1.__r = 0;
    }

    function H$1(n, l, u, i, t, r, o, f, e, a) {
        var h, v, y, d, k, b, g, m = i && i.__k || s,
            w = m.length;
        for (u.__k = [], h = 0; h < l.length; h++)
            if (null != (d = u.__k[h] = null == (d = l[h]) || "boolean" == typeof d ? null : "string" == typeof d || "number" == typeof d || "bigint" == typeof d ? p(null, d, null, null, d) : Array.isArray(d) ? p(_, {
                    children: d
                }, null, null, null) : d.__b > 0 ? p(d.type, d.props, d.key, d.ref ? d.ref : null, d.__v) : d)) {
                if (d.__ = u, d.__b = u.__b + 1, null === (y = m[h]) || y && d.key == y.key && d.type === y.type) m[h] = void 0;
                else
                    for (v = 0; v < w; v++) {
                        if ((y = m[v]) && d.key == y.key && d.type === y.type) {
                            m[v] = void 0;
                            break
                        }
                        y = null;
                    }
                M(n, d, y = y || c$1, t, r, o, f, e, a), k = d.__e, (v = d.ref) && y.ref != v && (g || (g = []), y.ref && g.push(y.ref, null, d), g.push(v, d.__c || k, d)), null != k ? (null == b && (b = k), "function" == typeof d.type && d.__k === y.__k ? d.__d = e = I$1(d, e, n) : e = z$1(n, d, y, m, k, e), "function" == typeof u.type && (u.__d = e)) : e && y.__e == e && e.parentNode != n && (e = A(y));
            } for (u.__e = b, h = w; h--;) null != m[h] && ("function" == typeof u.type && null != m[h].__e && m[h].__e == u.__d && (u.__d = L$1(i).nextSibling), q(m[h], m[h]));
        if (g)
            for (h = 0; h < g.length; h++) S(g[h], g[++h], g[++h]);
    }

    function I$1(n, l, u) {
        for (var i, t = n.__k, r = 0; t && r < t.length; r++)(i = t[r]) && (i.__ = n, l = "function" == typeof i.type ? I$1(i, l, u) : z$1(u, i, i, t, i.__e, l));
        return l
    }

    function j$2(n, l) {
        return l = l || [], null == n || "boolean" == typeof n || (Array.isArray(n) ? n.some(function(n) {
            j$2(n, l);
        }) : l.push(n)), l
    }

    function z$1(n, l, u, i, t, r) {
        var o, f, e;
        if (void 0 !== l.__d) o = l.__d, l.__d = void 0;
        else if (null == u || t != r || null == t.parentNode) n: if (null == r || r.parentNode !== n) n.appendChild(t), o = null;
            else {
                for (f = r, e = 0;
                    (f = f.nextSibling) && e < i.length; e += 1)
                    if (f == t) break n;
                n.insertBefore(t, r), o = r;
            } return void 0 !== o ? o : t.nextSibling
    }

    function L$1(n) {
        var l, u, i;
        if (null == n.type || "string" == typeof n.type) return n.__e;
        if (n.__k)
            for (l = n.__k.length - 1; l >= 0; l--)
                if ((u = n.__k[l]) && (i = L$1(u))) return i;
        return null
    }

    function M(n, u, i, t, r, o, f, e, c) {
        var s, a, v, y, p, d, k, b, g, m, w, A, P, C, T, $ = u.type;
        if (void 0 !== u.constructor) return null;
        null != i.__h && (c = i.__h, e = u.__e = i.__e, u.__h = null, o = [e]), (s = l$1.__b) && s(u);
        try {
            n: if ("function" == typeof $) {
                if (b = u.props, g = (s = $.contextType) && t[s.__c], m = s ? g ? g.props.value : s.__ : t, i.__c ? k = (a = u.__c = i.__c).__ = a.__E : ("prototype" in $ && $.prototype.render ? u.__c = a = new $(b, m) : (u.__c = a = new x$1(b, m), a.constructor = $, a.render = B$1), g && g.sub(a), a.props = b, a.state || (a.state = {}), a.context = m, a.__n = t, v = a.__d = !0, a.__h = [], a._sb = []), null == a.__s && (a.__s = a.state), null != $.getDerivedStateFromProps && (a.__s == a.state && (a.__s = h({}, a.__s)), h(a.__s, $.getDerivedStateFromProps(b, a.__s))), y = a.props, p = a.state, a.__v = u, v) null == $.getDerivedStateFromProps && null != a.componentWillMount && a.componentWillMount(), null != a.componentDidMount && a.__h.push(a.componentDidMount);
                else {
                    if (null == $.getDerivedStateFromProps && b !== y && null != a.componentWillReceiveProps && a.componentWillReceiveProps(b, m), !a.__e && null != a.shouldComponentUpdate && !1 === a.shouldComponentUpdate(b, a.__s, m) || u.__v === i.__v) {
                        for (u.__v !== i.__v && (a.props = b, a.state = a.__s, a.__d = !1), u.__e = i.__e, u.__k = i.__k, u.__k.forEach(function(n) {
                                n && (n.__ = u);
                            }), w = 0; w < a._sb.length; w++) a.__h.push(a._sb[w]);
                        a._sb = [], a.__h.length && f.push(a);
                        break n
                    }
                    null != a.componentWillUpdate && a.componentWillUpdate(b, a.__s, m), null != a.componentDidUpdate && a.__h.push(function() {
                        a.componentDidUpdate(y, p, d);
                    });
                }
                if (a.context = m, a.props = b, a.__P = n, A = l$1.__r, P = 0, "prototype" in $ && $.prototype.render) {
                    for (a.state = a.__s, a.__d = !1, A && A(u), s = a.render(a.props, a.state, a.context), C = 0; C < a._sb.length; C++) a.__h.push(a._sb[C]);
                    a._sb = [];
                } else
                    do {
                        a.__d = !1, A && A(u), s = a.render(a.props, a.state, a.context), a.state = a.__s;
                    } while (a.__d && ++P < 25);
                a.state = a.__s, null != a.getChildContext && (t = h(h({}, t), a.getChildContext())), v || null == a.getSnapshotBeforeUpdate || (d = a.getSnapshotBeforeUpdate(y, p)), T = null != s && s.type === _ && null == s.key ? s.props.children : s, H$1(n, Array.isArray(T) ? T : [T], u, i, t, r, o, f, e, c), a.base = u.__e, u.__h = null, a.__h.length && f.push(a), k && (a.__E = a.__ = null), a.__e = !1;
            } else null == o && u.__v === i.__v ? (u.__k = i.__k, u.__e = i.__e) : u.__e = O(i.__e, u, i, t, r, o, f, c);
            (s = l$1.diffed) && s(u);
        }
        catch (n) {
            u.__v = null, (c || null != o) && (u.__e = e, u.__h = !!c, o[o.indexOf(e)] = null), l$1.__e(n, u, i);
        }
    }

    function N(n, u) {
        l$1.__c && l$1.__c(u, n), n.some(function(u) {
            try {
                n = u.__h, u.__h = [], n.some(function(n) {
                    n.call(u);
                });
            } catch (n) {
                l$1.__e(n, u.__v);
            }
        });
    }

    function O(l, u, i, t, r, o, f, e) {
        var s, a, h, y = i.props,
            p = u.props,
            d = u.type,
            _ = 0;
        if ("svg" === d && (r = !0), null != o)
            for (; _ < o.length; _++)
                if ((s = o[_]) && "setAttribute" in s == !!d && (d ? s.localName === d : 3 === s.nodeType)) {
                    l = s, o[_] = null;
                    break
                } if (null == l) {
            if (null === d) return document.createTextNode(p);
            l = r ? document.createElementNS("http://www.w3.org/2000/svg", d) : document.createElement(d, p.is && p), o = null, e = !1;
        }
        if (null === d) y === p || e && l.data === p || (l.data = p);
        else {
            if (o = o && n.call(l.childNodes), a = (y = i.props || c$1).dangerouslySetInnerHTML, h = p.dangerouslySetInnerHTML, !e) {
                if (null != o)
                    for (y = {}, _ = 0; _ < l.attributes.length; _++) y[l.attributes[_].name] = l.attributes[_].value;
                (h || a) && (h && (a && h.__html == a.__html || h.__html === l.innerHTML) || (l.innerHTML = h && h.__html || ""));
            }
            if (k$1(l, p, y, r, e), h) u.__k = [];
            else if (_ = u.props.children, H$1(l, Array.isArray(_) ? _ : [_], u, i, t, r && "foreignObject" !== d, o, f, o ? o[0] : i.__k && A(i, 0), e), null != o)
                for (_ = o.length; _--;) null != o[_] && v$1(o[_]);
            e || ("value" in p && void 0 !== (_ = p.value) && (_ !== l.value || "progress" === d && !_ || "option" === d && _ !== y.value) && g$2(l, "value", _, y.value, !1), "checked" in p && void 0 !== (_ = p.checked) && _ !== l.checked && g$2(l, "checked", _, y.checked, !1));
        }
        return l
    }

    function S(n, u, i) {
        try {
            "function" == typeof n ? n(u) : n.current = u;
        } catch (n) {
            l$1.__e(n, i);
        }
    }

    function q(n, u, i) {
        var t, r;
        if (l$1.unmount && l$1.unmount(n), (t = n.ref) && (t.current && t.current !== n.__e || S(t, null, u)), null != (t = n.__c)) {
            if (t.componentWillUnmount) try {
                t.componentWillUnmount();
            } catch (n) {
                l$1.__e(n, u);
            }
            t.base = t.__P = null, n.__c = void 0;
        }
        if (t = n.__k)
            for (r = 0; r < t.length; r++) t[r] && q(t[r], u, i || "function" != typeof n.type);
        i || null == n.__e || v$1(n.__e), n.__ = n.__e = n.__d = void 0;
    }

    function B$1(n, l, u) {
        return this.constructor(n, u)
    }

    function D$1(u, i, t) {
        var r, o, f;
        l$1.__ && l$1.__(u, i), o = (r = "function" == typeof t) ? null : t && t.__k || i.__k, f = [], M(i, u = (!r && t || i).__k = y(_, null, [u]), o || c$1, c$1, void 0 !== i.ownerSVGElement, !r && t ? [t] : o ? null : i.firstChild ? n.call(i.childNodes) : null, f, !r && t ? t : o ? o.__e : i.firstChild, r), N(f, u);
    }

    function E(n, l) {
        D$1(n, l, E);
    }

    function F$1(l, u, i) {
        var t, r, o, f = h({}, l.props);
        for (o in u) "key" == o ? t = u[o] : "ref" == o ? r = u[o] : f[o] = u[o];
        return arguments.length > 2 && (f.children = arguments.length > 3 ? n.call(arguments, 2) : i), p(l.type, f, t || l.key, r || l.ref, null)
    }

    function G$1(n, l) {
        var u = {
            __c: l = "__cC" + e$1++,
            __: n,
            Consumer: function(n, l) {
                return n.children(l)
            },
            Provider: function(n) {
                var u, i;
                return this.getChildContext || (u = [], (i = {})[l] = this, this.getChildContext = function() {
                    return i
                }, this.shouldComponentUpdate = function(n) {
                    this.props.value !== n.value && u.some(function(n) {
                        n.__e = !0, T$1(n);
                    });
                }, this.sub = function(n) {
                    u.push(n);
                    var l = n.componentWillUnmount;
                    n.componentWillUnmount = function() {
                        u.splice(u.indexOf(n), 1), l && l.call(n);
                    };
                }), n.children
            }
        };
        return u.Provider.__ = u.Consumer.contextType = u
    }
    n = s.slice, l$1 = {
        __e: function(n, l, u, i) {
            for (var t, r, o; l = l.__;)
                if ((t = l.__c) && !t.__) try {
                    if ((r = t.constructor) && null != r.getDerivedStateFromError && (t.setState(r.getDerivedStateFromError(n)), o = t.__d), null != t.componentDidCatch && (t.componentDidCatch(n, i || {}), o = t.__d), o) return t.__E = t
                } catch (l) {
                    n = l;
                }
            throw n
        }
    }, u$1 = 0, i$1 = function(n) {
        return null != n && void 0 === n.constructor
    }, t = !1, x$1.prototype.setState = function(n, l) {
        var u;
        u = null != this.__s && this.__s !== this.state ? this.__s : this.__s = h({}, this.state), "function" == typeof n && (n = n(h({}, u), this.props)), n && h(u, n), null != n && this.__v && (l && this._sb.push(l), T$1(this));
    }, x$1.prototype.forceUpdate = function(n) {
        this.__v && (this.__e = !0, n && this.__h.push(n), T$1(this));
    }, x$1.prototype.render = _, r$1 = [], f$1 = "function" == typeof Promise ? Promise.prototype.then.bind(Promise.resolve()) : setTimeout, $$1.__r = 0, e$1 = 0;

    var r, u, i, f = [],
        c = [],
        e = l$1.__b,
        a = l$1.__r,
        v = l$1.diffed,
        l = l$1.__c,
        m = l$1.unmount;

    function b() {
        for (var t; t = f.shift();)
            if (t.__P && t.__H) try {
                t.__H.__h.forEach(k), t.__H.__h.forEach(w$1), t.__H.__h = [];
            } catch (r) {
                t.__H.__h = [], l$1.__e(r, t.__v);
            }
    }
    l$1.__b = function(n) {
        r = null, e && e(n);
    }, l$1.__r = function(n) {
        a && a(n);
        var i = (r = n.__c).__H;
        i && (u === r ? (i.__h = [], r.__h = [], i.__.forEach(function(n) {
            n.__N && (n.__ = n.__N), n.__V = c, n.__N = n.i = void 0;
        })) : (i.__h.forEach(k), i.__h.forEach(w$1), i.__h = [])), u = r;
    }, l$1.diffed = function(t) {
        v && v(t);
        var o = t.__c;
        o && o.__H && (o.__H.__h.length && (1 !== f.push(o) && i === l$1.requestAnimationFrame || ((i = l$1.requestAnimationFrame) || j$1)(b)), o.__H.__.forEach(function(n) {
            n.i && (n.__H = n.i), n.__V !== c && (n.__ = n.__V), n.i = void 0, n.__V = c;
        })), u = r = null;
    }, l$1.__c = function(t, r) {
        r.some(function(t) {
            try {
                t.__h.forEach(k), t.__h = t.__h.filter(function(n) {
                    return !n.__ || w$1(n)
                });
            } catch (u) {
                r.some(function(n) {
                    n.__h && (n.__h = []);
                }), r = [], l$1.__e(u, t.__v);
            }
        }), l && l(t, r);
    }, l$1.unmount = function(t) {
        m && m(t);
        var r, u = t.__c;
        u && u.__H && (u.__H.__.forEach(function(n) {
            try {
                k(n);
            } catch (n) {
                r = n;
            }
        }), u.__H = void 0, r && l$1.__e(r, u.__v));
    };
    var g$1 = "function" == typeof requestAnimationFrame;

    function j$1(n) {
        var t, r = function() {
                clearTimeout(u), g$1 && cancelAnimationFrame(t), setTimeout(n);
            },
            u = setTimeout(r, 100);
        g$1 && (t = requestAnimationFrame(r));
    }

    function k(n) {
        var t = r,
            u = n.__c;
        "function" == typeof u && (n.__c = void 0, u()), r = t;
    }

    function w$1(n) {
        var t = r;
        n.__c = n.__(), r = t;
    }

    function g(n, t) {
        for (var e in t) n[e] = t[e];
        return n
    }

    function C(n, t) {
        for (var e in n)
            if ("__source" !== e && !(e in t)) return !0;
        for (var r in t)
            if ("__source" !== r && n[r] !== t[r]) return !0;
        return !1
    }

    function w(n) {
        this.props = n;
    }(w.prototype = new x$1).isPureReactComponent = !0, w.prototype.shouldComponentUpdate = function(n, t) {
        return C(this.props, n) || C(this.state, t)
    };
    var x = l$1.__b;
    l$1.__b = function(n) {
        n.type && n.type.__f && n.ref && (n.props.ref = n.ref, n.ref = null), x && x(n);
    };
    var T = l$1.__e;
    l$1.__e = function(n, t, e, r) {
        if (n.then)
            for (var u, o = t; o = o.__;)
                if ((u = o.__c) && u.__c) return null == t.__e && (t.__e = e.__e, t.__k = e.__k), u.__c(n, t);
        T(n, t, e, r);
    };
    var I = l$1.unmount;

    function L(n, t, e) {
        return n && (n.__c && n.__c.__H && (n.__c.__H.__.forEach(function(n) {
            "function" == typeof n.__c && n.__c();
        }), n.__c.__H = null), null != (n = g({}, n)).__c && (n.__c.__P === e && (n.__c.__P = t), n.__c = null), n.__k = n.__k && n.__k.map(function(n) {
            return L(n, t, e)
        })), n
    }

    function U(n, t, e) {
        return n && (n.__v = null, n.__k = n.__k && n.__k.map(function(n) {
            return U(n, t, e)
        }), n.__c && n.__c.__P === t && (n.__e && e.insertBefore(n.__e, n.__d), n.__c.__e = !0, n.__c.__P = e)), n
    }

    function D() {
        this.__u = 0, this.t = null, this.__b = null;
    }

    function F(n) {
        var t = n.__.__c;
        return t && t.__a && t.__a(n)
    }

    function V() {
        this.u = null, this.o = null;
    }
    l$1.unmount = function(n) {
        var t = n.__c;
        t && t.__R && t.__R(), t && !0 === n.__h && (n.type = null), I && I(n);
    }, (D.prototype = new x$1).__c = function(n, t) {
        var e = t.__c,
            r = this;
        null == r.t && (r.t = []), r.t.push(e);
        var u = F(r.__v),
            o = !1,
            i = function() {
                o || (o = !0, e.__R = null, u ? u(l) : l());
            };
        e.__R = i;
        var l = function() {
                if (!--r.__u) {
                    if (r.state.__a) {
                        var n = r.state.__a;
                        r.__v.__k[0] = U(n, n.__c.__P, n.__c.__O);
                    }
                    var t;
                    for (r.setState({
                            __a: r.__b = null
                        }); t = r.t.pop();) t.forceUpdate();
                }
            },
            c = !0 === t.__h;
        r.__u++ || c || r.setState({
            __a: r.__b = r.__v.__k[0]
        }), n.then(i, i);
    }, D.prototype.componentWillUnmount = function() {
        this.t = [];
    }, D.prototype.render = function(n, e) {
        if (this.__b) {
            if (this.__v.__k) {
                var r = document.createElement("div"),
                    o = this.__v.__k[0].__c;
                this.__v.__k[0] = L(this.__b, r, o.__O = o.__P);
            }
            this.__b = null;
        }
        var i = e.__a && y(_, null, n.fallback);
        return i && (i.__h = null), [y(_, null, e.__a ? null : n.children), i]
    };
    var W = function(n, t, e) {
        if (++e[1] === e[0] && n.o.delete(t), n.props.revealOrder && ("t" !== n.props.revealOrder[0] || !n.o.size))
            for (e = n.u; e;) {
                for (; e.length > 3;) e.pop()();
                if (e[1] < e[0]) break;
                n.u = e = e[2];
            }
    };

    function P(n) {
        return this.getChildContext = function() {
            return n.context
        }, n.children
    }

    function $(n) {
        var e = this,
            r = n.i;
        e.componentWillUnmount = function() {
            D$1(null, e.l), e.l = null, e.i = null;
        }, e.i && e.i !== r && e.componentWillUnmount(), n.__v ? (e.l || (e.i = r, e.l = {
            nodeType: 1,
            parentNode: r,
            childNodes: [],
            appendChild: function(n) {
                this.childNodes.push(n), e.i.appendChild(n);
            },
            insertBefore: function(n, t) {
                this.childNodes.push(n), e.i.appendChild(n);
            },
            removeChild: function(n) {
                this.childNodes.splice(this.childNodes.indexOf(n) >>> 1, 1), e.i.removeChild(n);
            }
        }), D$1(y(P, {
            context: e.context
        }, n.__v), e.l)) : e.l && e.componentWillUnmount();
    }

    function j(n, e) {
        var r = y($, {
            __v: n,
            i: e
        });
        return r.containerInfo = e, r
    }(V.prototype = new x$1).__a = function(n) {
        var t = this,
            e = F(t.__v),
            r = t.o.get(n);
        return r[0]++,
            function(u) {
                var o = function() {
                    t.props.revealOrder ? (r.push(u), W(t, n, r)) : u();
                };
                e ? e(o) : o();
            }
    }, V.prototype.render = function(n) {
        this.u = null, this.o = new Map;
        var t = j$2(n.children);
        n.revealOrder && "b" === n.revealOrder[0] && t.reverse();
        for (var e = t.length; e--;) this.o.set(t[e], this.u = [1, 0, this.u]);
        return n.children
    }, V.prototype.componentDidUpdate = V.prototype.componentDidMount = function() {
        var n = this;
        this.o.forEach(function(t, e) {
            W(n, e, t);
        });
    };
    var z = "undefined" != typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103,
        B = /^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|image|letter|lighting|marker(?!H|W|U)|overline|paint|pointer|shape|stop|strikethrough|stroke|text(?!L)|transform|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/,
        H = "undefined" != typeof document,
        Z = function(n) {
            return ("undefined" != typeof Symbol && "symbol" == typeof Symbol() ? /fil|che|rad/i : /fil|che|ra/i).test(n)
        };
    x$1.prototype.isReactComponent = {}, ["componentWillMount", "componentWillReceiveProps", "componentWillUpdate"].forEach(function(t) {
        Object.defineProperty(x$1.prototype, t, {
            configurable: !0,
            get: function() {
                return this["UNSAFE_" + t]
            },
            set: function(n) {
                Object.defineProperty(this, t, {
                    configurable: !0,
                    writable: !0,
                    value: n
                });
            }
        });
    });
    var G = l$1.event;

    function J() {}

    function K() {
        return this.cancelBubble
    }

    function Q() {
        return this.defaultPrevented
    }
    l$1.event = function(n) {
        return G && (n = G(n)), n.persist = J, n.isPropagationStopped = K, n.isDefaultPrevented = Q, n.nativeEvent = n
    };
    var nn = {
            configurable: !0,
            get: function() {
                return this.class
            }
        },
        tn = l$1.vnode;
    l$1.vnode = function(n) {
        var t = n.type,
            e = n.props,
            u = e;
        if ("string" == typeof t) {
            var o = -1 === t.indexOf("-");
            for (var i in u = {}, e) {
                var l = e[i];
                H && "children" === i && "noscript" === t || "value" === i && "defaultValue" in e && null == l || ("defaultValue" === i && "value" in e && null == e.value ? i = "value" : "download" === i && !0 === l ? l = "" : /ondoubleclick/i.test(i) ? i = "ondblclick" : /^onchange(textarea|input)/i.test(i + t) && !Z(e.type) ? i = "oninput" : /^onfocus$/i.test(i) ? i = "onfocusin" : /^onblur$/i.test(i) ? i = "onfocusout" : /^on(Ani|Tra|Tou|BeforeInp|Compo)/.test(i) ? i = i.toLowerCase() : o && B.test(i) ? i = i.replace(/[A-Z0-9]/g, "-$&").toLowerCase() : null === l && (l = void 0), /^oninput$/i.test(i) && (i = i.toLowerCase(), u[i] && (i = "oninputCapture")), u[i] = l);
            }
            "select" == t && u.multiple && Array.isArray(u.value) && (u.value = j$2(e.children).forEach(function(n) {
                n.props.selected = -1 != u.value.indexOf(n.props.value);
            })), "select" == t && null != u.defaultValue && (u.value = j$2(e.children).forEach(function(n) {
                n.props.selected = u.multiple ? -1 != u.defaultValue.indexOf(n.props.value) : u.defaultValue == n.props.value;
            })), n.props = u, e.class != e.className && (nn.enumerable = "className" in e, null != e.className && (u.class = e.className), Object.defineProperty(u, "className", nn));
        }
        n.$$typeof = z, tn && tn(n);
    };
    var en = l$1.__r;
    l$1.__r = function(n) {
        en && en(n), n.__c;
    };

    const styleTexts = [];
    const styleEls = new Map();

    function injectStyles(styleText) {
        styleTexts.push(styleText);
        styleEls.forEach((styleEl) => {
            appendStylesTo(styleEl, styleText);
        });
    }

    function ensureElHasStyles(el) {
        if (el.isConnected && // sometimes true if SSR system simulates DOM
            el.getRootNode // sometimes undefined if SSR system simulates DOM
        ) {
            registerStylesRoot(el.getRootNode());
        }
    }

    function registerStylesRoot(rootNode) {
        let styleEl = styleEls.get(rootNode);
        if (!styleEl || !styleEl.isConnected) {
            styleEl = rootNode.querySelector('style[data-fullcalendar]');
            if (!styleEl) {
                styleEl = document.createElement('style');
                styleEl.setAttribute('data-fullcalendar', '');
                const nonce = getNonceValue();
                if (nonce) {
                    styleEl.nonce = nonce;
                }
                const parentEl = rootNode === document ? document.head : rootNode;
                const insertBefore = rootNode === document ?
                    parentEl.querySelector('script,link[rel=stylesheet],link[as=style],style') :
                    parentEl.firstChild;
                parentEl.insertBefore(styleEl, insertBefore);
            }
            styleEls.set(rootNode, styleEl);
            hydrateStylesRoot(styleEl);
        }
    }

    function hydrateStylesRoot(styleEl) {
        for (const styleText of styleTexts) {
            appendStylesTo(styleEl, styleText);
        }
    }

    function appendStylesTo(styleEl, styleText) {
        const {
            sheet
        } = styleEl;
        const ruleCnt = sheet.cssRules.length;
        styleText.split('}').forEach((styleStr, i) => {
            styleStr = styleStr.trim();
            if (styleStr) {
                sheet.insertRule(styleStr + '}', ruleCnt + i);
            }
        });
    }
    // nonce
    // -------------------------------------------------------------------------------------------------
    let queriedNonceValue;

    function getNonceValue() {
        if (queriedNonceValue === undefined) {
            queriedNonceValue = queryNonceValue();
        }
        return queriedNonceValue;
    }
    /*
    TODO: discourage meta tag and instead put nonce attribute on placeholder <style> tag
    */
    function queryNonceValue() {
        const metaWithNonce = document.querySelector('meta[name="csp-nonce"]');
        if (metaWithNonce && metaWithNonce.hasAttribute('content')) {
            return metaWithNonce.getAttribute('content');
        }
        const elWithNonce = document.querySelector('script[nonce]');
        if (elWithNonce) {
            return elWithNonce.nonce || '';
        }
        return '';
    }
    // main
    // -------------------------------------------------------------------------------------------------
    if (typeof document !== 'undefined') {
        registerStylesRoot(document);
    }

    var css_248z$4 = ":root{--fc-small-font-size:.85em;--fc-page-bg-color:#fff;--fc-neutral-bg-color:hsla(0,0%,82%,.3);--fc-neutral-text-color:grey;--fc-border-color:#ddd;--fc-button-text-color:#fff;--fc-button-bg-color:#2c3e50;--fc-button-border-color:#2c3e50;--fc-button-hover-bg-color:#1e2b37;--fc-button-hover-border-color:#1a252f;--fc-button-active-bg-color:#1a252f;--fc-button-active-border-color:#151e27;--fc-event-bg-color:#3788d8;--fc-event-border-color:#3788d8;--fc-event-text-color:#fff;--fc-event-selected-overlay-color:rgba(0,0,0,.25);--fc-more-link-bg-color:#d0d0d0;--fc-more-link-text-color:inherit;--fc-event-resizer-thickness:8px;--fc-event-resizer-dot-total-width:8px;--fc-event-resizer-dot-border-width:1px;--fc-non-business-color:hsla(0,0%,84%,.3);--fc-bg-event-color:#8fdf82;--fc-bg-event-opacity:0.3;--fc-highlight-color:rgba(188,232,241,.3);--fc-today-bg-color:rgba(255,220,40,.15);--fc-now-indicator-color:red}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc{display:flex;flex-direction:column;font-size:1em}.fc,.fc *,.fc :after,.fc :before{box-sizing:border-box}.fc table{border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{padding:0;vertical-align:top}.fc a[data-navlink]{cursor:pointer}.fc a[data-navlink]:hover{text-decoration:underline}.fc-direction-ltr{direction:ltr;text-align:left}.fc-direction-rtl{direction:rtl;text-align:right}.fc-theme-standard td,.fc-theme-standard th{border:1px solid var(--fc-border-color)}.fc-liquid-hack td,.fc-liquid-hack th{position:relative}@font-face{font-family:fcicons;font-style:normal;font-weight:400;src:url(\"data:application/x-font-ttf;charset=utf-8;base64,AAEAAAALAIAAAwAwT1MvMg8SBfAAAAC8AAAAYGNtYXAXVtKNAAABHAAAAFRnYXNwAAAAEAAAAXAAAAAIZ2x5ZgYydxIAAAF4AAAFNGhlYWQUJ7cIAAAGrAAAADZoaGVhB20DzAAABuQAAAAkaG10eCIABhQAAAcIAAAALGxvY2ED4AU6AAAHNAAAABhtYXhwAA8AjAAAB0wAAAAgbmFtZXsr690AAAdsAAABhnBvc3QAAwAAAAAI9AAAACAAAwPAAZAABQAAApkCzAAAAI8CmQLMAAAB6wAzAQkAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAAAAAAAAAAABAAADpBgPA/8AAQAPAAEAAAAABAAAAAAAAAAAAAAAgAAAAAAADAAAAAwAAABwAAQADAAAAHAADAAEAAAAcAAQAOAAAAAoACAACAAIAAQAg6Qb//f//AAAAAAAg6QD//f//AAH/4xcEAAMAAQAAAAAAAAAAAAAAAQAB//8ADwABAAAAAAAAAAAAAgAANzkBAAAAAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAWIAjQKeAskAEwAAJSc3NjQnJiIHAQYUFwEWMjc2NCcCnuLiDQ0MJAz/AA0NAQAMJAwNDcni4gwjDQwM/wANIwz/AA0NDCMNAAAAAQFiAI0CngLJABMAACUBNjQnASYiBwYUHwEHBhQXFjI3AZ4BAA0N/wAMJAwNDeLiDQ0MJAyNAQAMIw0BAAwMDSMM4uINIwwNDQAAAAIA4gC3Ax4CngATACcAACUnNzY0JyYiDwEGFB8BFjI3NjQnISc3NjQnJiIPAQYUHwEWMjc2NCcB87e3DQ0MIw3VDQ3VDSMMDQ0BK7e3DQ0MJAzVDQ3VDCQMDQ3zuLcMJAwNDdUNIwzWDAwNIwy4twwkDA0N1Q0jDNYMDA0jDAAAAgDiALcDHgKeABMAJwAAJTc2NC8BJiIHBhQfAQcGFBcWMjchNzY0LwEmIgcGFB8BBwYUFxYyNwJJ1Q0N1Q0jDA0Nt7cNDQwjDf7V1Q0N1QwkDA0Nt7cNDQwkDLfWDCMN1Q0NDCQMt7gMIw0MDNYMIw3VDQ0MJAy3uAwjDQwMAAADAFUAAAOrA1UAMwBoAHcAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMhMjY1NCYjISIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAAVYRGRkR/qoRGRkRA1UFBAUOCQkVDAsZDf2rDRkLDBUJCA4FBQUFBQUOCQgVDAsZDQJVDRkLDBUJCQ4FBAVVAgECBQMCBwQECAX9qwQJAwQHAwMFAQICAgIBBQMDBwQDCQQCVQUIBAQHAgMFAgEC/oAZEhEZGRESGQAAAAADAFUAAAOrA1UAMwBoAIkAABMiBgcOAQcOAQcOARURFBYXHgEXHgEXHgEzITI2Nz4BNz4BNz4BNRE0JicuAScuAScuASMFITIWFx4BFx4BFx4BFREUBgcOAQcOAQcOASMhIiYnLgEnLgEnLgE1ETQ2Nz4BNz4BNz4BMxMzFRQWMzI2PQEzMjY1NCYrATU0JiMiBh0BIyIGFRQWM9UNGAwLFQkJDgUFBQUFBQ4JCRULDBgNAlYNGAwLFQkJDgUFBQUFBQ4JCRULDBgN/aoCVgQIBAQHAwMFAQIBAQIBBQMDBwQECAT9qgQIBAQHAwMFAQIBAQIBBQMDBwQECASAgBkSEhmAERkZEYAZEhIZgBEZGREDVQUEBQ4JCRUMCxkN/asNGQsMFQkIDgUFBQUFBQ4JCBUMCxkNAlUNGQsMFQkJDgUEBVUCAQIFAwIHBAQIBf2rBAkDBAcDAwUBAgICAgEFAwMHBAMJBAJVBQgEBAcCAwUCAQL+gIASGRkSgBkSERmAEhkZEoAZERIZAAABAOIAjQMeAskAIAAAExcHBhQXFjI/ARcWMjc2NC8BNzY0JyYiDwEnJiIHBhQX4uLiDQ0MJAzi4gwkDA0N4uINDQwkDOLiDCQMDQ0CjeLiDSMMDQ3h4Q0NDCMN4uIMIw0MDOLiDAwNIwwAAAABAAAAAQAAa5n0y18PPPUACwQAAAAAANivOVsAAAAA2K85WwAAAAADqwNVAAAACAACAAAAAAAAAAEAAAPA/8AAAAQAAAAAAAOrAAEAAAAAAAAAAAAAAAAAAAALBAAAAAAAAAAAAAAAAgAAAAQAAWIEAAFiBAAA4gQAAOIEAABVBAAAVQQAAOIAAAAAAAoAFAAeAEQAagCqAOoBngJkApoAAQAAAAsAigADAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAA4ArgABAAAAAAABAAcAAAABAAAAAAACAAcAYAABAAAAAAADAAcANgABAAAAAAAEAAcAdQABAAAAAAAFAAsAFQABAAAAAAAGAAcASwABAAAAAAAKABoAigADAAEECQABAA4ABwADAAEECQACAA4AZwADAAEECQADAA4APQADAAEECQAEAA4AfAADAAEECQAFABYAIAADAAEECQAGAA4AUgADAAEECQAKADQApGZjaWNvbnMAZgBjAGkAYwBvAG4Ac1ZlcnNpb24gMS4wAFYAZQByAHMAaQBvAG4AIAAxAC4AMGZjaWNvbnMAZgBjAGkAYwBvAG4Ac2ZjaWNvbnMAZgBjAGkAYwBvAG4Ac1JlZ3VsYXIAUgBlAGcAdQBsAGEAcmZjaWNvbnMAZgBjAGkAYwBvAG4Ac0ZvbnQgZ2VuZXJhdGVkIGJ5IEljb01vb24uAEYAbwBuAHQAIABnAGUAbgBlAHIAYQB0AGUAZAAgAGIAeQAgAEkAYwBvAE0AbwBvAG4ALgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\") format(\"truetype\")}.fc-icon{speak:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font-family:fcicons!important;font-style:normal;font-variant:normal;font-weight:400;height:1em;line-height:1;text-align:center;text-transform:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:1em}.fc-icon-chevron-left:before{content:\"\\e900\"}.fc-icon-chevron-right:before{content:\"\\e901\"}.fc-icon-chevrons-left:before{content:\"\\e902\"}.fc-icon-chevrons-right:before{content:\"\\e903\"}.fc-icon-minus-square:before{content:\"\\e904\"}.fc-icon-plus-square:before{content:\"\\e905\"}.fc-icon-x:before{content:\"\\e906\"}.fc .fc-button{border-radius:0;font-family:inherit;font-size:inherit;line-height:inherit;margin:0;overflow:visible;text-transform:none}.fc .fc-button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}.fc .fc-button{-webkit-appearance:button}.fc .fc-button:not(:disabled){cursor:pointer}.fc .fc-button{background-color:transparent;border:1px solid transparent;border-radius:.25em;display:inline-block;font-size:1em;font-weight:400;line-height:1.5;padding:.4em .65em;text-align:center;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle}.fc .fc-button:hover{text-decoration:none}.fc .fc-button:focus{box-shadow:0 0 0 .2rem rgba(44,62,80,.25);outline:0}.fc .fc-button:disabled{opacity:.65}.fc .fc-button-primary{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:hover{background-color:var(--fc-button-hover-bg-color);border-color:var(--fc-button-hover-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:disabled{background-color:var(--fc-button-bg-color);border-color:var(--fc-button-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button-primary:not(:disabled).fc-button-active,.fc .fc-button-primary:not(:disabled):active{background-color:var(--fc-button-active-bg-color);border-color:var(--fc-button-active-border-color);color:var(--fc-button-text-color)}.fc .fc-button-primary:not(:disabled).fc-button-active:focus,.fc .fc-button-primary:not(:disabled):active:focus{box-shadow:0 0 0 .2rem rgba(76,91,106,.5)}.fc .fc-button .fc-icon{font-size:1.5em;vertical-align:middle}.fc .fc-button-group{display:inline-flex;position:relative;vertical-align:middle}.fc .fc-button-group>.fc-button{flex:1 1 auto;position:relative}.fc .fc-button-group>.fc-button.fc-button-active,.fc .fc-button-group>.fc-button:active,.fc .fc-button-group>.fc-button:focus,.fc .fc-button-group>.fc-button:hover{z-index:1}.fc-direction-ltr .fc-button-group>.fc-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0;margin-left:-1px}.fc-direction-ltr .fc-button-group>.fc-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.fc-direction-rtl .fc-button-group>.fc-button:not(:first-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.fc-direction-rtl .fc-button-group>.fc-button:not(:last-child){border-bottom-left-radius:0;border-top-left-radius:0}.fc .fc-toolbar{align-items:center;display:flex;justify-content:space-between}.fc .fc-toolbar.fc-header-toolbar{margin-bottom:1.5em}.fc .fc-toolbar.fc-footer-toolbar{margin-top:1.5em}.fc .fc-toolbar-title{font-size:1.75em;margin:0}.fc-direction-ltr .fc-toolbar>*>:not(:first-child){margin-left:.75em}.fc-direction-rtl .fc-toolbar>*>:not(:first-child){margin-right:.75em}.fc-direction-rtl .fc-toolbar-ltr{flex-direction:row-reverse}.fc .fc-scroller{-webkit-overflow-scrolling:touch;position:relative}.fc .fc-scroller-liquid{height:100%}.fc .fc-scroller-liquid-absolute{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-scroller-harness{direction:ltr;overflow:hidden;position:relative}.fc .fc-scroller-harness-liquid{height:100%}.fc-direction-rtl .fc-scroller-harness>.fc-scroller{direction:rtl}.fc-theme-standard .fc-scrollgrid{border:1px solid var(--fc-border-color)}.fc .fc-scrollgrid,.fc .fc-scrollgrid table{table-layout:fixed;width:100%}.fc .fc-scrollgrid table{border-left-style:hidden;border-right-style:hidden;border-top-style:hidden}.fc .fc-scrollgrid{border-bottom-width:0;border-collapse:separate;border-right-width:0}.fc .fc-scrollgrid-liquid{height:100%}.fc .fc-scrollgrid-section,.fc .fc-scrollgrid-section table,.fc .fc-scrollgrid-section>td{height:1px}.fc .fc-scrollgrid-section-liquid>td{height:100%}.fc .fc-scrollgrid-section>*{border-left-width:0;border-top-width:0}.fc .fc-scrollgrid-section-footer>*,.fc .fc-scrollgrid-section-header>*{border-bottom-width:0}.fc .fc-scrollgrid-section-body table,.fc .fc-scrollgrid-section-footer table{border-bottom-style:hidden}.fc .fc-scrollgrid-section-sticky>*{background:var(--fc-page-bg-color);position:sticky;z-index:3}.fc .fc-scrollgrid-section-header.fc-scrollgrid-section-sticky>*{top:0}.fc .fc-scrollgrid-section-footer.fc-scrollgrid-section-sticky>*{bottom:0}.fc .fc-scrollgrid-sticky-shim{height:1px;margin-bottom:-1px}.fc-sticky{position:sticky}.fc .fc-view-harness{flex-grow:1;position:relative}.fc .fc-view-harness-active>.fc-view{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-col-header-cell-cushion{display:inline-block;padding:2px 4px}.fc .fc-bg-event,.fc .fc-highlight,.fc .fc-non-business{bottom:0;left:0;position:absolute;right:0;top:0}.fc .fc-non-business{background:var(--fc-non-business-color)}.fc .fc-bg-event{background:var(--fc-bg-event-color);opacity:var(--fc-bg-event-opacity)}.fc .fc-bg-event .fc-event-title{font-size:var(--fc-small-font-size);font-style:italic;margin:.5em}.fc .fc-highlight{background:var(--fc-highlight-color)}.fc .fc-cell-shaded,.fc .fc-day-disabled{background:var(--fc-neutral-bg-color)}a.fc-event,a.fc-event:hover{text-decoration:none}.fc-event.fc-event-draggable,.fc-event[href]{cursor:pointer}.fc-event .fc-event-main{position:relative;z-index:2}.fc-event-dragging:not(.fc-event-selected){opacity:.75}.fc-event-dragging.fc-event-selected{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-event .fc-event-resizer{display:none;position:absolute;z-index:4}.fc-event-selected .fc-event-resizer,.fc-event:hover .fc-event-resizer{display:block}.fc-event-selected .fc-event-resizer{background:var(--fc-page-bg-color);border-color:inherit;border-radius:calc(var(--fc-event-resizer-dot-total-width)/2);border-style:solid;border-width:var(--fc-event-resizer-dot-border-width);height:var(--fc-event-resizer-dot-total-width);width:var(--fc-event-resizer-dot-total-width)}.fc-event-selected .fc-event-resizer:before{bottom:-20px;content:\"\";left:-20px;position:absolute;right:-20px;top:-20px}.fc-event-selected,.fc-event:focus{box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event-selected:before,.fc-event:focus:before{bottom:0;content:\"\";left:0;position:absolute;right:0;top:0;z-index:3}.fc-event-selected:after,.fc-event:focus:after{background:var(--fc-event-selected-overlay-color);bottom:-1px;content:\"\";left:-1px;position:absolute;right:-1px;top:-1px;z-index:1}.fc-h-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-h-event .fc-event-main{color:var(--fc-event-text-color)}.fc-h-event .fc-event-main-frame{display:flex}.fc-h-event .fc-event-time{max-width:100%;overflow:hidden}.fc-h-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-width:0}.fc-h-event .fc-event-title{display:inline-block;left:0;max-width:100%;overflow:hidden;right:0;vertical-align:top}.fc-h-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-start),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-end){border-bottom-left-radius:0;border-left-width:0;border-top-left-radius:0}.fc-direction-ltr .fc-daygrid-block-event:not(.fc-event-end),.fc-direction-rtl .fc-daygrid-block-event:not(.fc-event-start){border-bottom-right-radius:0;border-right-width:0;border-top-right-radius:0}.fc-h-event:not(.fc-event-selected) .fc-event-resizer{bottom:0;top:0;width:var(--fc-event-resizer-thickness)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end{cursor:w-resize;left:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-direction-ltr .fc-h-event:not(.fc-event-selected) .fc-event-resizer-end,.fc-direction-rtl .fc-h-event:not(.fc-event-selected) .fc-event-resizer-start{cursor:e-resize;right:calc(var(--fc-event-resizer-thickness)*-.5)}.fc-h-event.fc-event-selected .fc-event-resizer{margin-top:calc(var(--fc-event-resizer-dot-total-width)*-.5);top:50%}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-start,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-end{left:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc-direction-ltr .fc-h-event.fc-event-selected .fc-event-resizer-end,.fc-direction-rtl .fc-h-event.fc-event-selected .fc-event-resizer-start{right:calc(var(--fc-event-resizer-dot-total-width)*-.5)}.fc .fc-popover{box-shadow:0 2px 6px rgba(0,0,0,.15);position:absolute;z-index:9999}.fc .fc-popover-header{align-items:center;display:flex;flex-direction:row;justify-content:space-between;padding:3px 4px}.fc .fc-popover-title{margin:0 2px}.fc .fc-popover-close{cursor:pointer;font-size:1.1em;opacity:.65}.fc-theme-standard .fc-popover{background:var(--fc-page-bg-color);border:1px solid var(--fc-border-color)}.fc-theme-standard .fc-popover-header{background:var(--fc-neutral-bg-color)}";
    injectStyles(css_248z$4);

    class DelayedRunner {
        constructor(drainedOption) {
            this.drainedOption = drainedOption;
            this.isRunning = false;
            this.isDirty = false;
            this.pauseDepths = {};
            this.timeoutId = 0;
        }
        request(delay) {
            this.isDirty = true;
            if (!this.isPaused()) {
                this.clearTimeout();
                if (delay == null) {
                    this.tryDrain();
                } else {
                    this.timeoutId = setTimeout( // NOT OPTIMAL! TODO: look at debounce
                        this.tryDrain.bind(this), delay);
                }
            }
        }
        pause(scope = '') {
            let {
                pauseDepths
            } = this;
            pauseDepths[scope] = (pauseDepths[scope] || 0) + 1;
            this.clearTimeout();
        }
        resume(scope = '', force) {
            let {
                pauseDepths
            } = this;
            if (scope in pauseDepths) {
                if (force) {
                    delete pauseDepths[scope];
                } else {
                    pauseDepths[scope] -= 1;
                    let depth = pauseDepths[scope];
                    if (depth <= 0) {
                        delete pauseDepths[scope];
                    }
                }
                this.tryDrain();
            }
        }
        isPaused() {
            return Object.keys(this.pauseDepths).length;
        }
        tryDrain() {
            if (!this.isRunning && !this.isPaused()) {
                this.isRunning = true;
                while (this.isDirty) {
                    this.isDirty = false;
                    this.drained(); // might set isDirty to true again
                }
                this.isRunning = false;
            }
        }
        clear() {
            this.clearTimeout();
            this.isDirty = false;
            this.pauseDepths = {};
        }
        clearTimeout() {
            if (this.timeoutId) {
                clearTimeout(this.timeoutId);
                this.timeoutId = 0;
            }
        }
        drained() {
            if (this.drainedOption) {
                this.drainedOption();
            }
        }
    }

    function removeElement(el) {
        if (el.parentNode) {
            el.parentNode.removeChild(el);
        }
    }
    // Querying
    // ----------------------------------------------------------------------------------------------------------------
    function elementClosest(el, selector) {
        if (el.closest) {
            return el.closest(selector);
            // really bad fallback for IE
            // from https://developer.mozilla.org/en-US/docs/Web/API/Element/closest
        }
        if (!document.documentElement.contains(el)) {
            return null;
        }
        do {
            if (elementMatches(el, selector)) {
                return el;
            }
            el = (el.parentElement || el.parentNode);
        } while (el !== null && el.nodeType === 1);
        return null;
    }

    function elementMatches(el, selector) {
        let method = el.matches || el.matchesSelector || el.msMatchesSelector;
        return method.call(el, selector);
    }
    // accepts multiple subject els
    // returns a real array. good for methods like forEach
    // TODO: accept the document
    function findElements(container, selector) {
        let containers = container instanceof HTMLElement ? [container] : container;
        let allMatches = [];
        for (let i = 0; i < containers.length; i += 1) {
            let matches = containers[i].querySelectorAll(selector);
            for (let j = 0; j < matches.length; j += 1) {
                allMatches.push(matches[j]);
            }
        }
        return allMatches;
    }
    // accepts multiple subject els
    // only queries direct child elements // TODO: rename to findDirectChildren!
    function findDirectChildren(parent, selector) {
        let parents = parent instanceof HTMLElement ? [parent] : parent;
        let allMatches = [];
        for (let i = 0; i < parents.length; i += 1) {
            let childNodes = parents[i].children; // only ever elements
            for (let j = 0; j < childNodes.length; j += 1) {
                let childNode = childNodes[j];
                if (!selector || elementMatches(childNode, selector)) {
                    allMatches.push(childNode);
                }
            }
        }
        return allMatches;
    }
    // Style
    // ----------------------------------------------------------------------------------------------------------------
    const PIXEL_PROP_RE = /(top|left|right|bottom|width|height)$/i;

    function applyStyle(el, props) {
        for (let propName in props) {
            applyStyleProp(el, propName, props[propName]);
        }
    }

    function applyStyleProp(el, name, val) {
        if (val == null) {
            el.style[name] = '';
        } else if (typeof val === 'number' && PIXEL_PROP_RE.test(name)) {
            el.style[name] = `${val}px`;
        } else {
            el.style[name] = val;
        }
    }
    // Event Handling
    // ----------------------------------------------------------------------------------------------------------------
    // if intercepting bubbled events at the document/window/body level,
    // and want to see originating element (the 'target'), use this util instead
    // of `ev.target` because it goes within web-component boundaries.
    function getEventTargetViaRoot(ev) {
        var _a, _b;
        return (_b = (_a = ev.composedPath) === null || _a === void 0 ? void 0 : _a.call(ev)[0]) !== null && _b !== void 0 ? _b : ev.target;
    }
    // Unique ID for DOM attribute
    let guid$1 = 0;

    function getUniqueDomId() {
        guid$1 += 1;
        return 'fc-dom-' + guid$1;
    }

    // Stops a mouse/touch event from doing it's native browser action
    function preventDefault(ev) {
        ev.preventDefault();
    }
    // Event Delegation
    // ----------------------------------------------------------------------------------------------------------------
    function buildDelegationHandler(selector, handler) {
        return (ev) => {
            let matchedChild = elementClosest(ev.target, selector);
            if (matchedChild) {
                handler.call(matchedChild, ev, matchedChild);
            }
        };
    }

    function listenBySelector(container, eventType, selector, handler) {
        let attachedHandler = buildDelegationHandler(selector, handler);
        container.addEventListener(eventType, attachedHandler);
        return () => {
            container.removeEventListener(eventType, attachedHandler);
        };
    }

    function listenToHoverBySelector(container, selector, onMouseEnter, onMouseLeave) {
        let currentMatchedChild;
        return listenBySelector(container, 'mouseover', selector, (mouseOverEv, matchedChild) => {
            if (matchedChild !== currentMatchedChild) {
                currentMatchedChild = matchedChild;
                onMouseEnter(mouseOverEv, matchedChild);
                let realOnMouseLeave = (mouseLeaveEv) => {
                    currentMatchedChild = null;
                    onMouseLeave(mouseLeaveEv, matchedChild);
                    matchedChild.removeEventListener('mouseleave', realOnMouseLeave);
                };
                // listen to the next mouseleave, and then unattach
                matchedChild.addEventListener('mouseleave', realOnMouseLeave);
            }
        });
    }
    // Animation
    // ----------------------------------------------------------------------------------------------------------------
    const transitionEventNames = [
        'webkitTransitionEnd',
        'otransitionend',
        'oTransitionEnd',
        'msTransitionEnd',
        'transitionend',
    ];
    // triggered only when the next single subsequent transition finishes
    function whenTransitionDone(el, callback) {
        let realCallback = (ev) => {
            callback(ev);
            transitionEventNames.forEach((eventName) => {
                el.removeEventListener(eventName, realCallback);
            });
        };
        transitionEventNames.forEach((eventName) => {
            el.addEventListener(eventName, realCallback); // cross-browser way to determine when the transition finishes
        });
    }
    // ARIA workarounds
    // ----------------------------------------------------------------------------------------------------------------
    function createAriaClickAttrs(handler) {
        return Object.assign({
            onClick: handler
        }, createAriaKeyboardAttrs(handler));
    }

    function createAriaKeyboardAttrs(handler) {
        return {
            tabIndex: 0,
            onKeyDown(ev) {
                if (ev.key === 'Enter' || ev.key === ' ') {
                    handler(ev);
                    ev.preventDefault(); // if space, don't scroll down page
                }
            },
        };
    }

    let guidNumber = 0;

    function guid() {
        guidNumber += 1;
        return String(guidNumber);
    }
    /* FullCalendar-specific DOM Utilities
    ----------------------------------------------------------------------------------------------------------------------*/
    // Make the mouse cursor express that an event is not allowed in the current area
    function disableCursor() {
        document.body.classList.add('fc-not-allowed');
    }
    // Returns the mouse cursor to its original look
    function enableCursor() {
        document.body.classList.remove('fc-not-allowed');
    }
    /* Selection
    ----------------------------------------------------------------------------------------------------------------------*/
    function preventSelection(el) {
        el.style.userSelect = 'none';
        el.style.webkitUserSelect = 'none';
        el.addEventListener('selectstart', preventDefault);
    }

    function allowSelection(el) {
        el.style.userSelect = '';
        el.style.webkitUserSelect = '';
        el.removeEventListener('selectstart', preventDefault);
    }
    /* Context Menu
    ----------------------------------------------------------------------------------------------------------------------*/
    function preventContextMenu(el) {
        el.addEventListener('contextmenu', preventDefault);
    }

    function allowContextMenu(el) {
        el.removeEventListener('contextmenu', preventDefault);
    }

    function parseFieldSpecs(input) {
        let specs = [];
        let tokens = [];
        let i;
        let token;
        if (typeof input === 'string') {
            tokens = input.split(/\s*,\s*/);
        } else if (typeof input === 'function') {
            tokens = [input];
        } else if (Array.isArray(input)) {
            tokens = input;
        }
        for (i = 0; i < tokens.length; i += 1) {
            token = tokens[i];
            if (typeof token === 'string') {
                specs.push(token.charAt(0) === '-' ? {
                    field: token.substring(1),
                    order: -1
                } : {
                    field: token,
                    order: 1
                });
            } else if (typeof token === 'function') {
                specs.push({
                    func: token
                });
            }
        }
        return specs;
    }

    function compareByFieldSpecs(obj0, obj1, fieldSpecs) {
        let i;
        let cmp;
        for (i = 0; i < fieldSpecs.length; i += 1) {
            cmp = compareByFieldSpec(obj0, obj1, fieldSpecs[i]);
            if (cmp) {
                return cmp;
            }
        }
        return 0;
    }

    function compareByFieldSpec(obj0, obj1, fieldSpec) {
        if (fieldSpec.func) {
            return fieldSpec.func(obj0, obj1);
        }
        return flexibleCompare(obj0[fieldSpec.field], obj1[fieldSpec.field]) *
            (fieldSpec.order || 1);
    }

    function flexibleCompare(a, b) {
        if (!a && !b) {
            return 0;
        }
        if (b == null) {
            return -1;
        }
        if (a == null) {
            return 1;
        }
        if (typeof a === 'string' || typeof b === 'string') {
            return String(a).localeCompare(String(b));
        }
        return a - b;
    }
    /* String Utilities
    ----------------------------------------------------------------------------------------------------------------------*/
    function padStart(val, len) {
        let s = String(val);
        return '000'.substr(0, len - s.length) + s;
    }

    function formatWithOrdinals(formatter, args, fallbackText) {
        if (typeof formatter === 'function') {
            return formatter(...args);
        }
        if (typeof formatter === 'string') { // non-blank string
            return args.reduce((str, arg, index) => (str.replace('$' + index, arg || '')), formatter);
        }
        return fallbackText;
    }
    /* Number Utilities
    ----------------------------------------------------------------------------------------------------------------------*/
    function compareNumbers(a, b) {
        return a - b;
    }

    function isInt(n) {
        return n % 1 === 0;
    }
    /* FC-specific DOM dimension stuff
    ----------------------------------------------------------------------------------------------------------------------*/
    function computeSmallestCellWidth(cellEl) {
        let allWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-frame');
        let contentWidthEl = cellEl.querySelector('.fc-scrollgrid-shrink-cushion');
        if (!allWidthEl) {
            throw new Error('needs fc-scrollgrid-shrink-frame className'); // TODO: use const
        }
        if (!contentWidthEl) {
            throw new Error('needs fc-scrollgrid-shrink-cushion className');
        }
        return cellEl.getBoundingClientRect().width - allWidthEl.getBoundingClientRect().width + // the cell padding+border
            contentWidthEl.getBoundingClientRect().width;
    }

    const INTERNAL_UNITS = ['years', 'months', 'days', 'milliseconds'];
    const PARSE_RE = /^(-?)(?:(\d+)\.)?(\d+):(\d\d)(?::(\d\d)(?:\.(\d\d\d))?)?/;
    // Parsing and Creation
    function createDuration(input, unit) {
        if (typeof input === 'string') {
            return parseString(input);
        }
        if (typeof input === 'object' && input) { // non-null object
            return parseObject(input);
        }
        if (typeof input === 'number') {
            return parseObject({
                [unit || 'milliseconds']: input
            });
        }
        return null;
    }

    function parseString(s) {
        let m = PARSE_RE.exec(s);
        if (m) {
            let sign = m[1] ? -1 : 1;
            return {
                years: 0,
                months: 0,
                days: sign * (m[2] ? parseInt(m[2], 10) : 0),
                milliseconds: sign * ((m[3] ? parseInt(m[3], 10) : 0) * 60 * 60 * 1000 + // hours
                    (m[4] ? parseInt(m[4], 10) : 0) * 60 * 1000 + // minutes
                    (m[5] ? parseInt(m[5], 10) : 0) * 1000 + // seconds
                    (m[6] ? parseInt(m[6], 10) : 0) // ms
                ),
            };
        }
        return null;
    }

    function parseObject(obj) {
        let duration = {
            years: obj.years || obj.year || 0,
            months: obj.months || obj.month || 0,
            days: obj.days || obj.day || 0,
            milliseconds: (obj.hours || obj.hour || 0) * 60 * 60 * 1000 + // hours
                (obj.minutes || obj.minute || 0) * 60 * 1000 + // minutes
                (obj.seconds || obj.second || 0) * 1000 + // seconds
                (obj.milliseconds || obj.millisecond || obj.ms || 0), // ms
        };
        let weeks = obj.weeks || obj.week;
        if (weeks) {
            duration.days += weeks * 7;
            duration.specifiedWeeks = true;
        }
        return duration;
    }
    // Equality
    function durationsEqual(d0, d1) {
        return d0.years === d1.years &&
            d0.months === d1.months &&
            d0.days === d1.days &&
            d0.milliseconds === d1.milliseconds;
    }

    function asCleanDays(dur) {
        if (!dur.years && !dur.months && !dur.milliseconds) {
            return dur.days;
        }
        return 0;
    }
    // Simple Math
    function addDurations(d0, d1) {
        return {
            years: d0.years + d1.years,
            months: d0.months + d1.months,
            days: d0.days + d1.days,
            milliseconds: d0.milliseconds + d1.milliseconds,
        };
    }

    function subtractDurations(d1, d0) {
        return {
            years: d1.years - d0.years,
            months: d1.months - d0.months,
            days: d1.days - d0.days,
            milliseconds: d1.milliseconds - d0.milliseconds,
        };
    }

    function multiplyDuration(d, n) {
        return {
            years: d.years * n,
            months: d.months * n,
            days: d.days * n,
            milliseconds: d.milliseconds * n,
        };
    }
    // Conversions
    // "Rough" because they are based on average-case Gregorian months/years
    function asRoughYears(dur) {
        return asRoughDays(dur) / 365;
    }

    function asRoughMonths(dur) {
        return asRoughDays(dur) / 30;
    }

    function asRoughDays(dur) {
        return asRoughMs(dur) / 864e5;
    }

    function asRoughMinutes(dur) {
        return asRoughMs(dur) / (1000 * 60);
    }

    function asRoughSeconds(dur) {
        return asRoughMs(dur) / 1000;
    }

    function asRoughMs(dur) {
        return dur.years * (365 * 864e5) +
            dur.months * (30 * 864e5) +
            dur.days * 864e5 +
            dur.milliseconds;
    }
    // Advanced Math
    function wholeDivideDurations(numerator, denominator) {
        let res = null;
        for (let i = 0; i < INTERNAL_UNITS.length; i += 1) {
            let unit = INTERNAL_UNITS[i];
            if (denominator[unit]) {
                let localRes = numerator[unit] / denominator[unit];
                if (!isInt(localRes) || (res !== null && res !== localRes)) {
                    return null;
                }
                res = localRes;
            } else if (numerator[unit]) {
                // needs to divide by something but can't!
                return null;
            }
        }
        return res;
    }

    function greatestDurationDenominator(dur) {
        let ms = dur.milliseconds;
        if (ms) {
            if (ms % 1000 !== 0) {
                return {
                    unit: 'millisecond',
                    value: ms
                };
            }
            if (ms % (1000 * 60) !== 0) {
                return {
                    unit: 'second',
                    value: ms / 1000
                };
            }
            if (ms % (1000 * 60 * 60) !== 0) {
                return {
                    unit: 'minute',
                    value: ms / (1000 * 60)
                };
            }
            if (ms) {
                return {
                    unit: 'hour',
                    value: ms / (1000 * 60 * 60)
                };
            }
        }
        if (dur.days) {
            if (dur.specifiedWeeks && dur.days % 7 === 0) {
                return {
                    unit: 'week',
                    value: dur.days / 7
                };
            }
            return {
                unit: 'day',
                value: dur.days
            };
        }
        if (dur.months) {
            return {
                unit: 'month',
                value: dur.months
            };
        }
        if (dur.years) {
            return {
                unit: 'year',
                value: dur.years
            };
        }
        return {
            unit: 'millisecond',
            value: 0
        };
    }

    // TODO: new util arrayify?
    function removeExact(array, exactVal) {
        let removeCnt = 0;
        let i = 0;
        while (i < array.length) {
            if (array[i] === exactVal) {
                array.splice(i, 1);
                removeCnt += 1;
            } else {
                i += 1;
            }
        }
        return removeCnt;
    }

    function isArraysEqual(a0, a1, equalityFunc) {
        if (a0 === a1) {
            return true;
        }
        let len = a0.length;
        let i;
        if (len !== a1.length) { // not array? or not same length?
            return false;
        }
        for (i = 0; i < len; i += 1) {
            if (!(equalityFunc ? equalityFunc(a0[i], a1[i]) : a0[i] === a1[i])) {
                return false;
            }
        }
        return true;
    }

    const DAY_IDS = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
    // Adding
    function addWeeks(m, n) {
        let a = dateToUtcArray(m);
        a[2] += n * 7;
        return arrayToUtcDate(a);
    }

    function addDays(m, n) {
        let a = dateToUtcArray(m);
        a[2] += n;
        return arrayToUtcDate(a);
    }

    function addMs(m, n) {
        let a = dateToUtcArray(m);
        a[6] += n;
        return arrayToUtcDate(a);
    }
    // Diffing (all return floats)
    // TODO: why not use ranges?
    function diffWeeks(m0, m1) {
        return diffDays(m0, m1) / 7;
    }

    function diffDays(m0, m1) {
        return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60 * 24);
    }

    function diffHours(m0, m1) {
        return (m1.valueOf() - m0.valueOf()) / (1000 * 60 * 60);
    }

    function diffMinutes(m0, m1) {
        return (m1.valueOf() - m0.valueOf()) / (1000 * 60);
    }

    function diffSeconds(m0, m1) {
        return (m1.valueOf() - m0.valueOf()) / 1000;
    }

    function diffDayAndTime(m0, m1) {
        let m0day = startOfDay(m0);
        let m1day = startOfDay(m1);
        return {
            years: 0,
            months: 0,
            days: Math.round(diffDays(m0day, m1day)),
            milliseconds: (m1.valueOf() - m1day.valueOf()) - (m0.valueOf() - m0day.valueOf()),
        };
    }
    // Diffing Whole Units
    function diffWholeWeeks(m0, m1) {
        let d = diffWholeDays(m0, m1);
        if (d !== null && d % 7 === 0) {
            return d / 7;
        }
        return null;
    }

    function diffWholeDays(m0, m1) {
        if (timeAsMs(m0) === timeAsMs(m1)) {
            return Math.round(diffDays(m0, m1));
        }
        return null;
    }
    // Start-Of
    function startOfDay(m) {
        return arrayToUtcDate([
            m.getUTCFullYear(),
            m.getUTCMonth(),
            m.getUTCDate(),
        ]);
    }

    function startOfHour(m) {
        return arrayToUtcDate([
            m.getUTCFullYear(),
            m.getUTCMonth(),
            m.getUTCDate(),
            m.getUTCHours(),
        ]);
    }

    function startOfMinute(m) {
        return arrayToUtcDate([
            m.getUTCFullYear(),
            m.getUTCMonth(),
            m.getUTCDate(),
            m.getUTCHours(),
            m.getUTCMinutes(),
        ]);
    }

    function startOfSecond(m) {
        return arrayToUtcDate([
            m.getUTCFullYear(),
            m.getUTCMonth(),
            m.getUTCDate(),
            m.getUTCHours(),
            m.getUTCMinutes(),
            m.getUTCSeconds(),
        ]);
    }
    // Week Computation
    function weekOfYear(marker, dow, doy) {
        let y = marker.getUTCFullYear();
        let w = weekOfGivenYear(marker, y, dow, doy);
        if (w < 1) {
            return weekOfGivenYear(marker, y - 1, dow, doy);
        }
        let nextW = weekOfGivenYear(marker, y + 1, dow, doy);
        if (nextW >= 1) {
            return Math.min(w, nextW);
        }
        return w;
    }

    function weekOfGivenYear(marker, year, dow, doy) {
        let firstWeekStart = arrayToUtcDate([year, 0, 1 + firstWeekOffset(year, dow, doy)]);
        let dayStart = startOfDay(marker);
        let days = Math.round(diffDays(firstWeekStart, dayStart));
        return Math.floor(days / 7) + 1; // zero-indexed
    }
    // start-of-first-week - start-of-year
    function firstWeekOffset(year, dow, doy) {
        // first-week day -- which january is always in the first week (4 for iso, 1 for other)
        let fwd = 7 + dow - doy;
        // first-week day local weekday -- which local weekday is fwd
        let fwdlw = (7 + arrayToUtcDate([year, 0, fwd]).getUTCDay() - dow) % 7;
        return -fwdlw + fwd - 1;
    }
    // Array Conversion
    function dateToLocalArray(date) {
        return [
            date.getFullYear(),
            date.getMonth(),
            date.getDate(),
            date.getHours(),
            date.getMinutes(),
            date.getSeconds(),
            date.getMilliseconds(),
        ];
    }

    function arrayToLocalDate(a) {
        return new Date(a[0], a[1] || 0, a[2] == null ? 1 : a[2], // day of month
            a[3] || 0, a[4] || 0, a[5] || 0);
    }

    function dateToUtcArray(date) {
        return [
            date.getUTCFullYear(),
            date.getUTCMonth(),
            date.getUTCDate(),
            date.getUTCHours(),
            date.getUTCMinutes(),
            date.getUTCSeconds(),
            date.getUTCMilliseconds(),
        ];
    }

    function arrayToUtcDate(a) {
        // according to web standards (and Safari), a month index is required.
        // massage if only given a year.
        if (a.length === 1) {
            a = a.concat([0]);
        }
        return new Date(Date.UTC(...a));
    }
    // Other Utils
    function isValidDate(m) {
        return !isNaN(m.valueOf());
    }

    function timeAsMs(m) {
        return m.getUTCHours() * 1000 * 60 * 60 +
            m.getUTCMinutes() * 1000 * 60 +
            m.getUTCSeconds() * 1000 +
            m.getUTCMilliseconds();
    }

    // timeZoneOffset is in minutes
    function buildIsoString(marker, timeZoneOffset, stripZeroTime = false) {
        let s = marker.toISOString();
        s = s.replace('.000', '');
        if (stripZeroTime) {
            s = s.replace('T00:00:00Z', '');
        }
        if (s.length > 10) { // time part wasn't stripped, can add timezone info
            if (timeZoneOffset == null) {
                s = s.replace('Z', '');
            } else if (timeZoneOffset !== 0) {
                s = s.replace('Z', formatTimeZoneOffset(timeZoneOffset, true));
            }
            // otherwise, its UTC-0 and we want to keep the Z
        }
        return s;
    }
    // formats the date, but with no time part
    // TODO: somehow merge with buildIsoString and stripZeroTime
    // TODO: rename. omit "string"
    function formatDayString(marker) {
        return marker.toISOString().replace(/T.*$/, '');
    }

    function formatIsoMonthStr(marker) {
        return marker.toISOString().match(/^\d{4}-\d{2}/)[0];
    }
    // TODO: use Date::toISOString and use everything after the T?
    function formatIsoTimeString(marker) {
        return padStart(marker.getUTCHours(), 2) + ':' +
            padStart(marker.getUTCMinutes(), 2) + ':' +
            padStart(marker.getUTCSeconds(), 2);
    }

    function formatTimeZoneOffset(minutes, doIso = false) {
        let sign = minutes < 0 ? '-' : '+';
        let abs = Math.abs(minutes);
        let hours = Math.floor(abs / 60);
        let mins = Math.round(abs % 60);
        if (doIso) {
            return `${sign + padStart(hours, 2)}:${padStart(mins, 2)}`;
        }
        return `GMT${sign}${hours}${mins ? `:${padStart(mins, 2)}` : ''}`;
    }

    function memoize(workerFunc, resEquality, teardownFunc) {
        let currentArgs;
        let currentRes;
        return function(...newArgs) {
            if (!currentArgs) {
                currentRes = workerFunc.apply(this, newArgs);
            } else if (!isArraysEqual(currentArgs, newArgs)) {
                if (teardownFunc) {
                    teardownFunc(currentRes);
                }
                let res = workerFunc.apply(this, newArgs);
                if (!resEquality || !resEquality(res, currentRes)) {
                    currentRes = res;
                }
            }
            currentArgs = newArgs;
            return currentRes;
        };
    }

    function memoizeObjArg(workerFunc, resEquality, teardownFunc) {
        let currentArg;
        let currentRes;
        return (newArg) => {
            if (!currentArg) {
                currentRes = workerFunc.call(this, newArg);
            } else if (!isPropsEqual(currentArg, newArg)) {
                if (teardownFunc) {
                    teardownFunc(currentRes);
                }
                let res = workerFunc.call(this, newArg);
                if (!resEquality || !resEquality(res, currentRes)) {
                    currentRes = res;
                }
            }
            currentArg = newArg;
            return currentRes;
        };
    }

    function memoizeArraylike( // used at all?
        workerFunc, resEquality, teardownFunc) {
        let currentArgSets = [];
        let currentResults = [];
        return (newArgSets) => {
            let currentLen = currentArgSets.length;
            let newLen = newArgSets.length;
            let i = 0;
            for (; i < currentLen; i += 1) {
                if (!newArgSets[i]) { // one of the old sets no longer exists
                    if (teardownFunc) {
                        teardownFunc(currentResults[i]);
                    }
                } else if (!isArraysEqual(currentArgSets[i], newArgSets[i])) {
                    if (teardownFunc) {
                        teardownFunc(currentResults[i]);
                    }
                    let res = workerFunc.apply(this, newArgSets[i]);
                    if (!resEquality || !resEquality(res, currentResults[i])) {
                        currentResults[i] = res;
                    }
                }
            }
            for (; i < newLen; i += 1) {
                currentResults[i] = workerFunc.apply(this, newArgSets[i]);
            }
            currentArgSets = newArgSets;
            currentResults.splice(newLen); // remove excess
            return currentResults;
        };
    }

    function memoizeHashlike(workerFunc, resEquality, teardownFunc) {
        let currentArgHash = {};
        let currentResHash = {};
        return (newArgHash) => {
            let newResHash = {};
            for (let key in newArgHash) {
                if (!currentResHash[key]) {
                    newResHash[key] = workerFunc.apply(this, newArgHash[key]);
                } else if (!isArraysEqual(currentArgHash[key], newArgHash[key])) {
                    if (teardownFunc) {
                        teardownFunc(currentResHash[key]);
                    }
                    let res = workerFunc.apply(this, newArgHash[key]);
                    newResHash[key] = (resEquality && resEquality(res, currentResHash[key])) ?
                        currentResHash[key] :
                        res;
                } else {
                    newResHash[key] = currentResHash[key];
                }
            }
            currentArgHash = newArgHash;
            currentResHash = newResHash;
            return newResHash;
        };
    }

    const EXTENDED_SETTINGS_AND_SEVERITIES = {
        week: 3,
        separator: 9,
        omitZeroMinute: 9,
        meridiem: 9,
        omitCommas: 9,
    };
    const STANDARD_DATE_PROP_SEVERITIES = {
        timeZoneName: 7,
        era: 6,
        year: 5,
        month: 4,
        day: 2,
        weekday: 2,
        hour: 1,
        minute: 1,
        second: 1,
    };
    const MERIDIEM_RE = /\s*([ap])\.?m\.?/i; // eats up leading spaces too
    const COMMA_RE = /,/g; // we need re for globalness
    const MULTI_SPACE_RE = /\s+/g;
    const LTR_RE = /\u200e/g; // control character
    const UTC_RE = /UTC|GMT/;
    class NativeFormatter {
        constructor(formatSettings) {
            let standardDateProps = {};
            let extendedSettings = {};
            let smallestUnitNum = 9; // the smallest unit in the formatter (9 is a sentinel, beyond max)
            for (let name in formatSettings) {
                if (name in EXTENDED_SETTINGS_AND_SEVERITIES) {
                    extendedSettings[name] = formatSettings[name];
                    const severity = EXTENDED_SETTINGS_AND_SEVERITIES[name];
                    if (severity < 9) {
                        smallestUnitNum = Math.min(EXTENDED_SETTINGS_AND_SEVERITIES[name], smallestUnitNum);
                    }
                } else {
                    standardDateProps[name] = formatSettings[name];
                    if (name in STANDARD_DATE_PROP_SEVERITIES) { // TODO: what about hour12? no severity
                        smallestUnitNum = Math.min(STANDARD_DATE_PROP_SEVERITIES[name], smallestUnitNum);
                    }
                }
            }
            this.standardDateProps = standardDateProps;
            this.extendedSettings = extendedSettings;
            this.smallestUnitNum = smallestUnitNum;
            this.buildFormattingFunc = memoize(buildFormattingFunc);
        }
        format(date, context) {
            return this.buildFormattingFunc(this.standardDateProps, this.extendedSettings, context)(date);
        }
        formatRange(start, end, context, betterDefaultSeparator) {
            let {
                standardDateProps,
                extendedSettings
            } = this;
            let diffSeverity = computeMarkerDiffSeverity(start.marker, end.marker, context.calendarSystem);
            if (!diffSeverity) {
                return this.format(start, context);
            }
            let biggestUnitForPartial = diffSeverity;
            if (biggestUnitForPartial > 1 && // the two dates are different in a way that's larger scale than time
                (standardDateProps.year === 'numeric' || standardDateProps.year === '2-digit') &&
                (standardDateProps.month === 'numeric' || standardDateProps.month === '2-digit') &&
                (standardDateProps.day === 'numeric' || standardDateProps.day === '2-digit')) {
                biggestUnitForPartial = 1; // make it look like the dates are only different in terms of time
            }
            let full0 = this.format(start, context);
            let full1 = this.format(end, context);
            if (full0 === full1) {
                return full0;
            }
            let partialDateProps = computePartialFormattingOptions(standardDateProps, biggestUnitForPartial);
            let partialFormattingFunc = buildFormattingFunc(partialDateProps, extendedSettings, context);
            let partial0 = partialFormattingFunc(start);
            let partial1 = partialFormattingFunc(end);
            let insertion = findCommonInsertion(full0, partial0, full1, partial1);
            let separator = extendedSettings.separator || betterDefaultSeparator || context.defaultSeparator || '';
            if (insertion) {
                return insertion.before + partial0 + separator + partial1 + insertion.after;
            }
            return full0 + separator + full1;
        }
        getSmallestUnit() {
            switch (this.smallestUnitNum) {
                case 7:
                case 6:
                case 5:
                    return 'year';
                case 4:
                    return 'month';
                case 3:
                    return 'week';
                case 2:
                    return 'day';
                default:
                    return 'time'; // really?
            }
        }
    }

    function buildFormattingFunc(standardDateProps, extendedSettings, context) {
        let standardDatePropCnt = Object.keys(standardDateProps).length;
        if (standardDatePropCnt === 1 && standardDateProps.timeZoneName === 'short') {
            return (date) => (formatTimeZoneOffset(date.timeZoneOffset));
        }
        if (standardDatePropCnt === 0 && extendedSettings.week) {
            return (date) => (formatWeekNumber(context.computeWeekNumber(date.marker), context.weekText, context.weekTextLong, context.locale, extendedSettings.week));
        }
        return buildNativeFormattingFunc(standardDateProps, extendedSettings, context);
    }

    function buildNativeFormattingFunc(standardDateProps, extendedSettings, context) {
        standardDateProps = Object.assign({}, standardDateProps); // copy
        extendedSettings = Object.assign({}, extendedSettings); // copy
        sanitizeSettings(standardDateProps, extendedSettings);
        standardDateProps.timeZone = 'UTC'; // we leverage the only guaranteed timeZone for our UTC markers
        let normalFormat = new Intl.DateTimeFormat(context.locale.codes, standardDateProps);
        let zeroFormat; // needed?
        if (extendedSettings.omitZeroMinute) {
            let zeroProps = Object.assign({}, standardDateProps);
            delete zeroProps.minute; // seconds and ms were already considered in sanitizeSettings
            zeroFormat = new Intl.DateTimeFormat(context.locale.codes, zeroProps);
        }
        return (date) => {
            let {
                marker
            } = date;
            let format;
            if (zeroFormat && !marker.getUTCMinutes()) {
                format = zeroFormat;
            } else {
                format = normalFormat;
            }
            let s = format.format(marker);
            return postProcess(s, date, standardDateProps, extendedSettings, context);
        };
    }

    function sanitizeSettings(standardDateProps, extendedSettings) {
        // deal with a browser inconsistency where formatting the timezone
        // requires that the hour/minute be present.
        if (standardDateProps.timeZoneName) {
            if (!standardDateProps.hour) {
                standardDateProps.hour = '2-digit';
            }
            if (!standardDateProps.minute) {
                standardDateProps.minute = '2-digit';
            }
        }
        // only support short timezone names
        if (standardDateProps.timeZoneName === 'long') {
            standardDateProps.timeZoneName = 'short';
        }
        // if requesting to display seconds, MUST display minutes
        if (extendedSettings.omitZeroMinute && (standardDateProps.second || standardDateProps.millisecond)) {
            delete extendedSettings.omitZeroMinute;
        }
    }

    function postProcess(s, date, standardDateProps, extendedSettings, context) {
        s = s.replace(LTR_RE, ''); // remove left-to-right control chars. do first. good for other regexes
        if (standardDateProps.timeZoneName === 'short') {
            s = injectTzoStr(s, (context.timeZone === 'UTC' || date.timeZoneOffset == null) ?
                'UTC' : // important to normalize for IE, which does "GMT"
                formatTimeZoneOffset(date.timeZoneOffset));
        }
        if (extendedSettings.omitCommas) {
            s = s.replace(COMMA_RE, '').trim();
        }
        if (extendedSettings.omitZeroMinute) {
            s = s.replace(':00', ''); // zeroFormat doesn't always achieve this
        }
        // ^ do anything that might create adjacent spaces before this point,
        // because MERIDIEM_RE likes to eat up loading spaces
        if (extendedSettings.meridiem === false) {
            s = s.replace(MERIDIEM_RE, '').trim();
        } else if (extendedSettings.meridiem === 'narrow') { // a/p
            s = s.replace(MERIDIEM_RE, (m0, m1) => m1.toLocaleLowerCase());
        } else if (extendedSettings.meridiem === 'short') { // am/pm
            s = s.replace(MERIDIEM_RE, (m0, m1) => `${m1.toLocaleLowerCase()}m`);
        } else if (extendedSettings.meridiem === 'lowercase') { // other meridiem transformers already converted to lowercase
            s = s.replace(MERIDIEM_RE, (m0) => m0.toLocaleLowerCase());
        }
        s = s.replace(MULTI_SPACE_RE, ' ');
        s = s.trim();
        return s;
    }

    function injectTzoStr(s, tzoStr) {
        let replaced = false;
        s = s.replace(UTC_RE, () => {
            replaced = true;
            return tzoStr;
        });
        // IE11 doesn't include UTC/GMT in the original string, so append to end
        if (!replaced) {
            s += ` ${tzoStr}`;
        }
        return s;
    }

    function formatWeekNumber(num, weekText, weekTextLong, locale, display) {
        let parts = [];
        if (display === 'long') {
            parts.push(weekTextLong);
        } else if (display === 'short' || display === 'narrow') {
            parts.push(weekText);
        }
        if (display === 'long' || display === 'short') {
            parts.push(' ');
        }
        parts.push(locale.simpleNumberFormat.format(num));
        if (locale.options.direction === 'rtl') { // TODO: use control characters instead?
            parts.reverse();
        }
        return parts.join('');
    }
    // Range Formatting Utils
    // 0 = exactly the same
    // 1 = different by time
    // and bigger
    function computeMarkerDiffSeverity(d0, d1, ca) {
        if (ca.getMarkerYear(d0) !== ca.getMarkerYear(d1)) {
            return 5;
        }
        if (ca.getMarkerMonth(d0) !== ca.getMarkerMonth(d1)) {
            return 4;
        }
        if (ca.getMarkerDay(d0) !== ca.getMarkerDay(d1)) {
            return 2;
        }
        if (timeAsMs(d0) !== timeAsMs(d1)) {
            return 1;
        }
        return 0;
    }

    function computePartialFormattingOptions(options, biggestUnit) {
        let partialOptions = {};
        for (let name in options) {
            if (!(name in STANDARD_DATE_PROP_SEVERITIES) || // not a date part prop (like timeZone)
                STANDARD_DATE_PROP_SEVERITIES[name] <= biggestUnit) {
                partialOptions[name] = options[name];
            }
        }
        return partialOptions;
    }

    function findCommonInsertion(full0, partial0, full1, partial1) {
        let i0 = 0;
        while (i0 < full0.length) {
            let found0 = full0.indexOf(partial0, i0);
            if (found0 === -1) {
                break;
            }
            let before0 = full0.substr(0, found0);
            i0 = found0 + partial0.length;
            let after0 = full0.substr(i0);
            let i1 = 0;
            while (i1 < full1.length) {
                let found1 = full1.indexOf(partial1, i1);
                if (found1 === -1) {
                    break;
                }
                let before1 = full1.substr(0, found1);
                i1 = found1 + partial1.length;
                let after1 = full1.substr(i1);
                if (before0 === before1 && after0 === after1) {
                    return {
                        before: before0,
                        after: after0,
                    };
                }
            }
        }
        return null;
    }

    function expandZonedMarker(dateInfo, calendarSystem) {
        let a = calendarSystem.markerToArray(dateInfo.marker);
        return {
            marker: dateInfo.marker,
            timeZoneOffset: dateInfo.timeZoneOffset,
            array: a,
            year: a[0],
            month: a[1],
            day: a[2],
            hour: a[3],
            minute: a[4],
            second: a[5],
            millisecond: a[6],
        };
    }

    function createVerboseFormattingArg(start, end, context, betterDefaultSeparator) {
        let startInfo = expandZonedMarker(start, context.calendarSystem);
        let endInfo = end ? expandZonedMarker(end, context.calendarSystem) : null;
        return {
            date: startInfo,
            start: startInfo,
            end: endInfo,
            timeZone: context.timeZone,
            localeCodes: context.locale.codes,
            defaultSeparator: betterDefaultSeparator || context.defaultSeparator,
        };
    }

    /*
    TODO: fix the terminology of "formatter" vs "formatting func"
    */
    /*
    At the time of instantiation, this object does not know which cmd-formatting system it will use.
    It receives this at the time of formatting, as a setting.
    */
    class CmdFormatter {
        constructor(cmdStr) {
            this.cmdStr = cmdStr;
        }
        format(date, context, betterDefaultSeparator) {
            return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
        }
        formatRange(start, end, context, betterDefaultSeparator) {
            return context.cmdFormatter(this.cmdStr, createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
        }
    }

    class FuncFormatter {
        constructor(func) {
            this.func = func;
        }
        format(date, context, betterDefaultSeparator) {
            return this.func(createVerboseFormattingArg(date, null, context, betterDefaultSeparator));
        }
        formatRange(start, end, context, betterDefaultSeparator) {
            return this.func(createVerboseFormattingArg(start, end, context, betterDefaultSeparator));
        }
    }

    function createFormatter(input) {
        if (typeof input === 'object' && input) { // non-null object
            return new NativeFormatter(input);
        }
        if (typeof input === 'string') {
            return new CmdFormatter(input);
        }
        if (typeof input === 'function') {
            return new FuncFormatter(input);
        }
        return null;
    }

    // base options
    // ------------
    const BASE_OPTION_REFINERS = {
        navLinkDayClick: identity,
        navLinkWeekClick: identity,
        duration: createDuration,
        bootstrapFontAwesome: identity,
        buttonIcons: identity,
        customButtons: identity,
        defaultAllDayEventDuration: createDuration,
        defaultTimedEventDuration: createDuration,
        nextDayThreshold: createDuration,
        scrollTime: createDuration,
        scrollTimeReset: Boolean,
        slotMinTime: createDuration,
        slotMaxTime: createDuration,
        dayPopoverFormat: createFormatter,
        slotDuration: createDuration,
        snapDuration: createDuration,
        headerToolbar: identity,
        footerToolbar: identity,
        defaultRangeSeparator: String,
        titleRangeSeparator: String,
        forceEventDuration: Boolean,
        dayHeaders: Boolean,
        dayHeaderFormat: createFormatter,
        dayHeaderClassNames: identity,
        dayHeaderContent: identity,
        dayHeaderDidMount: identity,
        dayHeaderWillUnmount: identity,
        dayCellClassNames: identity,
        dayCellContent: identity,
        dayCellDidMount: identity,
        dayCellWillUnmount: identity,
        initialView: String,
        aspectRatio: Number,
        weekends: Boolean,
        weekNumberCalculation: identity,
        weekNumbers: Boolean,
        weekNumberClassNames: identity,
        weekNumberContent: identity,
        weekNumberDidMount: identity,
        weekNumberWillUnmount: identity,
        editable: Boolean,
        viewClassNames: identity,
        viewDidMount: identity,
        viewWillUnmount: identity,
        nowIndicator: Boolean,
        nowIndicatorSnap: identity,
        nowIndicatorClassNames: identity,
        nowIndicatorContent: identity,
        nowIndicatorDidMount: identity,
        nowIndicatorWillUnmount: identity,
        showNonCurrentDates: Boolean,
        lazyFetching: Boolean,
        startParam: String,
        endParam: String,
        timeZoneParam: String,
        timeZone: String,
        locales: identity,
        locale: identity,
        themeSystem: String,
        dragRevertDuration: Number,
        dragScroll: Boolean,
        allDayMaintainDuration: Boolean,
        unselectAuto: Boolean,
        dropAccept: identity,
        eventOrder: parseFieldSpecs,
        eventOrderStrict: Boolean,
        handleWindowResize: Boolean,
        windowResizeDelay: Number,
        longPressDelay: Number,
        eventDragMinDistance: Number,
        expandRows: Boolean,
        height: identity,
        contentHeight: identity,
        direction: String,
        weekNumberFormat: createFormatter,
        eventResizableFromStart: Boolean,
        displayEventTime: Boolean,
        displayEventEnd: Boolean,
        weekText: String,
        weekTextLong: String,
        progressiveEventRendering: Boolean,
        businessHours: identity,
        initialDate: identity,
        now: identity,
        eventDataTransform: identity,
        stickyHeaderDates: identity,
        stickyFooterScrollbar: identity,
        viewHeight: identity,
        defaultAllDay: Boolean,
        eventSourceFailure: identity,
        eventSourceSuccess: identity,
        eventDisplay: String,
        eventStartEditable: Boolean,
        eventDurationEditable: Boolean,
        eventOverlap: identity,
        eventConstraint: identity,
        eventAllow: identity,
        eventBackgroundColor: String,
        eventBorderColor: String,
        eventTextColor: String,
        eventColor: String,
        eventClassNames: identity,
        eventContent: identity,
        eventDidMount: identity,
        eventWillUnmount: identity,
        selectConstraint: identity,
        selectOverlap: identity,
        selectAllow: identity,
        droppable: Boolean,
        unselectCancel: String,
        slotLabelFormat: identity,
        slotLaneClassNames: identity,
        slotLaneContent: identity,
        slotLaneDidMount: identity,
        slotLaneWillUnmount: identity,
        slotLabelClassNames: identity,
        slotLabelContent: identity,
        slotLabelDidMount: identity,
        slotLabelWillUnmount: identity,
        dayMaxEvents: identity,
        dayMaxEventRows: identity,
        dayMinWidth: Number,
        slotLabelInterval: createDuration,
        allDayText: String,
        allDayClassNames: identity,
        allDayContent: identity,
        allDayDidMount: identity,
        allDayWillUnmount: identity,
        slotMinWidth: Number,
        navLinks: Boolean,
        eventTimeFormat: createFormatter,
        rerenderDelay: Number,
        moreLinkText: identity,
        moreLinkHint: identity,
        selectMinDistance: Number,
        selectable: Boolean,
        selectLongPressDelay: Number,
        eventLongPressDelay: Number,
        selectMirror: Boolean,
        eventMaxStack: Number,
        eventMinHeight: Number,
        eventMinWidth: Number,
        eventShortHeight: Number,
        slotEventOverlap: Boolean,
        plugins: identity,
        firstDay: Number,
        dayCount: Number,
        dateAlignment: String,
        dateIncrement: createDuration,
        hiddenDays: identity,
        fixedWeekCount: Boolean,
        validRange: identity,
        visibleRange: identity,
        titleFormat: identity,
        eventInteractive: Boolean,
        // only used by list-view, but languages define the value, so we need it in base options
        noEventsText: String,
        viewHint: identity,
        navLinkHint: identity,
        closeHint: String,
        timeHint: String,
        eventHint: String,
        moreLinkClick: identity,
        moreLinkClassNames: identity,
        moreLinkContent: identity,
        moreLinkDidMount: identity,
        moreLinkWillUnmount: identity,
        monthStartFormat: createFormatter,
        // for connectors
        // (can't be part of plugin system b/c must be provided at runtime)
        handleCustomRendering: identity,
        customRenderingMetaMap: identity,
        customRenderingReplaces: Boolean,
    };
    // do NOT give a type here. need `typeof BASE_OPTION_DEFAULTS` to give real results.
    // raw values.
    const BASE_OPTION_DEFAULTS = {
        eventDisplay: 'auto',
        defaultRangeSeparator: ' - ',
        titleRangeSeparator: ' \u2013 ',
        defaultTimedEventDuration: '01:00:00',
        defaultAllDayEventDuration: {
            day: 1
        },
        forceEventDuration: false,
        nextDayThreshold: '00:00:00',
        dayHeaders: true,
        initialView: '',
        aspectRatio: 1.35,
        headerToolbar: {
            start: 'title',
            center: '',
            end: 'today prev,next',
        },
        weekends: true,
        weekNumbers: false,
        weekNumberCalculation: 'local',
        editable: false,
        nowIndicator: false,
        scrollTime: '06:00:00',
        scrollTimeReset: true,
        slotMinTime: '00:00:00',
        slotMaxTime: '24:00:00',
        showNonCurrentDates: true,
        lazyFetching: true,
        startParam: 'start',
        endParam: 'end',
        timeZoneParam: 'timeZone',
        timeZone: 'local',
        locales: [],
        locale: '',
        themeSystem: 'standard',
        dragRevertDuration: 500,
        dragScroll: true,
        allDayMaintainDuration: false,
        unselectAuto: true,
        dropAccept: '*',
        eventOrder: 'start,-duration,allDay,title',
        dayPopoverFormat: {
            month: 'long',
            day: 'numeric',
            year: 'numeric'
        },
        handleWindowResize: true,
        windowResizeDelay: 100,
        longPressDelay: 1000,
        eventDragMinDistance: 5,
        expandRows: false,
        navLinks: false,
        selectable: false,
        eventMinHeight: 15,
        eventMinWidth: 30,
        eventShortHeight: 30,
        monthStartFormat: {
            month: 'long',
            day: 'numeric'
        },
        nowIndicatorSnap: 'auto',
    };
    // calendar listeners
    // ------------------
    const CALENDAR_LISTENER_REFINERS = {
        datesSet: identity,
        eventsSet: identity,
        eventAdd: identity,
        eventChange: identity,
        eventRemove: identity,
        windowResize: identity,
        eventClick: identity,
        eventMouseEnter: identity,
        eventMouseLeave: identity,
        select: identity,
        unselect: identity,
        loading: identity,
        // internal
        _unmount: identity,
        _beforeprint: identity,
        _afterprint: identity,
        _noEventDrop: identity,
        _noEventResize: identity,
        _resize: identity,
        _scrollRequest: identity,
    };
    // calendar-specific options
    // -------------------------
    const CALENDAR_OPTION_REFINERS = {
        buttonText: identity,
        buttonHints: identity,
        views: identity,
        plugins: identity,
        initialEvents: identity,
        events: identity,
        eventSources: identity,
    };
    const COMPLEX_OPTION_COMPARATORS = {
        headerToolbar: isMaybeObjectsEqual,
        footerToolbar: isMaybeObjectsEqual,
        buttonText: isMaybeObjectsEqual,
        buttonHints: isMaybeObjectsEqual,
        buttonIcons: isMaybeObjectsEqual,
        dateIncrement: isMaybeObjectsEqual,
        plugins: isMaybeArraysEqual,
        events: isMaybeArraysEqual,
        eventSources: isMaybeArraysEqual,
        ['resources']: isMaybeArraysEqual,
    };

    function isMaybeObjectsEqual(a, b) {
        if (typeof a === 'object' && typeof b === 'object' && a && b) { // both non-null objects
            return isPropsEqual(a, b);
        }
        return a === b;
    }

    function isMaybeArraysEqual(a, b) {
        if (Array.isArray(a) && Array.isArray(b)) {
            return isArraysEqual(a, b);
        }
        return a === b;
    }
    // view-specific options
    // ---------------------
    const VIEW_OPTION_REFINERS = {
        type: String,
        component: identity,
        buttonText: String,
        buttonTextKey: String,
        dateProfileGeneratorClass: identity,
        usesMinMaxTime: Boolean,
        classNames: identity,
        content: identity,
        didMount: identity,
        willUnmount: identity,
    };
    // util funcs
    // ----------------------------------------------------------------------------------------------------
    function mergeRawOptions(optionSets) {
        return mergeProps(optionSets, COMPLEX_OPTION_COMPARATORS);
    }

    function refineProps(input, refiners) {
        let refined = {};
        let extra = {};
        for (let propName in refiners) {
            if (propName in input) {
                refined[propName] = refiners[propName](input[propName]);
            }
        }
        for (let propName in input) {
            if (!(propName in refiners)) {
                extra[propName] = input[propName];
            }
        }
        return {
            refined,
            extra
        };
    }

    function identity(raw) {
        return raw;
    }

    const {
        hasOwnProperty
    } = Object.prototype;
    // Merges an array of objects into a single object.
    // The second argument allows for an array of property names who's object values will be merged together.
    function mergeProps(propObjs, complexPropsMap) {
        let dest = {};
        if (complexPropsMap) {
            for (let name in complexPropsMap) {
                if (complexPropsMap[name] === isMaybeObjectsEqual) { // implies that it's object-mergeable
                    let complexObjs = [];
                    // collect the trailing object values, stopping when a non-object is discovered
                    for (let i = propObjs.length - 1; i >= 0; i -= 1) {
                        let val = propObjs[i][name];
                        if (typeof val === 'object' && val) { // non-null object
                            complexObjs.unshift(val);
                        } else if (val !== undefined) {
                            dest[name] = val; // if there were no objects, this value will be used
                            break;
                        }
                    }
                    // if the trailing values were objects, use the merged value
                    if (complexObjs.length) {
                        dest[name] = mergeProps(complexObjs);
                    }
                }
            }
        }
        // copy values into the destination, going from last to first
        for (let i = propObjs.length - 1; i >= 0; i -= 1) {
            let props = propObjs[i];
            for (let name in props) {
                if (!(name in dest)) { // if already assigned by previous props or complex props, don't reassign
                    dest[name] = props[name];
                }
            }
        }
        return dest;
    }

    function filterHash(hash, func) {
        let filtered = {};
        for (let key in hash) {
            if (func(hash[key], key)) {
                filtered[key] = hash[key];
            }
        }
        return filtered;
    }

    function mapHash(hash, func) {
        let newHash = {};
        for (let key in hash) {
            newHash[key] = func(hash[key], key);
        }
        return newHash;
    }

    function arrayToHash(a) {
        let hash = {};
        for (let item of a) {
            hash[item] = true;
        }
        return hash;
    }
    // TODO: reassess browser support
    // https://caniuse.com/?search=object.values
    function hashValuesToArray(obj) {
        let a = [];
        for (let key in obj) {
            a.push(obj[key]);
        }
        return a;
    }

    function isPropsEqual(obj0, obj1) {
        if (obj0 === obj1) {
            return true;
        }
        for (let key in obj0) {
            if (hasOwnProperty.call(obj0, key)) {
                if (!(key in obj1)) {
                    return false;
                }
            }
        }
        for (let key in obj1) {
            if (hasOwnProperty.call(obj1, key)) {
                if (obj0[key] !== obj1[key]) {
                    return false;
                }
            }
        }
        return true;
    }
    const HANDLER_RE = /^on[A-Z]/;

    function isNonHandlerPropsEqual(obj0, obj1) {
        const keys = getUnequalProps(obj0, obj1);
        for (let key of keys) {
            if (!HANDLER_RE.test(key)) {
                return false;
            }
        }
        return true;
    }

    function getUnequalProps(obj0, obj1) {
        let keys = [];
        for (let key in obj0) {
            if (hasOwnProperty.call(obj0, key)) {
                if (!(key in obj1)) {
                    keys.push(key);
                }
            }
        }
        for (let key in obj1) {
            if (hasOwnProperty.call(obj1, key)) {
                if (obj0[key] !== obj1[key]) {
                    keys.push(key);
                }
            }
        }
        return keys;
    }

    function compareObjs(oldProps, newProps, equalityFuncs = {}) {
        if (oldProps === newProps) {
            return true;
        }
        // if (debug) {
        //   for (let key in newProps) {
        //     if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key])) {
        //       // equal
        //     } else {
        //       if (debug) {
        //         console.log('prop difference', key, oldProps[key], newProps[key])
        //       }
        //     }
        //   }
        //   // check for props that were omitted in the new
        //   for (let key in oldProps) {
        //     if (!(key in newProps)) {
        //       if (debug) {
        //         console.log('prop absent', key)
        //       }
        //     }
        //   }
        // }
        for (let key in newProps) {
            if (key in oldProps && isObjValsEqual(oldProps[key], newProps[key], equalityFuncs[key]));
            else {
                return false;
            }
        }
        // check for props that were omitted in the new
        for (let key in oldProps) {
            if (!(key in newProps)) {
                return false;
            }
        }
        return true;
    }
    /*
    assumed "true" equality for handler names like "onReceiveSomething"
    */
    function isObjValsEqual(val0, val1, comparator) {
        if (val0 === val1 || comparator === true) {
            return true;
        }
        if (comparator) {
            return comparator(val0, val1);
        }
        return false;
    }

    function collectFromHash(hash, startIndex = 0, endIndex, step = 1) {
        let res = [];
        if (endIndex == null) {
            endIndex = Object.keys(hash).length;
        }
        for (let i = startIndex; i < endIndex; i += step) {
            let val = hash[i];
            if (val !== undefined) { // will disregard undefined for sparse arrays
                res.push(val);
            }
        }
        return res;
    }

    let calendarSystemClassMap = {};

    function registerCalendarSystem(name, theClass) {
        calendarSystemClassMap[name] = theClass;
    }

    function createCalendarSystem(name) {
        return new calendarSystemClassMap[name]();
    }
    class GregorianCalendarSystem {
        getMarkerYear(d) {
            return d.getUTCFullYear();
        }
        getMarkerMonth(d) {
            return d.getUTCMonth();
        }
        getMarkerDay(d) {
            return d.getUTCDate();
        }
        arrayToMarker(arr) {
            return arrayToUtcDate(arr);
        }
        markerToArray(marker) {
            return dateToUtcArray(marker);
        }
    }
    registerCalendarSystem('gregory', GregorianCalendarSystem);

    const ISO_RE = /^\s*(\d{4})(-?(\d{2})(-?(\d{2})([T ](\d{2}):?(\d{2})(:?(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/;

    function parse(str) {
        let m = ISO_RE.exec(str);
        if (m) {
            let marker = new Date(Date.UTC(Number(m[1]), m[3] ? Number(m[3]) - 1 : 0, Number(m[5] || 1), Number(m[7] || 0), Number(m[8] || 0), Number(m[10] || 0), m[12] ? Number(`0.${m[12]}`) * 1000 : 0));
            if (isValidDate(marker)) {
                let timeZoneOffset = null;
                if (m[13]) {
                    timeZoneOffset = (m[15] === '-' ? -1 : 1) * (Number(m[16] || 0) * 60 +
                        Number(m[18] || 0));
                }
                return {
                    marker,
                    isTimeUnspecified: !m[6],
                    timeZoneOffset,
                };
            }
        }
        return null;
    }

    class DateEnv {
        constructor(settings) {
            let timeZone = this.timeZone = settings.timeZone;
            let isNamedTimeZone = timeZone !== 'local' && timeZone !== 'UTC';
            if (settings.namedTimeZoneImpl && isNamedTimeZone) {
                this.namedTimeZoneImpl = new settings.namedTimeZoneImpl(timeZone);
            }
            this.canComputeOffset = Boolean(!isNamedTimeZone || this.namedTimeZoneImpl);
            this.calendarSystem = createCalendarSystem(settings.calendarSystem);
            this.locale = settings.locale;
            this.weekDow = settings.locale.week.dow;
            this.weekDoy = settings.locale.week.doy;
            if (settings.weekNumberCalculation === 'ISO') {
                this.weekDow = 1;
                this.weekDoy = 4;
            }
            if (typeof settings.firstDay === 'number') {
                this.weekDow = settings.firstDay;
            }
            if (typeof settings.weekNumberCalculation === 'function') {
                this.weekNumberFunc = settings.weekNumberCalculation;
            }
            this.weekText = settings.weekText != null ? settings.weekText : settings.locale.options.weekText;
            this.weekTextLong = (settings.weekTextLong != null ? settings.weekTextLong : settings.locale.options.weekTextLong) || this.weekText;
            this.cmdFormatter = settings.cmdFormatter;
            this.defaultSeparator = settings.defaultSeparator;
        }
        // Creating / Parsing
        createMarker(input) {
            let meta = this.createMarkerMeta(input);
            if (meta === null) {
                return null;
            }
            return meta.marker;
        }
        createNowMarker() {
            if (this.canComputeOffset) {
                return this.timestampToMarker(new Date().valueOf());
            }
            // if we can't compute the current date val for a timezone,
            // better to give the current local date vals than UTC
            return arrayToUtcDate(dateToLocalArray(new Date()));
        }
        createMarkerMeta(input) {
            if (typeof input === 'string') {
                return this.parse(input);
            }
            let marker = null;
            if (typeof input === 'number') {
                marker = this.timestampToMarker(input);
            } else if (input instanceof Date) {
                input = input.valueOf();
                if (!isNaN(input)) {
                    marker = this.timestampToMarker(input);
                }
            } else if (Array.isArray(input)) {
                marker = arrayToUtcDate(input);
            }
            if (marker === null || !isValidDate(marker)) {
                return null;
            }
            return {
                marker,
                isTimeUnspecified: false,
                forcedTzo: null
            };
        }
        parse(s) {
            let parts = parse(s);
            if (parts === null) {
                return null;
            }
            let {
                marker
            } = parts;
            let forcedTzo = null;
            if (parts.timeZoneOffset !== null) {
                if (this.canComputeOffset) {
                    marker = this.timestampToMarker(marker.valueOf() - parts.timeZoneOffset * 60 * 1000);
                } else {
                    forcedTzo = parts.timeZoneOffset;
                }
            }
            return {
                marker,
                isTimeUnspecified: parts.isTimeUnspecified,
                forcedTzo
            };
        }
        // Accessors
        getYear(marker) {
            return this.calendarSystem.getMarkerYear(marker);
        }
        getMonth(marker) {
            return this.calendarSystem.getMarkerMonth(marker);
        }
        getDay(marker) {
            return this.calendarSystem.getMarkerDay(marker);
        }
        // Adding / Subtracting
        add(marker, dur) {
            let a = this.calendarSystem.markerToArray(marker);
            a[0] += dur.years;
            a[1] += dur.months;
            a[2] += dur.days;
            a[6] += dur.milliseconds;
            return this.calendarSystem.arrayToMarker(a);
        }
        subtract(marker, dur) {
            let a = this.calendarSystem.markerToArray(marker);
            a[0] -= dur.years;
            a[1] -= dur.months;
            a[2] -= dur.days;
            a[6] -= dur.milliseconds;
            return this.calendarSystem.arrayToMarker(a);
        }
        addYears(marker, n) {
            let a = this.calendarSystem.markerToArray(marker);
            a[0] += n;
            return this.calendarSystem.arrayToMarker(a);
        }
        addMonths(marker, n) {
            let a = this.calendarSystem.markerToArray(marker);
            a[1] += n;
            return this.calendarSystem.arrayToMarker(a);
        }
        // Diffing Whole Units
        diffWholeYears(m0, m1) {
            let {
                calendarSystem
            } = this;
            if (timeAsMs(m0) === timeAsMs(m1) &&
                calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1) &&
                calendarSystem.getMarkerMonth(m0) === calendarSystem.getMarkerMonth(m1)) {
                return calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0);
            }
            return null;
        }
        diffWholeMonths(m0, m1) {
            let {
                calendarSystem
            } = this;
            if (timeAsMs(m0) === timeAsMs(m1) &&
                calendarSystem.getMarkerDay(m0) === calendarSystem.getMarkerDay(m1)) {
                return (calendarSystem.getMarkerMonth(m1) - calendarSystem.getMarkerMonth(m0)) +
                    (calendarSystem.getMarkerYear(m1) - calendarSystem.getMarkerYear(m0)) * 12;
            }
            return null;
        }
        // Range / Duration
        greatestWholeUnit(m0, m1) {
            let n = this.diffWholeYears(m0, m1);
            if (n !== null) {
                return {
                    unit: 'year',
                    value: n
                };
            }
            n = this.diffWholeMonths(m0, m1);
            if (n !== null) {
                return {
                    unit: 'month',
                    value: n
                };
            }
            n = diffWholeWeeks(m0, m1);
            if (n !== null) {
                return {
                    unit: 'week',
                    value: n
                };
            }
            n = diffWholeDays(m0, m1);
            if (n !== null) {
                return {
                    unit: 'day',
                    value: n
                };
            }
            n = diffHours(m0, m1);
            if (isInt(n)) {
                return {
                    unit: 'hour',
                    value: n
                };
            }
            n = diffMinutes(m0, m1);
            if (isInt(n)) {
                return {
                    unit: 'minute',
                    value: n
                };
            }
            n = diffSeconds(m0, m1);
            if (isInt(n)) {
                return {
                    unit: 'second',
                    value: n
                };
            }
            return {
                unit: 'millisecond',
                value: m1.valueOf() - m0.valueOf()
            };
        }
        countDurationsBetween(m0, m1, d) {
            // TODO: can use greatestWholeUnit
            let diff;
            if (d.years) {
                diff = this.diffWholeYears(m0, m1);
                if (diff !== null) {
                    return diff / asRoughYears(d);
                }
            }
            if (d.months) {
                diff = this.diffWholeMonths(m0, m1);
                if (diff !== null) {
                    return diff / asRoughMonths(d);
                }
            }
            if (d.days) {
                diff = diffWholeDays(m0, m1);
                if (diff !== null) {
                    return diff / asRoughDays(d);
                }
            }
            return (m1.valueOf() - m0.valueOf()) / asRoughMs(d);
        }
        // Start-Of
        // these DON'T return zoned-dates. only UTC start-of dates
        startOf(m, unit) {
            if (unit === 'year') {
                return this.startOfYear(m);
            }
            if (unit === 'month') {
                return this.startOfMonth(m);
            }
            if (unit === 'week') {
                return this.startOfWeek(m);
            }
            if (unit === 'day') {
                return startOfDay(m);
            }
            if (unit === 'hour') {
                return startOfHour(m);
            }
            if (unit === 'minute') {
                return startOfMinute(m);
            }
            if (unit === 'second') {
                return startOfSecond(m);
            }
            return null;
        }
        startOfYear(m) {
            return this.calendarSystem.arrayToMarker([
                this.calendarSystem.getMarkerYear(m),
            ]);
        }
        startOfMonth(m) {
            return this.calendarSystem.arrayToMarker([
                this.calendarSystem.getMarkerYear(m),
                this.calendarSystem.getMarkerMonth(m),
            ]);
        }
        startOfWeek(m) {
            return this.calendarSystem.arrayToMarker([
                this.calendarSystem.getMarkerYear(m),
                this.calendarSystem.getMarkerMonth(m),
                m.getUTCDate() - ((m.getUTCDay() - this.weekDow + 7) % 7),
            ]);
        }
        // Week Number
        computeWeekNumber(marker) {
            if (this.weekNumberFunc) {
                return this.weekNumberFunc(this.toDate(marker));
            }
            return weekOfYear(marker, this.weekDow, this.weekDoy);
        }
        // TODO: choke on timeZoneName: long
        format(marker, formatter, dateOptions = {}) {
            return formatter.format({
                marker,
                timeZoneOffset: dateOptions.forcedTzo != null ?
                    dateOptions.forcedTzo : this.offsetForMarker(marker),
            }, this);
        }
        formatRange(start, end, formatter, dateOptions = {}) {
            if (dateOptions.isEndExclusive) {
                end = addMs(end, -1);
            }
            return formatter.formatRange({
                marker: start,
                timeZoneOffset: dateOptions.forcedStartTzo != null ?
                    dateOptions.forcedStartTzo : this.offsetForMarker(start),
            }, {
                marker: end,
                timeZoneOffset: dateOptions.forcedEndTzo != null ?
                    dateOptions.forcedEndTzo : this.offsetForMarker(end),
            }, this, dateOptions.defaultSeparator);
        }
        /*
        DUMB: the omitTime arg is dumb. if we omit the time, we want to omit the timezone offset. and if we do that,
        might as well use buildIsoString or some other util directly
        */
        formatIso(marker, extraOptions = {}) {
            let timeZoneOffset = null;
            if (!extraOptions.omitTimeZoneOffset) {
                if (extraOptions.forcedTzo != null) {
                    timeZoneOffset = extraOptions.forcedTzo;
                } else {
                    timeZoneOffset = this.offsetForMarker(marker);
                }
            }
            return buildIsoString(marker, timeZoneOffset, extraOptions.omitTime);
        }
        // TimeZone
        timestampToMarker(ms) {
            if (this.timeZone === 'local') {
                return arrayToUtcDate(dateToLocalArray(new Date(ms)));
            }
            if (this.timeZone === 'UTC' || !this.namedTimeZoneImpl) {
                return new Date(ms);
            }
            return arrayToUtcDate(this.namedTimeZoneImpl.timestampToArray(ms));
        }
        offsetForMarker(m) {
            if (this.timeZone === 'local') {
                return -arrayToLocalDate(dateToUtcArray(m)).getTimezoneOffset(); // convert "inverse" offset to "normal" offset
            }
            if (this.timeZone === 'UTC') {
                return 0;
            }
            if (this.namedTimeZoneImpl) {
                return this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m));
            }
            return null;
        }
        // Conversion
        toDate(m, forcedTzo) {
            if (this.timeZone === 'local') {
                return arrayToLocalDate(dateToUtcArray(m));
            }
            if (this.timeZone === 'UTC') {
                return new Date(m.valueOf()); // make sure it's a copy
            }
            if (!this.namedTimeZoneImpl) {
                return new Date(m.valueOf() - (forcedTzo || 0));
            }
            return new Date(m.valueOf() -
                this.namedTimeZoneImpl.offsetForArray(dateToUtcArray(m)) * 1000 * 60);
        }
    }

    class Theme {
        constructor(calendarOptions) {
            if (this.iconOverrideOption) {
                this.setIconOverride(calendarOptions[this.iconOverrideOption]);
            }
        }
        setIconOverride(iconOverrideHash) {
            let iconClassesCopy;
            let buttonName;
            if (typeof iconOverrideHash === 'object' && iconOverrideHash) { // non-null object
                iconClassesCopy = Object.assign({}, this.iconClasses);
                for (buttonName in iconOverrideHash) {
                    iconClassesCopy[buttonName] = this.applyIconOverridePrefix(iconOverrideHash[buttonName]);
                }
                this.iconClasses = iconClassesCopy;
            } else if (iconOverrideHash === false) {
                this.iconClasses = {};
            }
        }
        applyIconOverridePrefix(className) {
            let prefix = this.iconOverridePrefix;
            if (prefix && className.indexOf(prefix) !== 0) { // if not already present
                className = prefix + className;
            }
            return className;
        }
        getClass(key) {
            return this.classes[key] || '';
        }
        getIconClass(buttonName, isRtl) {
            let className;
            if (isRtl && this.rtlIconClasses) {
                className = this.rtlIconClasses[buttonName] || this.iconClasses[buttonName];
            } else {
                className = this.iconClasses[buttonName];
            }
            if (className) {
                return `${this.baseIconClass} ${className}`;
            }
            return '';
        }
        getCustomButtonIconClass(customButtonProps) {
            let className;
            if (this.iconOverrideCustomButtonOption) {
                className = customButtonProps[this.iconOverrideCustomButtonOption];
                if (className) {
                    return `${this.baseIconClass} ${this.applyIconOverridePrefix(className)}`;
                }
            }
            return '';
        }
    }
    Theme.prototype.classes = {};
    Theme.prototype.iconClasses = {};
    Theme.prototype.baseIconClass = '';
    Theme.prototype.iconOverridePrefix = '';

    /*
    NOTE: this can be a public API, especially createElement for hooks.
    See examples/typescript-scheduler/src/index.ts
    */
    function flushSync(runBeforeFlush) {
        runBeforeFlush();
        let oldDebounceRendering = l$1.debounceRendering; // orig
        let callbackQ = [];

        function execCallbackSync(callback) {
            callbackQ.push(callback);
        }
        l$1.debounceRendering = execCallbackSync;
        D$1(y(FakeComponent, {}), document.createElement('div'));
        while (callbackQ.length) {
            callbackQ.shift()();
        }
        l$1.debounceRendering = oldDebounceRendering;
    }
    class FakeComponent extends x$1 {
        render() {
            return y('div', {});
        }
        componentDidMount() {
            this.setState({});
        }
    }
    // TODO: use preact/compat instead?
    function createContext(defaultValue) {
        let ContextType = G$1(defaultValue);
        let origProvider = ContextType.Provider;
        ContextType.Provider = function() {
            let isNew = !this.getChildContext;
            let children = origProvider.apply(this, arguments); // eslint-disable-line prefer-rest-params
            if (isNew) {
                let subs = [];
                this.shouldComponentUpdate = (_props) => {
                    if (this.props.value !== _props.value) {
                        subs.forEach((c) => {
                            c.context = _props.value;
                            c.forceUpdate();
                        });
                    }
                };
                this.sub = (c) => {
                    subs.push(c);
                    let old = c.componentWillUnmount;
                    c.componentWillUnmount = () => {
                        subs.splice(subs.indexOf(c), 1);
                        old && old.call(c);
                    };
                };
            }
            return children;
        };
        return ContextType;
    }

    class ScrollResponder {
        constructor(execFunc, emitter, scrollTime, scrollTimeReset) {
            this.execFunc = execFunc;
            this.emitter = emitter;
            this.scrollTime = scrollTime;
            this.scrollTimeReset = scrollTimeReset;
            this.handleScrollRequest = (request) => {
                this.queuedRequest = Object.assign({}, this.queuedRequest || {}, request);
                this.drain();
            };
            emitter.on('_scrollRequest', this.handleScrollRequest);
            this.fireInitialScroll();
        }
        detach() {
            this.emitter.off('_scrollRequest', this.handleScrollRequest);
        }
        update(isDatesNew) {
            if (isDatesNew && this.scrollTimeReset) {
                this.fireInitialScroll(); // will drain
            } else {
                this.drain();
            }
        }
        fireInitialScroll() {
            this.handleScrollRequest({
                time: this.scrollTime,
            });
        }
        drain() {
            if (this.queuedRequest && this.execFunc(this.queuedRequest)) {
                this.queuedRequest = null;
            }
        }
    }

    const ViewContextType = createContext({}); // for Components
    function buildViewContext(viewSpec, viewApi, viewOptions, dateProfileGenerator, dateEnv, nowManager, theme, pluginHooks, dispatch, getCurrentData, emitter, calendarApi, registerInteractiveComponent, unregisterInteractiveComponent) {
        return {
            dateEnv,
            nowManager,
            options: viewOptions,
            pluginHooks,
            emitter,
            dispatch,
            getCurrentData,
            calendarApi,
            viewSpec,
            viewApi,
            dateProfileGenerator,
            theme,
            isRtl: viewOptions.direction === 'rtl',
            addResizeHandler(handler) {
                emitter.on('_resize', handler);
            },
            removeResizeHandler(handler) {
                emitter.off('_resize', handler);
            },
            createScrollResponder(execFunc) {
                return new ScrollResponder(execFunc, emitter, createDuration(viewOptions.scrollTime), viewOptions.scrollTimeReset);
            },
            registerInteractiveComponent,
            unregisterInteractiveComponent,
        };
    }

    /* eslint max-classes-per-file: off */
    class PureComponent extends x$1 {
        // debug: boolean
        shouldComponentUpdate(nextProps, nextState) {
            const shouldUpdate = !compareObjs(this.props, nextProps, this.propEquality /*, this.debug */ ) ||
                !compareObjs(this.state, nextState, this.stateEquality /*, this.debug */ );
            // if (this.debug && shouldUpdate) {
            //   console.log('shouldUpdate!')
            // }
            return shouldUpdate;
        }
        // HACK for freakin' React StrictMode
        safeSetState(newState) {
            if (!compareObjs(this.state, Object.assign(Object.assign({}, this.state), newState), this.stateEquality)) {
                this.setState(newState);
            }
        }
    }
    PureComponent.addPropsEquality = addPropsEquality;
    PureComponent.addStateEquality = addStateEquality;
    PureComponent.contextType = ViewContextType;
    PureComponent.prototype.propEquality = {};
    PureComponent.prototype.stateEquality = {};
    class BaseComponent extends PureComponent {}
    BaseComponent.contextType = ViewContextType;

    function addPropsEquality(propEquality) {
        let hash = Object.create(this.prototype.propEquality);
        Object.assign(hash, propEquality);
        this.prototype.propEquality = hash;
    }

    function addStateEquality(stateEquality) {
        let hash = Object.create(this.prototype.stateEquality);
        Object.assign(hash, stateEquality);
        this.prototype.stateEquality = hash;
    }
    // use other one
    function setRef(ref, current) {
        if (typeof ref === 'function') {
            ref(current);
        } else if (ref) {
            // see https://github.com/facebook/react/issues/13029
            ref.current = current;
        }
    }

    class ContentInjector extends BaseComponent {
        constructor() {
            super(...arguments);
            this.id = guid();
            this.queuedDomNodes = [];
            this.currentDomNodes = [];
            this.handleEl = (el) => {
                const {
                    options
                } = this.context;
                const {
                    generatorName
                } = this.props;
                if (!options.customRenderingReplaces || !hasCustomRenderingHandler(generatorName, options)) {
                    this.updateElRef(el);
                }
            };
            this.updateElRef = (el) => {
                if (this.props.elRef) {
                    setRef(this.props.elRef, el);
                }
            };
        }
        render() {
            const {
                props,
                context
            } = this;
            const {
                options
            } = context;
            const {
                customGenerator,
                defaultGenerator,
                renderProps
            } = props;
            const attrs = buildElAttrs(props, [], this.handleEl);
            let useDefault = false;
            let innerContent;
            let queuedDomNodes = [];
            let currentGeneratorMeta;
            if (customGenerator != null) {
                const customGeneratorRes = typeof customGenerator === 'function' ?
                    customGenerator(renderProps, y) :
                    customGenerator;
                if (customGeneratorRes === true) {
                    useDefault = true;
                } else {
                    const isObject = customGeneratorRes && typeof customGeneratorRes === 'object'; // non-null
                    if (isObject && ('html' in customGeneratorRes)) {
                        attrs.dangerouslySetInnerHTML = {
                            __html: customGeneratorRes.html
                        };
                    } else if (isObject && ('domNodes' in customGeneratorRes)) {
                        queuedDomNodes = Array.prototype.slice.call(customGeneratorRes.domNodes);
                    } else if (isObject ?
                        i$1(customGeneratorRes) // vdom node
                        :
                        typeof customGeneratorRes !== 'function' // primitive value (like string or number)
                    ) {
                        // use in vdom
                        innerContent = customGeneratorRes;
                    } else {
                        // an exotic object for handleCustomRendering
                        currentGeneratorMeta = customGeneratorRes;
                    }
                }
            } else {
                useDefault = !hasCustomRenderingHandler(props.generatorName, options);
            }
            if (useDefault && defaultGenerator) {
                innerContent = defaultGenerator(renderProps);
            }
            this.queuedDomNodes = queuedDomNodes;
            this.currentGeneratorMeta = currentGeneratorMeta;
            return y(props.elTag, attrs, innerContent);
        }
        componentDidMount() {
            this.applyQueueudDomNodes();
            this.triggerCustomRendering(true);
        }
        componentDidUpdate() {
            this.applyQueueudDomNodes();
            this.triggerCustomRendering(true);
        }
        componentWillUnmount() {
            this.triggerCustomRendering(false); // TODO: different API for removal?
        }
        triggerCustomRendering(isActive) {
            var _a;
            const {
                props,
                context
            } = this;
            const {
                handleCustomRendering,
                customRenderingMetaMap
            } = context.options;
            if (handleCustomRendering) {
                const generatorMeta = (_a = this.currentGeneratorMeta) !== null && _a !== void 0 ? _a : customRenderingMetaMap === null || customRenderingMetaMap === void 0 ? void 0 : customRenderingMetaMap[props.generatorName];
                if (generatorMeta) {
                    handleCustomRendering(Object.assign(Object.assign({
                        id: this.id,
                        isActive,
                        containerEl: this.base,
                        reportNewContainerEl: this.updateElRef, // front-end framework tells us about new container els
                        generatorMeta
                    }, props), {
                        elClasses: (props.elClasses || []).filter(isTruthy)
                    }));
                }
            }
        }
        applyQueueudDomNodes() {
            const {
                queuedDomNodes,
                currentDomNodes
            } = this;
            const el = this.base;
            if (!isArraysEqual(queuedDomNodes, currentDomNodes)) {
                currentDomNodes.forEach(removeElement);
                for (let newNode of queuedDomNodes) {
                    el.appendChild(newNode);
                }
                this.currentDomNodes = queuedDomNodes;
            }
        }
    }
    ContentInjector.addPropsEquality({
        elClasses: isArraysEqual,
        elStyle: isPropsEqual,
        elAttrs: isNonHandlerPropsEqual,
        renderProps: isPropsEqual,
    });
    // Util
    /*
    Does UI-framework provide custom way of rendering that does not use Preact VDOM
    AND does the calendar's options define custom rendering?
    AKA. Should we NOT render the default content?
    */
    function hasCustomRenderingHandler(generatorName, options) {
        var _a;
        return Boolean(options.handleCustomRendering &&
            generatorName &&
            ((_a = options.customRenderingMetaMap) === null || _a === void 0 ? void 0 : _a[generatorName]));
    }

    function buildElAttrs(props, extraClassNames, elRef) {
        const attrs = Object.assign(Object.assign({}, props.elAttrs), {
            ref: elRef
        });
        if (props.elClasses || extraClassNames) {
            attrs.className = (props.elClasses || [])
                .concat(extraClassNames || [])
                .concat(attrs.className || [])
                .filter(Boolean)
                .join(' ');
        }
        if (props.elStyle) {
            attrs.style = props.elStyle;
        }
        return attrs;
    }

    function isTruthy(val) {
        return Boolean(val);
    }

    const RenderId = createContext(0);

    class ContentContainer extends x$1 {
        constructor() {
            super(...arguments);
            this.InnerContent = InnerContentInjector.bind(undefined, this);
            this.handleEl = (el) => {
                this.el = el;
                if (this.props.elRef) {
                    setRef(this.props.elRef, el);
                    if (el && this.didMountMisfire) {
                        this.componentDidMount();
                    }
                }
            };
        }
        render() {
            const {
                props
            } = this;
            const generatedClassNames = generateClassNames(props.classNameGenerator, props.renderProps);
            if (props.children) {
                const elAttrs = buildElAttrs(props, generatedClassNames, this.handleEl);
                const children = props.children(this.InnerContent, props.renderProps, elAttrs);
                if (props.elTag) {
                    return y(props.elTag, elAttrs, children);
                } else {
                    return children;
                }
            } else {
                return y((ContentInjector), Object.assign(Object.assign({}, props), {
                    elRef: this.handleEl,
                    elTag: props.elTag || 'div',
                    elClasses: (props.elClasses || []).concat(generatedClassNames),
                    renderId: this.context
                }));
            }
        }
        componentDidMount() {
            var _a, _b;
            if (this.el) {
                (_b = (_a = this.props).didMount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), {
                    el: this.el
                }));
            } else {
                this.didMountMisfire = true;
            }
        }
        componentWillUnmount() {
            var _a, _b;
            (_b = (_a = this.props).willUnmount) === null || _b === void 0 ? void 0 : _b.call(_a, Object.assign(Object.assign({}, this.props.renderProps), {
                el: this.el
            }));
        }
    }
    ContentContainer.contextType = RenderId;

    function InnerContentInjector(containerComponent, props) {
        const parentProps = containerComponent.props;
        return y((ContentInjector), Object.assign({
            renderProps: parentProps.renderProps,
            generatorName: parentProps.generatorName,
            customGenerator: parentProps.customGenerator,
            defaultGenerator: parentProps.defaultGenerator,
            renderId: containerComponent.context
        }, props));
    }
    // Utils
    function generateClassNames(classNameGenerator, renderProps) {
        const classNames = typeof classNameGenerator === 'function' ?
            classNameGenerator(renderProps) :
            classNameGenerator || [];
        return typeof classNames === 'string' ? [classNames] : classNames;
    }

    class ViewContainer extends BaseComponent {
        render() {
            let {
                props,
                context
            } = this;
            let {
                options
            } = context;
            let renderProps = {
                view: context.viewApi
            };
            return (y(ContentContainer, {
                elRef: props.elRef,
                elTag: props.elTag || 'div',
                elAttrs: props.elAttrs,
                elClasses: [
                    ...buildViewClassNames(props.viewSpec),
                    ...(props.elClasses || []),
                ],
                elStyle: props.elStyle,
                renderProps: renderProps,
                classNameGenerator: options.viewClassNames,
                generatorName: undefined,
                didMount: options.viewDidMount,
                willUnmount: options.viewWillUnmount
            }, () => props.children));
        }
    }

    function buildViewClassNames(viewSpec) {
        return [
            `fc-${viewSpec.type}-view`,
            'fc-view',
        ];
    }

    function parseRange(input, dateEnv) {
        let start = null;
        let end = null;
        if (input.start) {
            start = dateEnv.createMarker(input.start);
        }
        if (input.end) {
            end = dateEnv.createMarker(input.end);
        }
        if (!start && !end) {
            return null;
        }
        if (start && end && end < start) {
            return null;
        }
        return {
            start,
            end
        };
    }
    // SIDE-EFFECT: will mutate ranges.
    // Will return a new array result.
    function invertRanges(ranges, constraintRange) {
        let invertedRanges = [];
        let {
            start
        } = constraintRange; // the end of the previous range. the start of the new range
        let i;
        let dateRange;
        // ranges need to be in order. required for our date-walking algorithm
        ranges.sort(compareRanges);
        for (i = 0; i < ranges.length; i += 1) {
            dateRange = ranges[i];
            // add the span of time before the event (if there is any)
            if (dateRange.start > start) { // compare millisecond time (skip any ambig logic)
                invertedRanges.push({
                    start,
                    end: dateRange.start
                });
            }
            if (dateRange.end > start) {
                start = dateRange.end;
            }
        }
        // add the span of time after the last event (if there is any)
        if (start < constraintRange.end) { // compare millisecond time (skip any ambig logic)
            invertedRanges.push({
                start,
                end: constraintRange.end
            });
        }
        return invertedRanges;
    }

    function compareRanges(range0, range1) {
        return range0.start.valueOf() - range1.start.valueOf(); // earlier ranges go first
    }

    function intersectRanges(range0, range1) {
        let {
            start,
            end
        } = range0;
        let newRange = null;
        if (range1.start !== null) {
            if (start === null) {
                start = range1.start;
            } else {
                start = new Date(Math.max(start.valueOf(), range1.start.valueOf()));
            }
        }
        if (range1.end != null) {
            if (end === null) {
                end = range1.end;
            } else {
                end = new Date(Math.min(end.valueOf(), range1.end.valueOf()));
            }
        }
        if (start === null || end === null || start < end) {
            newRange = {
                start,
                end
            };
        }
        return newRange;
    }

    function rangesEqual(range0, range1) {
        return (range0.start === null ? null : range0.start.valueOf()) === (range1.start === null ? null : range1.start.valueOf()) &&
            (range0.end === null ? null : range0.end.valueOf()) === (range1.end === null ? null : range1.end.valueOf());
    }

    function rangesIntersect(range0, range1) {
        return (range0.end === null || range1.start === null || range0.end > range1.start) &&
            (range0.start === null || range1.end === null || range0.start < range1.end);
    }

    function rangeContainsRange(outerRange, innerRange) {
        return (outerRange.start === null || (innerRange.start !== null && innerRange.start >= outerRange.start)) &&
            (outerRange.end === null || (innerRange.end !== null && innerRange.end <= outerRange.end));
    }

    function rangeContainsMarker(range, date) {
        return (range.start === null || date >= range.start) &&
            (range.end === null || date < range.end);
    }
    // If the given date is not within the given range, move it inside.
    // (If it's past the end, make it one millisecond before the end).
    function constrainMarkerToRange(date, range) {
        if (range.start != null && date < range.start) {
            return range.start;
        }
        if (range.end != null && date >= range.end) {
            return new Date(range.end.valueOf() - 1);
        }
        return date;
    }

    /* Date stuff that doesn't belong in datelib core
    ----------------------------------------------------------------------------------------------------------------------*/
    // given a timed range, computes an all-day range that has the same exact duration,
    // but whose start time is aligned with the start of the day.
    function computeAlignedDayRange(timedRange) {
        let dayCnt = Math.floor(diffDays(timedRange.start, timedRange.end)) || 1;
        let start = startOfDay(timedRange.start);
        let end = addDays(start, dayCnt);
        return {
            start,
            end
        };
    }
    // given a timed range, computes an all-day range based on how for the end date bleeds into the next day
    // TODO: give nextDayThreshold a default arg
    function computeVisibleDayRange(timedRange, nextDayThreshold = createDuration(0)) {
        let startDay = null;
        let endDay = null;
        if (timedRange.end) {
            endDay = startOfDay(timedRange.end);
            let endTimeMS = timedRange.end.valueOf() - endDay.valueOf(); // # of milliseconds into `endDay`
            // If the end time is actually inclusively part of the next day and is equal to or
            // beyond the next day threshold, adjust the end to be the exclusive end of `endDay`.
            // Otherwise, leaving it as inclusive will cause it to exclude `endDay`.
            if (endTimeMS && endTimeMS >= asRoughMs(nextDayThreshold)) {
                endDay = addDays(endDay, 1);
            }
        }
        if (timedRange.start) {
            startDay = startOfDay(timedRange.start); // the beginning of the day the range starts
            // If end is within `startDay` but not past nextDayThreshold, assign the default duration of one day.
            if (endDay && endDay <= startDay) {
                endDay = addDays(startDay, 1);
            }
        }
        return {
            start: startDay,
            end: endDay
        };
    }
    // spans from one day into another?
    function isMultiDayRange(range) {
        let visibleRange = computeVisibleDayRange(range);
        return diffDays(visibleRange.start, visibleRange.end) > 1;
    }

    function diffDates(date0, date1, dateEnv, largeUnit) {
        if (largeUnit === 'year') {
            return createDuration(dateEnv.diffWholeYears(date0, date1), 'year');
        }
        if (largeUnit === 'month') {
            return createDuration(dateEnv.diffWholeMonths(date0, date1), 'month');
        }
        return diffDayAndTime(date0, date1); // returns a duration
    }

    class DateProfileGenerator {
        constructor(props) {
            this.props = props;
            this.initHiddenDays();
        }
        /* Date Range Computation
        ------------------------------------------------------------------------------------------------------------------*/
        // Builds a structure with info about what the dates/ranges will be for the "prev" view.
        buildPrev(currentDateProfile, currentDate, forceToValid) {
            let {
                dateEnv
            } = this.props;
            let prevDate = dateEnv.subtract(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
                currentDateProfile.dateIncrement);
            return this.build(prevDate, -1, forceToValid);
        }
        // Builds a structure with info about what the dates/ranges will be for the "next" view.
        buildNext(currentDateProfile, currentDate, forceToValid) {
            let {
                dateEnv
            } = this.props;
            let nextDate = dateEnv.add(dateEnv.startOf(currentDate, currentDateProfile.currentRangeUnit), // important for start-of-month
                currentDateProfile.dateIncrement);
            return this.build(nextDate, 1, forceToValid);
        }
        // Builds a structure holding dates/ranges for rendering around the given date.
        // Optional direction param indicates whether the date is being incremented/decremented
        // from its previous value. decremented = -1, incremented = 1 (default).
        build(currentDate, direction, forceToValid = true) {
            let {
                props
            } = this;
            let validRange;
            let currentInfo;
            let isRangeAllDay;
            let renderRange;
            let activeRange;
            let isValid;
            validRange = this.buildValidRange();
            validRange = this.trimHiddenDays(validRange);
            if (forceToValid) {
                currentDate = constrainMarkerToRange(currentDate, validRange);
            }
            currentInfo = this.buildCurrentRangeInfo(currentDate, direction);
            isRangeAllDay = /^(year|month|week|day)$/.test(currentInfo.unit);
            renderRange = this.buildRenderRange(this.trimHiddenDays(currentInfo.range), currentInfo.unit, isRangeAllDay);
            renderRange = this.trimHiddenDays(renderRange);
            activeRange = renderRange;
            if (!props.showNonCurrentDates) {
                activeRange = intersectRanges(activeRange, currentInfo.range);
            }
            activeRange = this.adjustActiveRange(activeRange);
            activeRange = intersectRanges(activeRange, validRange); // might return null
            // it's invalid if the originally requested date is not contained,
            // or if the range is completely outside of the valid range.
            isValid = rangesIntersect(currentInfo.range, validRange);
            // HACK: constrain to render-range so `currentDate` is more useful to view rendering
            if (!rangeContainsMarker(renderRange, currentDate)) {
                currentDate = renderRange.start;
            }
            return {
                currentDate,
                // constraint for where prev/next operations can go and where events can be dragged/resized to.
                // an object with optional start and end properties.
                validRange,
                // range the view is formally responsible for.
                // for example, a month view might have 1st-31st, excluding padded dates
                currentRange: currentInfo.range,
                // name of largest unit being displayed, like "month" or "week"
                currentRangeUnit: currentInfo.unit,
                isRangeAllDay,
                // dates that display events and accept drag-n-drop
                // will be `null` if no dates accept events
                activeRange,
                // date range with a rendered skeleton
                // includes not-active days that need some sort of DOM
                renderRange,
                // Duration object that denotes the first visible time of any given day
                slotMinTime: props.slotMinTime,
                // Duration object that denotes the exclusive visible end time of any given day
                slotMaxTime: props.slotMaxTime,
                isValid,
                // how far the current date will move for a prev/next operation
                dateIncrement: this.buildDateIncrement(currentInfo.duration),
                // pass a fallback (might be null) ^
            };
        }
        // Builds an object with optional start/end properties.
        // Indicates the minimum/maximum dates to display.
        // not responsible for trimming hidden days.
        buildValidRange() {
            let input = this.props.validRangeInput;
            let simpleInput = typeof input === 'function' ?
                input.call(this.props.calendarApi, this.props.dateEnv.toDate(this.props.nowManager.getDateMarker())) :
                input;
            return this.refineRange(simpleInput) || {
                start: null,
                end: null
            }; // completely open-ended
        }
        // Builds a structure with info about the "current" range, the range that is
        // highlighted as being the current month for example.
        // See build() for a description of `direction`.
        // Guaranteed to have `range` and `unit` properties. `duration` is optional.
        buildCurrentRangeInfo(date, direction) {
            let {
                props
            } = this;
            let duration = null;
            let unit = null;
            let range = null;
            let dayCount;
            if (props.duration) {
                duration = props.duration;
                unit = props.durationUnit;
                range = this.buildRangeFromDuration(date, direction, duration, unit);
            } else if ((dayCount = this.props.dayCount)) {
                unit = 'day';
                range = this.buildRangeFromDayCount(date, direction, dayCount);
            } else if ((range = this.buildCustomVisibleRange(date))) {
                unit = props.dateEnv.greatestWholeUnit(range.start, range.end).unit;
            } else {
                duration = this.getFallbackDuration();
                unit = greatestDurationDenominator(duration).unit;
                range = this.buildRangeFromDuration(date, direction, duration, unit);
            }
            return {
                duration,
                unit,
                range
            };
        }
        getFallbackDuration() {
            return createDuration({
                day: 1
            });
        }
        // Returns a new activeRange to have time values (un-ambiguate)
        // slotMinTime or slotMaxTime causes the range to expand.
        adjustActiveRange(range) {
            let {
                dateEnv,
                usesMinMaxTime,
                slotMinTime,
                slotMaxTime
            } = this.props;
            let {
                start,
                end
            } = range;
            if (usesMinMaxTime) {
                // expand active range if slotMinTime is negative (why not when positive?)
                if (asRoughDays(slotMinTime) < 0) {
                    start = startOfDay(start); // necessary?
                    start = dateEnv.add(start, slotMinTime);
                }
                // expand active range if slotMaxTime is beyond one day (why not when negative?)
                if (asRoughDays(slotMaxTime) > 1) {
                    end = startOfDay(end); // necessary?
                    end = addDays(end, -1);
                    end = dateEnv.add(end, slotMaxTime);
                }
            }
            return {
                start,
                end
            };
        }
        // Builds the "current" range when it is specified as an explicit duration.
        // `unit` is the already-computed greatestDurationDenominator unit of duration.
        buildRangeFromDuration(date, direction, duration, unit) {
            let {
                dateEnv,
                dateAlignment
            } = this.props;
            let start;
            let end;
            let res;
            // compute what the alignment should be
            if (!dateAlignment) {
                let {
                    dateIncrement
                } = this.props;
                if (dateIncrement) {
                    // use the smaller of the two units
                    if (asRoughMs(dateIncrement) < asRoughMs(duration)) {
                        dateAlignment = greatestDurationDenominator(dateIncrement).unit;
                    } else {
                        dateAlignment = unit;
                    }
                } else {
                    dateAlignment = unit;
                }
            }
            // if the view displays a single day or smaller
            if (asRoughDays(duration) <= 1) {
                if (this.isHiddenDay(start)) {
                    start = this.skipHiddenDays(start, direction);
                    start = startOfDay(start);
                }
            }

            function computeRes() {
                start = dateEnv.startOf(date, dateAlignment);
                end = dateEnv.add(start, duration);
                res = {
                    start,
                    end
                };
            }
            computeRes();
            // if range is completely enveloped by hidden days, go past the hidden days
            if (!this.trimHiddenDays(res)) {
                date = this.skipHiddenDays(date, direction);
                computeRes();
            }
            return res;
        }
        // Builds the "current" range when a dayCount is specified.
        buildRangeFromDayCount(date, direction, dayCount) {
            let {
                dateEnv,
                dateAlignment
            } = this.props;
            let runningCount = 0;
            let start = date;
            let end;
            if (dateAlignment) {
                start = dateEnv.startOf(start, dateAlignment);
            }
            start = startOfDay(start);
            start = this.skipHiddenDays(start, direction);
            end = start;
            do {
                end = addDays(end, 1);
                if (!this.isHiddenDay(end)) {
                    runningCount += 1;
                }
            } while (runningCount < dayCount);
            return {
                start,
                end
            };
        }
        // Builds a normalized range object for the "visible" range,
        // which is a way to define the currentRange and activeRange at the same time.
        buildCustomVisibleRange(date) {
            let {
                props
            } = this;
            let input = props.visibleRangeInput;
            let simpleInput = typeof input === 'function' ?
                input.call(props.calendarApi, props.dateEnv.toDate(date)) :
                input;
            let range = this.refineRange(simpleInput);
            if (range && (range.start == null || range.end == null)) {
                return null;
            }
            return range;
        }
        // Computes the range that will represent the element/cells for *rendering*,
        // but which may have voided days/times.
        // not responsible for trimming hidden days.
        buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
            return currentRange;
        }
        // Compute the duration value that should be added/substracted to the current date
        // when a prev/next operation happens.
        buildDateIncrement(fallback) {
            let {
                dateIncrement
            } = this.props;
            let customAlignment;
            if (dateIncrement) {
                return dateIncrement;
            }
            if ((customAlignment = this.props.dateAlignment)) {
                return createDuration(1, customAlignment);
            }
            if (fallback) {
                return fallback;
            }
            return createDuration({
                days: 1
            });
        }
        refineRange(rangeInput) {
            if (rangeInput) {
                let range = parseRange(rangeInput, this.props.dateEnv);
                if (range) {
                    range = computeVisibleDayRange(range);
                }
                return range;
            }
            return null;
        }
        /* Hidden Days
        ------------------------------------------------------------------------------------------------------------------*/
        // Initializes internal variables related to calculating hidden days-of-week
        initHiddenDays() {
            let hiddenDays = this.props.hiddenDays || []; // array of day-of-week indices that are hidden
            let isHiddenDayHash = []; // is the day-of-week hidden? (hash with day-of-week-index -> bool)
            let dayCnt = 0;
            let i;
            if (this.props.weekends === false) {
                hiddenDays.push(0, 6); // 0=sunday, 6=saturday
            }
            for (i = 0; i < 7; i += 1) {
                if (!(isHiddenDayHash[i] = hiddenDays.indexOf(i) !== -1)) {
                    dayCnt += 1;
                }
            }
            if (!dayCnt) {
                throw new Error('invalid hiddenDays'); // all days were hidden? bad.
            }
            this.isHiddenDayHash = isHiddenDayHash;
        }
        // Remove days from the beginning and end of the range that are computed as hidden.
        // If the whole range is trimmed off, returns null
        trimHiddenDays(range) {
            let {
                start,
                end
            } = range;
            if (start) {
                start = this.skipHiddenDays(start);
            }
            if (end) {
                end = this.skipHiddenDays(end, -1, true);
            }
            if (start == null || end == null || start < end) {
                return {
                    start,
                    end
                };
            }
            return null;
        }
        // Is the current day hidden?
        // `day` is a day-of-week index (0-6), or a Date (used for UTC)
        isHiddenDay(day) {
            if (day instanceof Date) {
                day = day.getUTCDay();
            }
            return this.isHiddenDayHash[day];
        }
        // Incrementing the current day until it is no longer a hidden day, returning a copy.
        // DOES NOT CONSIDER validRange!
        // If the initial value of `date` is not a hidden day, don't do anything.
        // Pass `isExclusive` as `true` if you are dealing with an end date.
        // `inc` defaults to `1` (increment one day forward each time)
        skipHiddenDays(date, inc = 1, isExclusive = false) {
            while (this.isHiddenDayHash[(date.getUTCDay() + (isExclusive ? inc : 0) + 7) % 7]) {
                date = addDays(date, inc);
            }
            return date;
        }
    }

    function createEventInstance(defId, range, forcedStartTzo, forcedEndTzo) {
        return {
            instanceId: guid(),
            defId,
            range,
            forcedStartTzo: forcedStartTzo == null ? null : forcedStartTzo,
            forcedEndTzo: forcedEndTzo == null ? null : forcedEndTzo,
        };
    }

    function parseRecurring(refined, defaultAllDay, dateEnv, recurringTypes) {
        for (let i = 0; i < recurringTypes.length; i += 1) {
            let parsed = recurringTypes[i].parse(refined, dateEnv);
            if (parsed) {
                let {
                    allDay
                } = refined;
                if (allDay == null) {
                    allDay = defaultAllDay;
                    if (allDay == null) {
                        allDay = parsed.allDayGuess;
                        if (allDay == null) {
                            allDay = false;
                        }
                    }
                }
                return {
                    allDay,
                    duration: parsed.duration,
                    typeData: parsed.typeData,
                    typeId: i,
                };
            }
        }
        return null;
    }

    function expandRecurring(eventStore, framingRange, context) {
        let {
            dateEnv,
            pluginHooks,
            options
        } = context;
        let {
            defs,
            instances
        } = eventStore;
        // remove existing recurring instances
        // TODO: bad. always expand events as a second step
        instances = filterHash(instances, (instance) => !defs[instance.defId].recurringDef);
        for (let defId in defs) {
            let def = defs[defId];
            if (def.recurringDef) {
                let {
                    duration
                } = def.recurringDef;
                if (!duration) {
                    duration = def.allDay ?
                        options.defaultAllDayEventDuration :
                        options.defaultTimedEventDuration;
                }
                let starts = expandRecurringRanges(def, duration, framingRange, dateEnv, pluginHooks.recurringTypes);
                for (let start of starts) {
                    let instance = createEventInstance(defId, {
                        start,
                        end: dateEnv.add(start, duration),
                    });
                    instances[instance.instanceId] = instance;
                }
            }
        }
        return {
            defs,
            instances
        };
    }
    /*
    Event MUST have a recurringDef
    */
    function expandRecurringRanges(eventDef, duration, framingRange, dateEnv, recurringTypes) {
        let typeDef = recurringTypes[eventDef.recurringDef.typeId];
        let markers = typeDef.expand(eventDef.recurringDef.typeData, {
            start: dateEnv.subtract(framingRange.start, duration),
            end: framingRange.end,
        }, dateEnv);
        // the recurrence plugins don't guarantee that all-day events are start-of-day, so we have to
        if (eventDef.allDay) {
            markers = markers.map(startOfDay);
        }
        return markers;
    }

    const EVENT_NON_DATE_REFINERS = {
        id: String,
        groupId: String,
        title: String,
        url: String,
        interactive: Boolean,
    };
    const EVENT_DATE_REFINERS = {
        start: identity,
        end: identity,
        date: identity,
        allDay: Boolean,
    };
    const EVENT_REFINERS = Object.assign(Object.assign(Object.assign({}, EVENT_NON_DATE_REFINERS), EVENT_DATE_REFINERS), {
        extendedProps: identity
    });

    function parseEvent(raw, eventSource, context, allowOpenRange, refiners = buildEventRefiners(context), defIdMap, instanceIdMap) {
        let {
            refined,
            extra
        } = refineEventDef(raw, context, refiners);
        let defaultAllDay = computeIsDefaultAllDay(eventSource, context);
        let recurringRes = parseRecurring(refined, defaultAllDay, context.dateEnv, context.pluginHooks.recurringTypes);
        if (recurringRes) {
            let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', recurringRes.allDay, Boolean(recurringRes.duration), context, defIdMap);
            def.recurringDef = {
                typeId: recurringRes.typeId,
                typeData: recurringRes.typeData,
                duration: recurringRes.duration,
            };
            return {
                def,
                instance: null
            };
        }
        let singleRes = parseSingle(refined, defaultAllDay, context, allowOpenRange);
        if (singleRes) {
            let def = parseEventDef(refined, extra, eventSource ? eventSource.sourceId : '', singleRes.allDay, singleRes.hasEnd, context, defIdMap);
            let instance = createEventInstance(def.defId, singleRes.range, singleRes.forcedStartTzo, singleRes.forcedEndTzo);
            if (instanceIdMap && def.publicId && instanceIdMap[def.publicId]) {
                instance.instanceId = instanceIdMap[def.publicId];
            }
            return {
                def,
                instance
            };
        }
        return null;
    }

    function refineEventDef(raw, context, refiners = buildEventRefiners(context)) {
        return refineProps(raw, refiners);
    }

    function buildEventRefiners(context) {
        return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_REFINERS), context.pluginHooks.eventRefiners);
    }
    /*
    Will NOT populate extendedProps with the leftover properties.
    Will NOT populate date-related props.
    */
    function parseEventDef(refined, extra, sourceId, allDay, hasEnd, context, defIdMap) {
        let def = {
            title: refined.title || '',
            groupId: refined.groupId || '',
            publicId: refined.id || '',
            url: refined.url || '',
            recurringDef: null,
            defId: ((defIdMap && refined.id) ? defIdMap[refined.id] : '') || guid(),
            sourceId,
            allDay,
            hasEnd,
            interactive: refined.interactive,
            ui: createEventUi(refined, context),
            extendedProps: Object.assign(Object.assign({}, (refined.extendedProps || {})), extra),
        };
        for (let memberAdder of context.pluginHooks.eventDefMemberAdders) {
            Object.assign(def, memberAdder(refined));
        }
        // help out EventImpl from having user modify props
        Object.freeze(def.ui.classNames);
        Object.freeze(def.extendedProps);
        return def;
    }

    function parseSingle(refined, defaultAllDay, context, allowOpenRange) {
        let {
            allDay
        } = refined;
        let startMeta;
        let startMarker = null;
        let hasEnd = false;
        let endMeta;
        let endMarker = null;
        let startInput = refined.start != null ? refined.start : refined.date;
        startMeta = context.dateEnv.createMarkerMeta(startInput);
        if (startMeta) {
            startMarker = startMeta.marker;
        } else if (!allowOpenRange) {
            return null;
        }
        if (refined.end != null) {
            endMeta = context.dateEnv.createMarkerMeta(refined.end);
        }
        if (allDay == null) {
            if (defaultAllDay != null) {
                allDay = defaultAllDay;
            } else {
                // fall back to the date props LAST
                allDay = (!startMeta || startMeta.isTimeUnspecified) &&
                    (!endMeta || endMeta.isTimeUnspecified);
            }
        }
        if (allDay && startMarker) {
            startMarker = startOfDay(startMarker);
        }
        if (endMeta) {
            endMarker = endMeta.marker;
            if (allDay) {
                endMarker = startOfDay(endMarker);
            }
            if (startMarker && endMarker <= startMarker) {
                endMarker = null;
            }
        }
        if (endMarker) {
            hasEnd = true;
        } else if (!allowOpenRange) {
            hasEnd = context.options.forceEventDuration || false;
            endMarker = context.dateEnv.add(startMarker, allDay ?
                context.options.defaultAllDayEventDuration :
                context.options.defaultTimedEventDuration);
        }
        return {
            allDay,
            hasEnd,
            range: {
                start: startMarker,
                end: endMarker
            },
            forcedStartTzo: startMeta ? startMeta.forcedTzo : null,
            forcedEndTzo: endMeta ? endMeta.forcedTzo : null,
        };
    }

    function computeIsDefaultAllDay(eventSource, context) {
        let res = null;
        if (eventSource) {
            res = eventSource.defaultAllDay;
        }
        if (res == null) {
            res = context.options.defaultAllDay;
        }
        return res;
    }

    function parseEvents(rawEvents, eventSource, context, allowOpenRange, defIdMap, instanceIdMap) {
        let eventStore = createEmptyEventStore();
        let eventRefiners = buildEventRefiners(context);
        for (let rawEvent of rawEvents) {
            let tuple = parseEvent(rawEvent, eventSource, context, allowOpenRange, eventRefiners, defIdMap, instanceIdMap);
            if (tuple) {
                eventTupleToStore(tuple, eventStore);
            }
        }
        return eventStore;
    }

    function eventTupleToStore(tuple, eventStore = createEmptyEventStore()) {
        eventStore.defs[tuple.def.defId] = tuple.def;
        if (tuple.instance) {
            eventStore.instances[tuple.instance.instanceId] = tuple.instance;
        }
        return eventStore;
    }
    // retrieves events that have the same groupId as the instance specified by `instanceId`
    // or they are the same as the instance.
    // why might instanceId not be in the store? an event from another calendar?
    function getRelevantEvents(eventStore, instanceId) {
        let instance = eventStore.instances[instanceId];
        if (instance) {
            let def = eventStore.defs[instance.defId];
            // get events/instances with same group
            let newStore = filterEventStoreDefs(eventStore, (lookDef) => isEventDefsGrouped(def, lookDef));
            // add the original
            // TODO: wish we could use eventTupleToStore or something like it
            newStore.defs[def.defId] = def;
            newStore.instances[instance.instanceId] = instance;
            return newStore;
        }
        return createEmptyEventStore();
    }

    function isEventDefsGrouped(def0, def1) {
        return Boolean(def0.groupId && def0.groupId === def1.groupId);
    }

    function createEmptyEventStore() {
        return {
            defs: {},
            instances: {}
        };
    }

    function mergeEventStores(store0, store1) {
        return {
            defs: Object.assign(Object.assign({}, store0.defs), store1.defs),
            instances: Object.assign(Object.assign({}, store0.instances), store1.instances),
        };
    }

    function filterEventStoreDefs(eventStore, filterFunc) {
        let defs = filterHash(eventStore.defs, filterFunc);
        let instances = filterHash(eventStore.instances, (instance) => (defs[instance.defId] // still exists?
        ));
        return {
            defs,
            instances
        };
    }

    function excludeSubEventStore(master, sub) {
        let {
            defs,
            instances
        } = master;
        let filteredDefs = {};
        let filteredInstances = {};
        for (let defId in defs) {
            if (!sub.defs[defId]) { // not explicitly excluded
                filteredDefs[defId] = defs[defId];
            }
        }
        for (let instanceId in instances) {
            if (!sub.instances[instanceId] && // not explicitly excluded
                filteredDefs[instances[instanceId].defId] // def wasn't filtered away
            ) {
                filteredInstances[instanceId] = instances[instanceId];
            }
        }
        return {
            defs: filteredDefs,
            instances: filteredInstances,
        };
    }

    function normalizeConstraint(input, context) {
        if (Array.isArray(input)) {
            return parseEvents(input, null, context, true); // allowOpenRange=true
        }
        if (typeof input === 'object' && input) { // non-null object
            return parseEvents([input], null, context, true); // allowOpenRange=true
        }
        if (input != null) {
            return String(input);
        }
        return null;
    }

    function parseClassNames(raw) {
        if (Array.isArray(raw)) {
            return raw;
        }
        if (typeof raw === 'string') {
            return raw.split(/\s+/);
        }
        return [];
    }

    // TODO: better called "EventSettings" or "EventConfig"
    // TODO: move this file into structs
    // TODO: separate constraint/overlap/allow, because selection uses only that, not other props
    const EVENT_UI_REFINERS = {
        display: String,
        editable: Boolean,
        startEditable: Boolean,
        durationEditable: Boolean,
        constraint: identity,
        overlap: identity,
        allow: identity,
        className: parseClassNames,
        classNames: parseClassNames,
        color: String,
        backgroundColor: String,
        borderColor: String,
        textColor: String,
    };
    const EMPTY_EVENT_UI = {
        display: null,
        startEditable: null,
        durationEditable: null,
        constraints: [],
        overlap: null,
        allows: [],
        backgroundColor: '',
        borderColor: '',
        textColor: '',
        classNames: [],
    };

    function createEventUi(refined, context) {
        let constraint = normalizeConstraint(refined.constraint, context);
        return {
            display: refined.display || null,
            startEditable: refined.startEditable != null ? refined.startEditable : refined.editable,
            durationEditable: refined.durationEditable != null ? refined.durationEditable : refined.editable,
            constraints: constraint != null ? [constraint] : [],
            overlap: refined.overlap != null ? refined.overlap : null,
            allows: refined.allow != null ? [refined.allow] : [],
            backgroundColor: refined.backgroundColor || refined.color || '',
            borderColor: refined.borderColor || refined.color || '',
            textColor: refined.textColor || '',
            classNames: (refined.className || []).concat(refined.classNames || []), // join singular and plural
        };
    }
    // TODO: prevent against problems with <2 args!
    function combineEventUis(uis) {
        return uis.reduce(combineTwoEventUis, EMPTY_EVENT_UI);
    }

    function combineTwoEventUis(item0, item1) {
        return {
            display: item1.display != null ? item1.display : item0.display,
            startEditable: item1.startEditable != null ? item1.startEditable : item0.startEditable,
            durationEditable: item1.durationEditable != null ? item1.durationEditable : item0.durationEditable,
            constraints: item0.constraints.concat(item1.constraints),
            overlap: typeof item1.overlap === 'boolean' ? item1.overlap : item0.overlap,
            allows: item0.allows.concat(item1.allows),
            backgroundColor: item1.backgroundColor || item0.backgroundColor,
            borderColor: item1.borderColor || item0.borderColor,
            textColor: item1.textColor || item0.textColor,
            classNames: item0.classNames.concat(item1.classNames),
        };
    }

    const EVENT_SOURCE_REFINERS = {
        id: String,
        defaultAllDay: Boolean,
        url: String,
        format: String,
        events: identity,
        eventDataTransform: identity,
        // for any network-related sources
        success: identity,
        failure: identity,
    };

    function parseEventSource(raw, context, refiners = buildEventSourceRefiners(context)) {
        let rawObj;
        if (typeof raw === 'string') {
            rawObj = {
                url: raw
            };
        } else if (typeof raw === 'function' || Array.isArray(raw)) {
            rawObj = {
                events: raw
            };
        } else if (typeof raw === 'object' && raw) { // not null
            rawObj = raw;
        }
        if (rawObj) {
            let {
                refined,
                extra
            } = refineProps(rawObj, refiners);
            let metaRes = buildEventSourceMeta(refined, context);
            if (metaRes) {
                return {
                    _raw: raw,
                    isFetching: false,
                    latestFetchId: '',
                    fetchRange: null,
                    defaultAllDay: refined.defaultAllDay,
                    eventDataTransform: refined.eventDataTransform,
                    success: refined.success,
                    failure: refined.failure,
                    publicId: refined.id || '',
                    sourceId: guid(),
                    sourceDefId: metaRes.sourceDefId,
                    meta: metaRes.meta,
                    ui: createEventUi(refined, context),
                    extendedProps: extra,
                };
            }
        }
        return null;
    }

    function buildEventSourceRefiners(context) {
        return Object.assign(Object.assign(Object.assign({}, EVENT_UI_REFINERS), EVENT_SOURCE_REFINERS), context.pluginHooks.eventSourceRefiners);
    }

    function buildEventSourceMeta(raw, context) {
        let defs = context.pluginHooks.eventSourceDefs;
        for (let i = defs.length - 1; i >= 0; i -= 1) { // later-added plugins take precedence
            let def = defs[i];
            let meta = def.parseMeta(raw);
            if (meta) {
                return {
                    sourceDefId: i,
                    meta
                };
            }
        }
        return null;
    }

    function reduceEventStore(eventStore, action, eventSources, dateProfile, context) {
        switch (action.type) {
            case 'RECEIVE_EVENTS': // raw
                return receiveRawEvents(eventStore, eventSources[action.sourceId], action.fetchId, action.fetchRange, action.rawEvents, context);
            case 'RESET_RAW_EVENTS':
                return resetRawEvents(eventStore, eventSources[action.sourceId], action.rawEvents, dateProfile.activeRange, context);
            case 'ADD_EVENTS': // already parsed, but not expanded
                return addEvent(eventStore, action.eventStore, // new ones
                    dateProfile ? dateProfile.activeRange : null, context);
            case 'RESET_EVENTS':
                return action.eventStore;
            case 'MERGE_EVENTS': // already parsed and expanded
                return mergeEventStores(eventStore, action.eventStore);
            case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
            case 'NEXT':
            case 'CHANGE_DATE':
            case 'CHANGE_VIEW_TYPE':
                if (dateProfile) {
                    return expandRecurring(eventStore, dateProfile.activeRange, context);
                }
                return eventStore;
            case 'REMOVE_EVENTS':
                return excludeSubEventStore(eventStore, action.eventStore);
            case 'REMOVE_EVENT_SOURCE':
                return excludeEventsBySourceId(eventStore, action.sourceId);
            case 'REMOVE_ALL_EVENT_SOURCES':
                return filterEventStoreDefs(eventStore, (eventDef) => (!eventDef.sourceId // only keep events with no source id
                ));
            case 'REMOVE_ALL_EVENTS':
                return createEmptyEventStore();
            default:
                return eventStore;
        }
    }

    function receiveRawEvents(eventStore, eventSource, fetchId, fetchRange, rawEvents, context) {
        if (eventSource && // not already removed
            fetchId === eventSource.latestFetchId // TODO: wish this logic was always in event-sources
        ) {
            let subset = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context);
            if (fetchRange) {
                subset = expandRecurring(subset, fetchRange, context);
            }
            return mergeEventStores(excludeEventsBySourceId(eventStore, eventSource.sourceId), subset);
        }
        return eventStore;
    }

    function resetRawEvents(existingEventStore, eventSource, rawEvents, activeRange, context) {
        const {
            defIdMap,
            instanceIdMap
        } = buildPublicIdMaps(existingEventStore);
        let newEventStore = parseEvents(transformRawEvents(rawEvents, eventSource, context), eventSource, context, false, defIdMap, instanceIdMap);
        return expandRecurring(newEventStore, activeRange, context);
    }

    function transformRawEvents(rawEvents, eventSource, context) {
        let calEachTransform = context.options.eventDataTransform;
        let sourceEachTransform = eventSource ? eventSource.eventDataTransform : null;
        if (sourceEachTransform) {
            rawEvents = transformEachRawEvent(rawEvents, sourceEachTransform);
        }
        if (calEachTransform) {
            rawEvents = transformEachRawEvent(rawEvents, calEachTransform);
        }
        return rawEvents;
    }

    function transformEachRawEvent(rawEvents, func) {
        let refinedEvents;
        if (!func) {
            refinedEvents = rawEvents;
        } else {
            refinedEvents = [];
            for (let rawEvent of rawEvents) {
                let refinedEvent = func(rawEvent);
                if (refinedEvent) {
                    refinedEvents.push(refinedEvent);
                } else if (refinedEvent == null) {
                    refinedEvents.push(rawEvent);
                } // if a different falsy value, do nothing
            }
        }
        return refinedEvents;
    }

    function addEvent(eventStore, subset, expandRange, context) {
        if (expandRange) {
            subset = expandRecurring(subset, expandRange, context);
        }
        return mergeEventStores(eventStore, subset);
    }

    function rezoneEventStoreDates(eventStore, oldDateEnv, newDateEnv) {
        let {
            defs
        } = eventStore;
        let instances = mapHash(eventStore.instances, (instance) => {
            let def = defs[instance.defId];
            if (def.allDay) {
                return instance; // isn't dependent on timezone
            }
            return Object.assign(Object.assign({}, instance), {
                range: {
                    start: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.start, instance.forcedStartTzo)),
                    end: newDateEnv.createMarker(oldDateEnv.toDate(instance.range.end, instance.forcedEndTzo)),
                },
                forcedStartTzo: newDateEnv.canComputeOffset ? null : instance.forcedStartTzo,
                forcedEndTzo: newDateEnv.canComputeOffset ? null : instance.forcedEndTzo
            });
        });
        return {
            defs,
            instances
        };
    }

    function excludeEventsBySourceId(eventStore, sourceId) {
        return filterEventStoreDefs(eventStore, (eventDef) => eventDef.sourceId !== sourceId);
    }
    // QUESTION: why not just return instances? do a general object-property-exclusion util
    function excludeInstances(eventStore, removals) {
        return {
            defs: eventStore.defs,
            instances: filterHash(eventStore.instances, (instance) => !removals[instance.instanceId]),
        };
    }

    function buildPublicIdMaps(eventStore) {
        const {
            defs,
            instances
        } = eventStore;
        const defIdMap = {};
        const instanceIdMap = {};
        for (let defId in defs) {
            const def = defs[defId];
            const {
                publicId
            } = def;
            if (publicId) {
                defIdMap[publicId] = defId;
            }
        }
        for (let instanceId in instances) {
            const instance = instances[instanceId];
            const def = defs[instance.defId];
            const {
                publicId
            } = def;
            if (publicId) {
                instanceIdMap[publicId] = instanceId;
            }
        }
        return {
            defIdMap,
            instanceIdMap
        };
    }

    class Emitter {
        constructor() {
            this.handlers = {};
            this.thisContext = null;
        }
        setThisContext(thisContext) {
            this.thisContext = thisContext;
        }
        setOptions(options) {
            this.options = options;
        }
        on(type, handler) {
            addToHash(this.handlers, type, handler);
        }
        off(type, handler) {
            removeFromHash(this.handlers, type, handler);
        }
        trigger(type, ...args) {
            let attachedHandlers = this.handlers[type] || [];
            let optionHandler = this.options && this.options[type];
            let handlers = [].concat(optionHandler || [], attachedHandlers);
            for (let handler of handlers) {
                handler.apply(this.thisContext, args);
            }
        }
        hasHandlers(type) {
            return Boolean((this.handlers[type] && this.handlers[type].length) ||
                (this.options && this.options[type]));
        }
    }

    function addToHash(hash, type, handler) {
        (hash[type] || (hash[type] = []))
        .push(handler);
    }

    function removeFromHash(hash, type, handler) {
        if (handler) {
            if (hash[type]) {
                hash[type] = hash[type].filter((func) => func !== handler);
            }
        } else {
            delete hash[type]; // remove all handler funcs for this type
        }
    }

    const DEF_DEFAULTS = {
        startTime: '09:00',
        endTime: '17:00',
        daysOfWeek: [1, 2, 3, 4, 5],
        display: 'inverse-background',
        classNames: 'fc-non-business',
        groupId: '_businessHours', // so multiple defs get grouped
    };
    /*
    TODO: pass around as EventDefHash!!!
    */
    function parseBusinessHours(input, context) {
        return parseEvents(refineInputs(input), null, context);
    }

    function refineInputs(input) {
        let rawDefs;
        if (input === true) {
            rawDefs = [{}]; // will get DEF_DEFAULTS verbatim
        } else if (Array.isArray(input)) {
            // if specifying an array, every sub-definition NEEDS a day-of-week
            rawDefs = input.filter((rawDef) => rawDef.daysOfWeek);
        } else if (typeof input === 'object' && input) { // non-null object
            rawDefs = [input];
        } else { // is probably false
            rawDefs = [];
        }
        rawDefs = rawDefs.map((rawDef) => (Object.assign(Object.assign({}, DEF_DEFAULTS), rawDef)));
        return rawDefs;
    }

    function triggerDateSelect(selection, pev, context) {
        context.emitter.trigger('select', Object.assign(Object.assign({}, buildDateSpanApiWithContext(selection, context)), {
            jsEvent: pev ? pev.origEvent : null,
            view: context.viewApi || context.calendarApi.view
        }));
    }

    function triggerDateUnselect(pev, context) {
        context.emitter.trigger('unselect', {
            jsEvent: pev ? pev.origEvent : null,
            view: context.viewApi || context.calendarApi.view,
        });
    }

    function buildDateSpanApiWithContext(dateSpan, context) {
        let props = {};
        for (let transform of context.pluginHooks.dateSpanTransforms) {
            Object.assign(props, transform(dateSpan, context));
        }
        Object.assign(props, buildDateSpanApi(dateSpan, context.dateEnv));
        return props;
    }
    // Given an event's allDay status and start date, return what its fallback end date should be.
    // TODO: rename to computeDefaultEventEnd
    function getDefaultEventEnd(allDay, marker, context) {
        let {
            dateEnv,
            options
        } = context;
        let end = marker;
        if (allDay) {
            end = startOfDay(end);
            end = dateEnv.add(end, options.defaultAllDayEventDuration);
        } else {
            end = dateEnv.add(end, options.defaultTimedEventDuration);
        }
        return end;
    }

    // applies the mutation to ALL defs/instances within the event store
    function applyMutationToEventStore(eventStore, eventConfigBase, mutation, context) {
        let eventConfigs = compileEventUis(eventStore.defs, eventConfigBase);
        let dest = createEmptyEventStore();
        for (let defId in eventStore.defs) {
            let def = eventStore.defs[defId];
            dest.defs[defId] = applyMutationToEventDef(def, eventConfigs[defId], mutation, context);
        }
        for (let instanceId in eventStore.instances) {
            let instance = eventStore.instances[instanceId];
            let def = dest.defs[instance.defId]; // important to grab the newly modified def
            dest.instances[instanceId] = applyMutationToEventInstance(instance, def, eventConfigs[instance.defId], mutation, context);
        }
        return dest;
    }

    function applyMutationToEventDef(eventDef, eventConfig, mutation, context) {
        let standardProps = mutation.standardProps || {};
        // if hasEnd has not been specified, guess a good value based on deltas.
        // if duration will change, there's no way the default duration will persist,
        // and thus, we need to mark the event as having a real end
        if (standardProps.hasEnd == null &&
            eventConfig.durationEditable &&
            (mutation.startDelta || mutation.endDelta)) {
            standardProps.hasEnd = true; // TODO: is this mutation okay?
        }
        let copy = Object.assign(Object.assign(Object.assign({}, eventDef), standardProps), {
            ui: Object.assign(Object.assign({}, eventDef.ui), standardProps.ui)
        });
        if (mutation.extendedProps) {
            copy.extendedProps = Object.assign(Object.assign({}, copy.extendedProps), mutation.extendedProps);
        }
        for (let applier of context.pluginHooks.eventDefMutationAppliers) {
            applier(copy, mutation, context);
        }
        if (!copy.hasEnd && context.options.forceEventDuration) {
            copy.hasEnd = true;
        }
        return copy;
    }

    function applyMutationToEventInstance(eventInstance, eventDef, // must first be modified by applyMutationToEventDef
        eventConfig, mutation, context) {
        let {
            dateEnv
        } = context;
        let forceAllDay = mutation.standardProps && mutation.standardProps.allDay === true;
        let clearEnd = mutation.standardProps && mutation.standardProps.hasEnd === false;
        let copy = Object.assign({}, eventInstance);
        if (forceAllDay) {
            copy.range = computeAlignedDayRange(copy.range);
        }
        if (mutation.datesDelta && eventConfig.startEditable) {
            copy.range = {
                start: dateEnv.add(copy.range.start, mutation.datesDelta),
                end: dateEnv.add(copy.range.end, mutation.datesDelta),
            };
        }
        if (mutation.startDelta && eventConfig.durationEditable) {
            copy.range = {
                start: dateEnv.add(copy.range.start, mutation.startDelta),
                end: copy.range.end,
            };
        }
        if (mutation.endDelta && eventConfig.durationEditable) {
            copy.range = {
                start: copy.range.start,
                end: dateEnv.add(copy.range.end, mutation.endDelta),
            };
        }
        if (clearEnd) {
            copy.range = {
                start: copy.range.start,
                end: getDefaultEventEnd(eventDef.allDay, copy.range.start, context),
            };
        }
        // in case event was all-day but the supplied deltas were not
        // better util for this?
        if (eventDef.allDay) {
            copy.range = {
                start: startOfDay(copy.range.start),
                end: startOfDay(copy.range.end),
            };
        }
        // handle invalid durations
        if (copy.range.end < copy.range.start) {
            copy.range.end = getDefaultEventEnd(eventDef.allDay, copy.range.start, context);
        }
        return copy;
    }

    class EventSourceImpl {
        constructor(context, internalEventSource) {
            this.context = context;
            this.internalEventSource = internalEventSource;
        }
        remove() {
            this.context.dispatch({
                type: 'REMOVE_EVENT_SOURCE',
                sourceId: this.internalEventSource.sourceId,
            });
        }
        refetch() {
            this.context.dispatch({
                type: 'FETCH_EVENT_SOURCES',
                sourceIds: [this.internalEventSource.sourceId],
                isRefetch: true,
            });
        }
        get id() {
            return this.internalEventSource.publicId;
        }
        get url() {
            return this.internalEventSource.meta.url;
        }
        get format() {
            return this.internalEventSource.meta.format; // TODO: bad. not guaranteed
        }
    }

    class EventImpl {
        // instance will be null if expressing a recurring event that has no current instances,
        // OR if trying to validate an incoming external event that has no dates assigned
        constructor(context, def, instance) {
            this._context = context;
            this._def = def;
            this._instance = instance || null;
        }
        /*
        TODO: make event struct more responsible for this
        */
        setProp(name, val) {
            if (name in EVENT_DATE_REFINERS) {
                console.warn('Could not set date-related prop \'name\'. Use one of the date-related methods instead.');
                // TODO: make proper aliasing system?
            } else if (name === 'id') {
                val = EVENT_NON_DATE_REFINERS[name](val);
                this.mutate({
                    standardProps: {
                        publicId: val
                    }, // hardcoded internal name
                });
            } else if (name in EVENT_NON_DATE_REFINERS) {
                val = EVENT_NON_DATE_REFINERS[name](val);
                this.mutate({
                    standardProps: {
                        [name]: val
                    },
                });
            } else if (name in EVENT_UI_REFINERS) {
                let ui = EVENT_UI_REFINERS[name](val);
                if (name === 'color') {
                    ui = {
                        backgroundColor: val,
                        borderColor: val
                    };
                } else if (name === 'editable') {
                    ui = {
                        startEditable: val,
                        durationEditable: val
                    };
                } else {
                    ui = {
                        [name]: val
                    };
                }
                this.mutate({
                    standardProps: {
                        ui
                    },
                });
            } else {
                console.warn(`Could not set prop '${name}'. Use setExtendedProp instead.`);
            }
        }
        setExtendedProp(name, val) {
            this.mutate({
                extendedProps: {
                    [name]: val
                },
            });
        }
        setStart(startInput, options = {}) {
            let {
                dateEnv
            } = this._context;
            let start = dateEnv.createMarker(startInput);
            if (start && this._instance) { // TODO: warning if parsed bad
                let instanceRange = this._instance.range;
                let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity); // what if parsed bad!?
                if (options.maintainDuration) {
                    this.mutate({
                        datesDelta: startDelta
                    });
                } else {
                    this.mutate({
                        startDelta
                    });
                }
            }
        }
        setEnd(endInput, options = {}) {
            let {
                dateEnv
            } = this._context;
            let end;
            if (endInput != null) {
                end = dateEnv.createMarker(endInput);
                if (!end) {
                    return; // TODO: warning if parsed bad
                }
            }
            if (this._instance) {
                if (end) {
                    let endDelta = diffDates(this._instance.range.end, end, dateEnv, options.granularity);
                    this.mutate({
                        endDelta
                    });
                } else {
                    this.mutate({
                        standardProps: {
                            hasEnd: false
                        }
                    });
                }
            }
        }
        setDates(startInput, endInput, options = {}) {
            let {
                dateEnv
            } = this._context;
            let standardProps = {
                allDay: options.allDay
            };
            let start = dateEnv.createMarker(startInput);
            let end;
            if (!start) {
                return; // TODO: warning if parsed bad
            }
            if (endInput != null) {
                end = dateEnv.createMarker(endInput);
                if (!end) { // TODO: warning if parsed bad
                    return;
                }
            }
            if (this._instance) {
                let instanceRange = this._instance.range;
                // when computing the diff for an event being converted to all-day,
                // compute diff off of the all-day values the way event-mutation does.
                if (options.allDay === true) {
                    instanceRange = computeAlignedDayRange(instanceRange);
                }
                let startDelta = diffDates(instanceRange.start, start, dateEnv, options.granularity);
                if (end) {
                    let endDelta = diffDates(instanceRange.end, end, dateEnv, options.granularity);
                    if (durationsEqual(startDelta, endDelta)) {
                        this.mutate({
                            datesDelta: startDelta,
                            standardProps
                        });
                    } else {
                        this.mutate({
                            startDelta,
                            endDelta,
                            standardProps
                        });
                    }
                } else { // means "clear the end"
                    standardProps.hasEnd = false;
                    this.mutate({
                        datesDelta: startDelta,
                        standardProps
                    });
                }
            }
        }
        moveStart(deltaInput) {
            let delta = createDuration(deltaInput);
            if (delta) { // TODO: warning if parsed bad
                this.mutate({
                    startDelta: delta
                });
            }
        }
        moveEnd(deltaInput) {
            let delta = createDuration(deltaInput);
            if (delta) { // TODO: warning if parsed bad
                this.mutate({
                    endDelta: delta
                });
            }
        }
        moveDates(deltaInput) {
            let delta = createDuration(deltaInput);
            if (delta) { // TODO: warning if parsed bad
                this.mutate({
                    datesDelta: delta
                });
            }
        }
        setAllDay(allDay, options = {}) {
            let standardProps = {
                allDay
            };
            let {
                maintainDuration
            } = options;
            if (maintainDuration == null) {
                maintainDuration = this._context.options.allDayMaintainDuration;
            }
            if (this._def.allDay !== allDay) {
                standardProps.hasEnd = maintainDuration;
            }
            this.mutate({
                standardProps
            });
        }
        formatRange(formatInput) {
            let {
                dateEnv
            } = this._context;
            let instance = this._instance;
            let formatter = createFormatter(formatInput);
            if (this._def.hasEnd) {
                return dateEnv.formatRange(instance.range.start, instance.range.end, formatter, {
                    forcedStartTzo: instance.forcedStartTzo,
                    forcedEndTzo: instance.forcedEndTzo,
                });
            }
            return dateEnv.format(instance.range.start, formatter, {
                forcedTzo: instance.forcedStartTzo,
            });
        }
        mutate(mutation) {
            let instance = this._instance;
            if (instance) {
                let def = this._def;
                let context = this._context;
                let {
                    eventStore
                } = context.getCurrentData();
                let relevantEvents = getRelevantEvents(eventStore, instance.instanceId);
                let eventConfigBase = {
                    '': {
                        display: '',
                        startEditable: true,
                        durationEditable: true,
                        constraints: [],
                        overlap: null,
                        allows: [],
                        backgroundColor: '',
                        borderColor: '',
                        textColor: '',
                        classNames: [],
                    },
                };
                relevantEvents = applyMutationToEventStore(relevantEvents, eventConfigBase, mutation, context);
                let oldEvent = new EventImpl(context, def, instance); // snapshot
                this._def = relevantEvents.defs[def.defId];
                this._instance = relevantEvents.instances[instance.instanceId];
                context.dispatch({
                    type: 'MERGE_EVENTS',
                    eventStore: relevantEvents,
                });
                context.emitter.trigger('eventChange', {
                    oldEvent,
                    event: this,
                    relatedEvents: buildEventApis(relevantEvents, context, instance),
                    revert() {
                        context.dispatch({
                            type: 'RESET_EVENTS',
                            eventStore, // the ORIGINAL store
                        });
                    },
                });
            }
        }
        remove() {
            let context = this._context;
            let asStore = eventApiToStore(this);
            context.dispatch({
                type: 'REMOVE_EVENTS',
                eventStore: asStore,
            });
            context.emitter.trigger('eventRemove', {
                event: this,
                relatedEvents: [],
                revert() {
                    context.dispatch({
                        type: 'MERGE_EVENTS',
                        eventStore: asStore,
                    });
                },
            });
        }
        get source() {
            let {
                sourceId
            } = this._def;
            if (sourceId) {
                return new EventSourceImpl(this._context, this._context.getCurrentData().eventSources[sourceId]);
            }
            return null;
        }
        get start() {
            return this._instance ?
                this._context.dateEnv.toDate(this._instance.range.start) :
                null;
        }
        get end() {
            return (this._instance && this._def.hasEnd) ?
                this._context.dateEnv.toDate(this._instance.range.end) :
                null;
        }
        get startStr() {
            let instance = this._instance;
            if (instance) {
                return this._context.dateEnv.formatIso(instance.range.start, {
                    omitTime: this._def.allDay,
                    forcedTzo: instance.forcedStartTzo,
                });
            }
            return '';
        }
        get endStr() {
            let instance = this._instance;
            if (instance && this._def.hasEnd) {
                return this._context.dateEnv.formatIso(instance.range.end, {
                    omitTime: this._def.allDay,
                    forcedTzo: instance.forcedEndTzo,
                });
            }
            return '';
        }
        // computable props that all access the def
        // TODO: find a TypeScript-compatible way to do this at scale
        get id() {
            return this._def.publicId;
        }
        get groupId() {
            return this._def.groupId;
        }
        get allDay() {
            return this._def.allDay;
        }
        get title() {
            return this._def.title;
        }
        get url() {
            return this._def.url;
        }
        get display() {
            return this._def.ui.display || 'auto';
        } // bad. just normalize the type earlier
        get startEditable() {
            return this._def.ui.startEditable;
        }
        get durationEditable() {
            return this._def.ui.durationEditable;
        }
        get constraint() {
            return this._def.ui.constraints[0] || null;
        }
        get overlap() {
            return this._def.ui.overlap;
        }
        get allow() {
            return this._def.ui.allows[0] || null;
        }
        get backgroundColor() {
            return this._def.ui.backgroundColor;
        }
        get borderColor() {
            return this._def.ui.borderColor;
        }
        get textColor() {
            return this._def.ui.textColor;
        }
        // NOTE: user can't modify these because Object.freeze was called in event-def parsing
        get classNames() {
            return this._def.ui.classNames;
        }
        get extendedProps() {
            return this._def.extendedProps;
        }
        toPlainObject(settings = {}) {
            let def = this._def;
            let {
                ui
            } = def;
            let {
                startStr,
                endStr
            } = this;
            let res = {
                allDay: def.allDay,
            };
            if (def.title) {
                res.title = def.title;
            }
            if (startStr) {
                res.start = startStr;
            }
            if (endStr) {
                res.end = endStr;
            }
            if (def.publicId) {
                res.id = def.publicId;
            }
            if (def.groupId) {
                res.groupId = def.groupId;
            }
            if (def.url) {
                res.url = def.url;
            }
            if (ui.display && ui.display !== 'auto') {
                res.display = ui.display;
            }
            // TODO: what about recurring-event properties???
            // TODO: include startEditable/durationEditable/constraint/overlap/allow
            if (settings.collapseColor && ui.backgroundColor && ui.backgroundColor === ui.borderColor) {
                res.color = ui.backgroundColor;
            } else {
                if (ui.backgroundColor) {
                    res.backgroundColor = ui.backgroundColor;
                }
                if (ui.borderColor) {
                    res.borderColor = ui.borderColor;
                }
            }
            if (ui.textColor) {
                res.textColor = ui.textColor;
            }
            if (ui.classNames.length) {
                res.classNames = ui.classNames;
            }
            if (Object.keys(def.extendedProps).length) {
                if (settings.collapseExtendedProps) {
                    Object.assign(res, def.extendedProps);
                } else {
                    res.extendedProps = def.extendedProps;
                }
            }
            return res;
        }
        toJSON() {
            return this.toPlainObject();
        }
    }

    function eventApiToStore(eventApi) {
        let def = eventApi._def;
        let instance = eventApi._instance;
        return {
            defs: {
                [def.defId]: def
            },
            instances: instance ?
                {
                    [instance.instanceId]: instance
                } :
                {},
        };
    }

    function buildEventApis(eventStore, context, excludeInstance) {
        let {
            defs,
            instances
        } = eventStore;
        let eventApis = [];
        let excludeInstanceId = excludeInstance ? excludeInstance.instanceId : '';
        for (let id in instances) {
            let instance = instances[id];
            let def = defs[instance.defId];
            if (instance.instanceId !== excludeInstanceId) {
                eventApis.push(new EventImpl(context, def, instance));
            }
        }
        return eventApis;
    }

    /*
    Specifying nextDayThreshold signals that all-day ranges should be sliced.
    */
    function sliceEventStore(eventStore, eventUiBases, framingRange, nextDayThreshold) {
        let inverseBgByGroupId = {};
        let inverseBgByDefId = {};
        let defByGroupId = {};
        let bgRanges = [];
        let fgRanges = [];
        let eventUis = compileEventUis(eventStore.defs, eventUiBases);
        for (let defId in eventStore.defs) {
            let def = eventStore.defs[defId];
            let ui = eventUis[def.defId];
            if (ui.display === 'inverse-background') {
                if (def.groupId) {
                    inverseBgByGroupId[def.groupId] = [];
                    if (!defByGroupId[def.groupId]) {
                        defByGroupId[def.groupId] = def;
                    }
                } else {
                    inverseBgByDefId[defId] = [];
                }
            }
        }
        for (let instanceId in eventStore.instances) {
            let instance = eventStore.instances[instanceId];
            let def = eventStore.defs[instance.defId];
            let ui = eventUis[def.defId];
            let origRange = instance.range;
            let normalRange = (!def.allDay && nextDayThreshold) ?
                computeVisibleDayRange(origRange, nextDayThreshold) :
                origRange;
            let slicedRange = intersectRanges(normalRange, framingRange);
            if (slicedRange) {
                if (ui.display === 'inverse-background') {
                    if (def.groupId) {
                        inverseBgByGroupId[def.groupId].push(slicedRange);
                    } else {
                        inverseBgByDefId[instance.defId].push(slicedRange);
                    }
                } else if (ui.display !== 'none') {
                    (ui.display === 'background' ? bgRanges : fgRanges).push({
                        def,
                        ui,
                        instance,
                        range: slicedRange,
                        isStart: normalRange.start && normalRange.start.valueOf() === slicedRange.start.valueOf(),
                        isEnd: normalRange.end && normalRange.end.valueOf() === slicedRange.end.valueOf(),
                    });
                }
            }
        }
        for (let groupId in inverseBgByGroupId) { // BY GROUP
            let ranges = inverseBgByGroupId[groupId];
            let invertedRanges = invertRanges(ranges, framingRange);
            for (let invertedRange of invertedRanges) {
                let def = defByGroupId[groupId];
                let ui = eventUis[def.defId];
                bgRanges.push({
                    def,
                    ui,
                    instance: null,
                    range: invertedRange,
                    isStart: false,
                    isEnd: false,
                });
            }
        }
        for (let defId in inverseBgByDefId) {
            let ranges = inverseBgByDefId[defId];
            let invertedRanges = invertRanges(ranges, framingRange);
            for (let invertedRange of invertedRanges) {
                bgRanges.push({
                    def: eventStore.defs[defId],
                    ui: eventUis[defId],
                    instance: null,
                    range: invertedRange,
                    isStart: false,
                    isEnd: false,
                });
            }
        }
        return {
            bg: bgRanges,
            fg: fgRanges
        };
    }

    function hasBgRendering(def) {
        return def.ui.display === 'background' || def.ui.display === 'inverse-background';
    }

    function setElSeg(el, seg) {
        el.fcSeg = seg;
    }

    function getElSeg(el) {
        return el.fcSeg ||
            el.parentNode.fcSeg || // for the harness
            null;
    }
    // event ui computation
    function compileEventUis(eventDefs, eventUiBases) {
        return mapHash(eventDefs, (eventDef) => compileEventUi(eventDef, eventUiBases));
    }

    function compileEventUi(eventDef, eventUiBases) {
        let uis = [];
        if (eventUiBases['']) {
            uis.push(eventUiBases['']);
        }
        if (eventUiBases[eventDef.defId]) {
            uis.push(eventUiBases[eventDef.defId]);
        }
        uis.push(eventDef.ui);
        return combineEventUis(uis);
    }

    function sortEventSegs(segs, eventOrderSpecs) {
        let objs = segs.map(buildSegCompareObj);
        objs.sort((obj0, obj1) => compareByFieldSpecs(obj0, obj1, eventOrderSpecs));
        return objs.map((c) => c._seg);
    }
    // returns a object with all primitive props that can be compared
    function buildSegCompareObj(seg) {
        let {
            eventRange
        } = seg;
        let eventDef = eventRange.def;
        let range = eventRange.instance ? eventRange.instance.range : eventRange.range;
        let start = range.start ? range.start.valueOf() : 0; // TODO: better support for open-range events
        let end = range.end ? range.end.valueOf() : 0; // "
        return Object.assign(Object.assign(Object.assign({}, eventDef.extendedProps), eventDef), {
            id: eventDef.publicId,
            start,
            end,
            duration: end - start,
            allDay: Number(eventDef.allDay),
            _seg: seg
        });
    }

    function computeSegDraggable(seg, context) {
        let {
            pluginHooks
        } = context;
        let transformers = pluginHooks.isDraggableTransformers;
        let {
            def,
            ui
        } = seg.eventRange;
        let val = ui.startEditable;
        for (let transformer of transformers) {
            val = transformer(val, def, ui, context);
        }
        return val;
    }

    function computeSegStartResizable(seg, context) {
        return seg.isStart && seg.eventRange.ui.durationEditable && context.options.eventResizableFromStart;
    }

    function computeSegEndResizable(seg, context) {
        return seg.isEnd && seg.eventRange.ui.durationEditable;
    }

    function buildSegTimeText(seg, timeFormat, context, defaultDisplayEventTime, // defaults to true
        defaultDisplayEventEnd, // defaults to true
        startOverride, endOverride) {
        let {
            dateEnv,
            options
        } = context;
        let {
            displayEventTime,
            displayEventEnd
        } = options;
        let eventDef = seg.eventRange.def;
        let eventInstance = seg.eventRange.instance;
        if (displayEventTime == null) {
            displayEventTime = defaultDisplayEventTime !== false;
        }
        if (displayEventEnd == null) {
            displayEventEnd = defaultDisplayEventEnd !== false;
        }
        let wholeEventStart = eventInstance.range.start;
        let wholeEventEnd = eventInstance.range.end;
        let segStart = startOverride || seg.start || seg.eventRange.range.start;
        let segEnd = endOverride || seg.end || seg.eventRange.range.end;
        let isStartDay = startOfDay(wholeEventStart).valueOf() === startOfDay(segStart).valueOf();
        let isEndDay = startOfDay(addMs(wholeEventEnd, -1)).valueOf() === startOfDay(addMs(segEnd, -1)).valueOf();
        if (displayEventTime && !eventDef.allDay && (isStartDay || isEndDay)) {
            segStart = isStartDay ? wholeEventStart : segStart;
            segEnd = isEndDay ? wholeEventEnd : segEnd;
            if (displayEventEnd && eventDef.hasEnd) {
                return dateEnv.formatRange(segStart, segEnd, timeFormat, {
                    forcedStartTzo: startOverride ? null : eventInstance.forcedStartTzo,
                    forcedEndTzo: endOverride ? null : eventInstance.forcedEndTzo,
                });
            }
            return dateEnv.format(segStart, timeFormat, {
                forcedTzo: startOverride ? null : eventInstance.forcedStartTzo, // nooooo, same
            });
        }
        return '';
    }

    function getSegMeta(seg, todayRange, nowDate) {
        let segRange = seg.eventRange.range;
        return {
            isPast: segRange.end <= (nowDate || todayRange.start),
            isFuture: segRange.start >= (nowDate || todayRange.end),
            isToday: todayRange && rangeContainsMarker(todayRange, segRange.start),
        };
    }

    function getEventClassNames(props) {
        let classNames = ['fc-event'];
        if (props.isMirror) {
            classNames.push('fc-event-mirror');
        }
        if (props.isDraggable) {
            classNames.push('fc-event-draggable');
        }
        if (props.isStartResizable || props.isEndResizable) {
            classNames.push('fc-event-resizable');
        }
        if (props.isDragging) {
            classNames.push('fc-event-dragging');
        }
        if (props.isResizing) {
            classNames.push('fc-event-resizing');
        }
        if (props.isSelected) {
            classNames.push('fc-event-selected');
        }
        if (props.isStart) {
            classNames.push('fc-event-start');
        }
        if (props.isEnd) {
            classNames.push('fc-event-end');
        }
        if (props.isPast) {
            classNames.push('fc-event-past');
        }
        if (props.isToday) {
            classNames.push('fc-event-today');
        }
        if (props.isFuture) {
            classNames.push('fc-event-future');
        }
        return classNames;
    }

    function buildEventRangeKey(eventRange) {
        return eventRange.instance ?
            eventRange.instance.instanceId :
            `${eventRange.def.defId}:${eventRange.range.start.toISOString()}`;
        // inverse-background events don't have specific instances. TODO: better solution
    }

    function getSegAnchorAttrs(seg, context) {
        let {
            def,
            instance
        } = seg.eventRange;
        let {
            url
        } = def;
        if (url) {
            return {
                href: url
            };
        }
        let {
            emitter,
            options
        } = context;
        let {
            eventInteractive
        } = options;
        if (eventInteractive == null) {
            eventInteractive = def.interactive;
            if (eventInteractive == null) {
                eventInteractive = Boolean(emitter.hasHandlers('eventClick'));
            }
        }
        // mock what happens in EventClicking
        if (eventInteractive) {
            // only attach keyboard-related handlers because click handler is already done in EventClicking
            return createAriaKeyboardAttrs((ev) => {
                emitter.trigger('eventClick', {
                    el: ev.target,
                    event: new EventImpl(context, def, instance),
                    jsEvent: ev,
                    view: context.viewApi,
                });
            });
        }
        return {};
    }

    const STANDARD_PROPS = {
        start: identity,
        end: identity,
        allDay: Boolean,
    };

    function parseDateSpan(raw, dateEnv, defaultDuration) {
        let span = parseOpenDateSpan(raw, dateEnv);
        let {
            range
        } = span;
        if (!range.start) {
            return null;
        }
        if (!range.end) {
            if (defaultDuration == null) {
                return null;
            }
            range.end = dateEnv.add(range.start, defaultDuration);
        }
        return span;
    }
    /*
    TODO: somehow combine with parseRange?
    Will return null if the start/end props were present but parsed invalidly.
    */
    function parseOpenDateSpan(raw, dateEnv) {
        let {
            refined: standardProps,
            extra
        } = refineProps(raw, STANDARD_PROPS);
        let startMeta = standardProps.start ? dateEnv.createMarkerMeta(standardProps.start) : null;
        let endMeta = standardProps.end ? dateEnv.createMarkerMeta(standardProps.end) : null;
        let {
            allDay
        } = standardProps;
        if (allDay == null) {
            allDay = (startMeta && startMeta.isTimeUnspecified) &&
                (!endMeta || endMeta.isTimeUnspecified);
        }
        return Object.assign({
            range: {
                start: startMeta ? startMeta.marker : null,
                end: endMeta ? endMeta.marker : null,
            },
            allDay
        }, extra);
    }

    function isDateSpansEqual(span0, span1) {
        return rangesEqual(span0.range, span1.range) &&
            span0.allDay === span1.allDay &&
            isSpanPropsEqual(span0, span1);
    }
    // the NON-DATE-RELATED props
    function isSpanPropsEqual(span0, span1) {
        for (let propName in span1) {
            if (propName !== 'range' && propName !== 'allDay') {
                if (span0[propName] !== span1[propName]) {
                    return false;
                }
            }
        }
        // are there any props that span0 has that span1 DOESN'T have?
        // both have range/allDay, so no need to special-case.
        for (let propName in span0) {
            if (!(propName in span1)) {
                return false;
            }
        }
        return true;
    }

    function buildDateSpanApi(span, dateEnv) {
        return Object.assign(Object.assign({}, buildRangeApi(span.range, dateEnv, span.allDay)), {
            allDay: span.allDay
        });
    }

    function buildRangeApiWithTimeZone(range, dateEnv, omitTime) {
        return Object.assign(Object.assign({}, buildRangeApi(range, dateEnv, omitTime)), {
            timeZone: dateEnv.timeZone
        });
    }

    function buildRangeApi(range, dateEnv, omitTime) {
        return {
            start: dateEnv.toDate(range.start),
            end: dateEnv.toDate(range.end),
            startStr: dateEnv.formatIso(range.start, {
                omitTime
            }),
            endStr: dateEnv.formatIso(range.end, {
                omitTime
            }),
        };
    }

    function fabricateEventRange(dateSpan, eventUiBases, context) {
        let res = refineEventDef({
            editable: false
        }, context);
        let def = parseEventDef(res.refined, res.extra, '', // sourceId
            dateSpan.allDay, true, // hasEnd
            context);
        return {
            def,
            ui: compileEventUi(def, eventUiBases),
            instance: createEventInstance(def.defId, dateSpan.range),
            range: dateSpan.range,
            isStart: true,
            isEnd: true,
        };
    }

    /*
    given a function that resolves a result asynchronously.
    the function can either call passed-in success and failure callbacks,
    or it can return a promise.
    if you need to pass additional params to func, bind them first.
    */
    function unpromisify(func, normalizedSuccessCallback, normalizedFailureCallback) {
        // guard against success/failure callbacks being called more than once
        // and guard against a promise AND callback being used together.
        let isResolved = false;
        let wrappedSuccess = function(res) {
            if (!isResolved) {
                isResolved = true;
                normalizedSuccessCallback(res);
            }
        };
        let wrappedFailure = function(error) {
            if (!isResolved) {
                isResolved = true;
                normalizedFailureCallback(error);
            }
        };
        let res = func(wrappedSuccess, wrappedFailure);
        if (res && typeof res.then === 'function') {
            res.then(wrappedSuccess, wrappedFailure);
        }
    }

    class JsonRequestError extends Error {
        constructor(message, response) {
            super(message);
            this.response = response;
        }
    }

    function requestJson(method, url, params) {
        method = method.toUpperCase();
        const fetchOptions = {
            method,
        };
        if (method === 'GET') {
            url += (url.indexOf('?') === -1 ? '?' : '&') +
                new URLSearchParams(params);
        } else {
            fetchOptions.body = new URLSearchParams(params);
            fetchOptions.headers = {
                'Content-Type': 'application/x-www-form-urlencoded',
            };
        }
        return fetch(url, fetchOptions).then((fetchRes) => {
            if (fetchRes.ok) {
                return fetchRes.json().then((parsedResponse) => {
                    return [parsedResponse, fetchRes];
                }, () => {
                    throw new JsonRequestError('Failure parsing JSON', fetchRes);
                });
            } else {
                throw new JsonRequestError('Request failed', fetchRes);
            }
        });
    }

    let canVGrowWithinCell;

    function getCanVGrowWithinCell() {
        if (canVGrowWithinCell == null) {
            canVGrowWithinCell = computeCanVGrowWithinCell();
        }
        return canVGrowWithinCell;
    }

    function computeCanVGrowWithinCell() {
        // for SSR, because this function is call immediately at top-level
        // TODO: just make this logic execute top-level, immediately, instead of doing lazily
        if (typeof document === 'undefined') {
            return true;
        }
        let el = document.createElement('div');
        el.style.position = 'absolute';
        el.style.top = '0px';
        el.style.left = '0px';
        el.innerHTML = '<table><tr><td><div></div></td></tr></table>';
        el.querySelector('table').style.height = '100px';
        el.querySelector('div').style.height = '100%';
        document.body.appendChild(el);
        let div = el.querySelector('div');
        let possible = div.offsetHeight > 0;
        document.body.removeChild(el);
        return possible;
    }

    class CalendarRoot extends BaseComponent {
        constructor() {
            super(...arguments);
            this.state = {
                forPrint: false,
            };
            this.handleBeforePrint = () => {
                flushSync(() => {
                    this.setState({
                        forPrint: true
                    });
                });
            };
            this.handleAfterPrint = () => {
                flushSync(() => {
                    this.setState({
                        forPrint: false
                    });
                });
            };
        }
        render() {
            let {
                props
            } = this;
            let {
                options
            } = props;
            let {
                forPrint
            } = this.state;
            let isHeightAuto = forPrint || options.height === 'auto' || options.contentHeight === 'auto';
            let height = (!isHeightAuto && options.height != null) ? options.height : '';
            let classNames = [
                'fc',
                forPrint ? 'fc-media-print' : 'fc-media-screen',
                `fc-direction-${options.direction}`,
                props.theme.getClass('root'),
            ];
            if (!getCanVGrowWithinCell()) {
                classNames.push('fc-liquid-hack');
            }
            return props.children(classNames, height, isHeightAuto, forPrint);
        }
        componentDidMount() {
            let {
                emitter
            } = this.props;
            emitter.on('_beforeprint', this.handleBeforePrint);
            emitter.on('_afterprint', this.handleAfterPrint);
        }
        componentWillUnmount() {
            let {
                emitter
            } = this.props;
            emitter.off('_beforeprint', this.handleBeforePrint);
            emitter.off('_afterprint', this.handleAfterPrint);
        }
    }

    class Interaction {
        constructor(settings) {
            this.component = settings.component;
            this.isHitComboAllowed = settings.isHitComboAllowed || null;
        }
        destroy() {}
    }

    function parseInteractionSettings(component, input) {
        return {
            component,
            el: input.el,
            useEventCenter: input.useEventCenter != null ? input.useEventCenter : true,
            isHitComboAllowed: input.isHitComboAllowed || null,
        };
    }

    function interactionSettingsToStore(settings) {
        return {
            [settings.component.uid]: settings,
        };
    }
    // global state
    const interactionSettingsStore = {};

    class NowTimer extends x$1 {
        constructor(props, context) {
            super(props, context);
            this.handleRefresh = () => {
                let timing = this.computeTiming();
                if (timing.state.nowDate.valueOf() !== this.state.nowDate.valueOf()) {
                    this.setState(timing.state);
                }
                this.clearTimeout();
                this.setTimeout(timing.waitMs);
            };
            this.handleVisibilityChange = () => {
                if (!document.hidden) {
                    this.handleRefresh();
                }
            };
            this.state = this.computeTiming().state;
        }
        render() {
            let {
                props,
                state
            } = this;
            return props.children(state.nowDate, state.todayRange);
        }
        componentDidMount() {
            this.setTimeout();
            this.context.nowManager.addResetListener(this.handleRefresh);
            // fired tab becomes visible after being hidden
            document.addEventListener('visibilitychange', this.handleVisibilityChange);
        }
        componentDidUpdate(prevProps) {
            if (prevProps.unit !== this.props.unit) {
                this.clearTimeout();
                this.setTimeout();
            }
        }
        componentWillUnmount() {
            this.clearTimeout();
            this.context.nowManager.removeResetListener(this.handleRefresh);
            document.removeEventListener('visibilitychange', this.handleVisibilityChange);
        }
        computeTiming() {
            let {
                props,
                context
            } = this;
            let unroundedNow = context.nowManager.getDateMarker();
            let {
                nowIndicatorSnap
            } = context.options;
            if (nowIndicatorSnap === 'auto') {
                nowIndicatorSnap =
                    // large unit?
                    /year|month|week|day/.test(props.unit) ||
                    // if slotDuration 30 mins for example, would NOT appear to snap (legacy behavior)
                    (props.unitValue || 1) === 1;
            }
            let nowDate;
            let waitMs;
            if (nowIndicatorSnap) {
                nowDate = context.dateEnv.startOf(unroundedNow, props.unit); // aka currentUnitStart
                let nextUnitStart = context.dateEnv.add(nowDate, createDuration(1, props.unit));
                waitMs = nextUnitStart.valueOf() - unroundedNow.valueOf();
            } else {
                nowDate = unroundedNow;
                waitMs = 1000 * 60; // 1 minute
            }
            // there is a max setTimeout ms value (https://stackoverflow.com/a/3468650/96342)
            // ensure no longer than a day
            waitMs = Math.min(1000 * 60 * 60 * 24, waitMs);
            return {
                state: {
                    nowDate,
                    todayRange: buildDayRange(nowDate)
                },
                waitMs,
            };
        }
        setTimeout(waitMs = this.computeTiming().waitMs) {
            // NOTE: timeout could take longer than expected if tab sleeps,
            // which is why we listen to 'visibilitychange'
            this.timeoutId = setTimeout(() => {
                // NOTE: timeout could also return *earlier* than expected, and we need to wait 2 ms more
                // This is why use use same waitMs from computeTiming, so we don't skip an interval while
                // .setState() is executing
                const timing = this.computeTiming();
                this.setState(timing.state, () => {
                    this.setTimeout(timing.waitMs);
                });
            }, waitMs);
        }
        clearTimeout() {
            if (this.timeoutId) {
                clearTimeout(this.timeoutId);
            }
        }
    }
    NowTimer.contextType = ViewContextType;

    function buildDayRange(date) {
        let start = startOfDay(date);
        let end = addDays(start, 1);
        return {
            start,
            end
        };
    }

    class CalendarImpl {
        getCurrentData() {
            return this.currentDataManager.getCurrentData();
        }
        dispatch(action) {
            this.currentDataManager.dispatch(action);
        }
        get view() {
            return this.getCurrentData().viewApi;
        }
        batchRendering(callback) {
            callback();
        }
        updateSize() {
            this.trigger('_resize', true);
        }
        // Options
        // -----------------------------------------------------------------------------------------------------------------
        setOption(name, val) {
            this.dispatch({
                type: 'SET_OPTION',
                optionName: name,
                rawOptionValue: val,
            });
        }
        getOption(name) {
            return this.currentDataManager.currentCalendarOptionsInput[name];
        }
        getAvailableLocaleCodes() {
            return Object.keys(this.getCurrentData().availableRawLocales);
        }
        // Trigger
        // -----------------------------------------------------------------------------------------------------------------
        on(handlerName, handler) {
            let {
                currentDataManager
            } = this;
            if (currentDataManager.currentCalendarOptionsRefiners[handlerName]) {
                currentDataManager.emitter.on(handlerName, handler);
            } else {
                console.warn(`Unknown listener name '${handlerName}'`);
            }
        }
        off(handlerName, handler) {
            this.currentDataManager.emitter.off(handlerName, handler);
        }
        // not meant for public use
        trigger(handlerName, ...args) {
            this.currentDataManager.emitter.trigger(handlerName, ...args);
        }
        // View
        // -----------------------------------------------------------------------------------------------------------------
        changeView(viewType, dateOrRange) {
            this.batchRendering(() => {
                this.unselect();
                if (dateOrRange) {
                    if (dateOrRange.start && dateOrRange.end) { // a range
                        this.dispatch({
                            type: 'CHANGE_VIEW_TYPE',
                            viewType,
                        });
                        this.dispatch({
                            type: 'SET_OPTION',
                            optionName: 'visibleRange',
                            rawOptionValue: dateOrRange,
                        });
                    } else {
                        let {
                            dateEnv
                        } = this.getCurrentData();
                        this.dispatch({
                            type: 'CHANGE_VIEW_TYPE',
                            viewType,
                            dateMarker: dateEnv.createMarker(dateOrRange),
                        });
                    }
                } else {
                    this.dispatch({
                        type: 'CHANGE_VIEW_TYPE',
                        viewType,
                    });
                }
            });
        }
        // Forces navigation to a view for the given date.
        // `viewType` can be a specific view name or a generic one like "week" or "day".
        // needs to change
        zoomTo(dateMarker, viewType) {
            let state = this.getCurrentData();
            let spec;
            viewType = viewType || 'day'; // day is default zoom
            spec = state.viewSpecs[viewType] || this.getUnitViewSpec(viewType);
            this.unselect();
            if (spec) {
                this.dispatch({
                    type: 'CHANGE_VIEW_TYPE',
                    viewType: spec.type,
                    dateMarker,
                });
            } else {
                this.dispatch({
                    type: 'CHANGE_DATE',
                    dateMarker,
                });
            }
        }
        // Given a duration singular unit, like "week" or "day", finds a matching view spec.
        // Preference is given to views that have corresponding buttons.
        getUnitViewSpec(unit) {
            let {
                viewSpecs,
                toolbarConfig
            } = this.getCurrentData();
            let viewTypes = [].concat(toolbarConfig.header ? toolbarConfig.header.viewsWithButtons : [], toolbarConfig.footer ? toolbarConfig.footer.viewsWithButtons : []);
            let i;
            let spec;
            for (let viewType in viewSpecs) {
                viewTypes.push(viewType);
            }
            for (i = 0; i < viewTypes.length; i += 1) {
                spec = viewSpecs[viewTypes[i]];
                if (spec) {
                    if (spec.singleUnit === unit) {
                        return spec;
                    }
                }
            }
            return null;
        }
        // Current Date
        // -----------------------------------------------------------------------------------------------------------------
        prev() {
            this.unselect();
            this.dispatch({
                type: 'PREV'
            });
        }
        next() {
            this.unselect();
            this.dispatch({
                type: 'NEXT'
            });
        }
        prevYear() {
            let state = this.getCurrentData();
            this.unselect();
            this.dispatch({
                type: 'CHANGE_DATE',
                dateMarker: state.dateEnv.addYears(state.currentDate, -1),
            });
        }
        nextYear() {
            let state = this.getCurrentData();
            this.unselect();
            this.dispatch({
                type: 'CHANGE_DATE',
                dateMarker: state.dateEnv.addYears(state.currentDate, 1),
            });
        }
        today() {
            let state = this.getCurrentData();
            this.unselect();
            this.dispatch({
                type: 'CHANGE_DATE',
                dateMarker: state.nowManager.getDateMarker(),
            });
        }
        gotoDate(zonedDateInput) {
            let state = this.getCurrentData();
            this.unselect();
            this.dispatch({
                type: 'CHANGE_DATE',
                dateMarker: state.dateEnv.createMarker(zonedDateInput),
            });
        }
        incrementDate(deltaInput) {
            let state = this.getCurrentData();
            let delta = createDuration(deltaInput);
            if (delta) { // else, warn about invalid input?
                this.unselect();
                this.dispatch({
                    type: 'CHANGE_DATE',
                    dateMarker: state.dateEnv.add(state.currentDate, delta),
                });
            }
        }
        getDate() {
            let state = this.getCurrentData();
            return state.dateEnv.toDate(state.currentDate);
        }
        // Date Formatting Utils
        // -----------------------------------------------------------------------------------------------------------------
        formatDate(d, formatter) {
            let {
                dateEnv
            } = this.getCurrentData();
            return dateEnv.format(dateEnv.createMarker(d), createFormatter(formatter));
        }
        // `settings` is for formatter AND isEndExclusive
        formatRange(d0, d1, settings) {
            let {
                dateEnv
            } = this.getCurrentData();
            return dateEnv.formatRange(dateEnv.createMarker(d0), dateEnv.createMarker(d1), createFormatter(settings), settings);
        }
        formatIso(d, omitTime) {
            let {
                dateEnv
            } = this.getCurrentData();
            return dateEnv.formatIso(dateEnv.createMarker(d), {
                omitTime
            });
        }
        // Date Selection / Event Selection / DayClick
        // -----------------------------------------------------------------------------------------------------------------
        select(dateOrObj, endDate) {
            let selectionInput;
            if (endDate == null) {
                if (dateOrObj.start != null) {
                    selectionInput = dateOrObj;
                } else {
                    selectionInput = {
                        start: dateOrObj,
                        end: null,
                    };
                }
            } else {
                selectionInput = {
                    start: dateOrObj,
                    end: endDate,
                };
            }
            let state = this.getCurrentData();
            let selection = parseDateSpan(selectionInput, state.dateEnv, createDuration({
                days: 1
            }));
            if (selection) { // throw parse error otherwise?
                this.dispatch({
                    type: 'SELECT_DATES',
                    selection
                });
                triggerDateSelect(selection, null, state);
            }
        }
        unselect(pev) {
            let state = this.getCurrentData();
            if (state.dateSelection) {
                this.dispatch({
                    type: 'UNSELECT_DATES'
                });
                triggerDateUnselect(pev, state);
            }
        }
        // Public Events API
        // -----------------------------------------------------------------------------------------------------------------
        addEvent(eventInput, sourceInput) {
            if (eventInput instanceof EventImpl) {
                let def = eventInput._def;
                let instance = eventInput._instance;
                let currentData = this.getCurrentData();
                // not already present? don't want to add an old snapshot
                if (!currentData.eventStore.defs[def.defId]) {
                    this.dispatch({
                        type: 'ADD_EVENTS',
                        eventStore: eventTupleToStore({
                            def,
                            instance
                        }), // TODO: better util for two args?
                    });
                    this.triggerEventAdd(eventInput);
                }
                return eventInput;
            }
            let state = this.getCurrentData();
            let eventSource;
            if (sourceInput instanceof EventSourceImpl) {
                eventSource = sourceInput.internalEventSource;
            } else if (typeof sourceInput === 'boolean') {
                if (sourceInput) { // true. part of the first event source
                    [eventSource] = hashValuesToArray(state.eventSources);
                }
            } else if (sourceInput != null) { // an ID. accepts a number too
                let sourceApi = this.getEventSourceById(sourceInput); // TODO: use an internal function
                if (!sourceApi) {
                    console.warn(`Could not find an event source with ID "${sourceInput}"`); // TODO: test
                    return null;
                }
                eventSource = sourceApi.internalEventSource;
            }
            let tuple = parseEvent(eventInput, eventSource, state, false);
            if (tuple) {
                let newEventApi = new EventImpl(state, tuple.def, tuple.def.recurringDef ? null : tuple.instance);
                this.dispatch({
                    type: 'ADD_EVENTS',
                    eventStore: eventTupleToStore(tuple),
                });
                this.triggerEventAdd(newEventApi);
                return newEventApi;
            }
            return null;
        }
        triggerEventAdd(eventApi) {
            let {
                emitter
            } = this.getCurrentData();
            emitter.trigger('eventAdd', {
                event: eventApi,
                relatedEvents: [],
                revert: () => {
                    this.dispatch({
                        type: 'REMOVE_EVENTS',
                        eventStore: eventApiToStore(eventApi),
                    });
                },
            });
        }
        // TODO: optimize
        getEventById(id) {
            let state = this.getCurrentData();
            let {
                defs,
                instances
            } = state.eventStore;
            id = String(id);
            for (let defId in defs) {
                let def = defs[defId];
                if (def.publicId === id) {
                    if (def.recurringDef) {
                        return new EventImpl(state, def, null);
                    }
                    for (let instanceId in instances) {
                        let instance = instances[instanceId];
                        if (instance.defId === def.defId) {
                            return new EventImpl(state, def, instance);
                        }
                    }
                }
            }
            return null;
        }
        getEvents() {
            let currentData = this.getCurrentData();
            return buildEventApis(currentData.eventStore, currentData);
        }
        removeAllEvents() {
            this.dispatch({
                type: 'REMOVE_ALL_EVENTS'
            });
        }
        // Public Event Sources API
        // -----------------------------------------------------------------------------------------------------------------
        getEventSources() {
            let state = this.getCurrentData();
            let sourceHash = state.eventSources;
            let sourceApis = [];
            for (let internalId in sourceHash) {
                sourceApis.push(new EventSourceImpl(state, sourceHash[internalId]));
            }
            return sourceApis;
        }
        getEventSourceById(id) {
            let state = this.getCurrentData();
            let sourceHash = state.eventSources;
            id = String(id);
            for (let sourceId in sourceHash) {
                if (sourceHash[sourceId].publicId === id) {
                    return new EventSourceImpl(state, sourceHash[sourceId]);
                }
            }
            return null;
        }
        addEventSource(sourceInput) {
            let state = this.getCurrentData();
            if (sourceInput instanceof EventSourceImpl) {
                // not already present? don't want to add an old snapshot
                if (!state.eventSources[sourceInput.internalEventSource.sourceId]) {
                    this.dispatch({
                        type: 'ADD_EVENT_SOURCES',
                        sources: [sourceInput.internalEventSource],
                    });
                }
                return sourceInput;
            }
            let eventSource = parseEventSource(sourceInput, state);
            if (eventSource) { // TODO: error otherwise?
                this.dispatch({
                    type: 'ADD_EVENT_SOURCES',
                    sources: [eventSource]
                });
                return new EventSourceImpl(state, eventSource);
            }
            return null;
        }
        removeAllEventSources() {
            this.dispatch({
                type: 'REMOVE_ALL_EVENT_SOURCES'
            });
        }
        refetchEvents() {
            this.dispatch({
                type: 'FETCH_EVENT_SOURCES',
                isRefetch: true
            });
        }
        // Scroll
        // -----------------------------------------------------------------------------------------------------------------
        scrollToTime(timeInput) {
            let time = createDuration(timeInput);
            if (time) {
                this.trigger('_scrollRequest', {
                    time
                });
            }
        }
    }

    function pointInsideRect(point, rect) {
        return point.left >= rect.left &&
            point.left < rect.right &&
            point.top >= rect.top &&
            point.top < rect.bottom;
    }
    // Returns a new rectangle that is the intersection of the two rectangles. If they don't intersect, returns false
    function intersectRects(rect1, rect2) {
        let res = {
            left: Math.max(rect1.left, rect2.left),
            right: Math.min(rect1.right, rect2.right),
            top: Math.max(rect1.top, rect2.top),
            bottom: Math.min(rect1.bottom, rect2.bottom),
        };
        if (res.left < res.right && res.top < res.bottom) {
            return res;
        }
        return false;
    }

    function translateRect(rect, deltaX, deltaY) {
        return {
            left: rect.left + deltaX,
            right: rect.right + deltaX,
            top: rect.top + deltaY,
            bottom: rect.bottom + deltaY,
        };
    }
    // Returns a new point that will have been moved to reside within the given rectangle
    function constrainPoint(point, rect) {
        return {
            left: Math.min(Math.max(point.left, rect.left), rect.right),
            top: Math.min(Math.max(point.top, rect.top), rect.bottom),
        };
    }
    // Returns a point that is the center of the given rectangle
    function getRectCenter(rect) {
        return {
            left: (rect.left + rect.right) / 2,
            top: (rect.top + rect.bottom) / 2,
        };
    }
    // Subtracts point2's coordinates from point1's coordinates, returning a delta
    function diffPoints(point1, point2) {
        return {
            left: point1.left - point2.left,
            top: point1.top - point2.top,
        };
    }

    const EMPTY_EVENT_STORE = createEmptyEventStore(); // for purecomponents. TODO: keep elsewhere
    class Splitter {
        constructor() {
            this.getKeysForEventDefs = memoize(this._getKeysForEventDefs);
            this.splitDateSelection = memoize(this._splitDateSpan);
            this.splitEventStore = memoize(this._splitEventStore);
            this.splitIndividualUi = memoize(this._splitIndividualUi);
            this.splitEventDrag = memoize(this._splitInteraction);
            this.splitEventResize = memoize(this._splitInteraction);
            this.eventUiBuilders = {}; // TODO: typescript protection
        }
        splitProps(props) {
            let keyInfos = this.getKeyInfo(props);
            let defKeys = this.getKeysForEventDefs(props.eventStore);
            let dateSelections = this.splitDateSelection(props.dateSelection);
            let individualUi = this.splitIndividualUi(props.eventUiBases, defKeys); // the individual *bases*
            let eventStores = this.splitEventStore(props.eventStore, defKeys);
            let eventDrags = this.splitEventDrag(props.eventDrag);
            let eventResizes = this.splitEventResize(props.eventResize);
            let splitProps = {};
            this.eventUiBuilders = mapHash(keyInfos, (info, key) => this.eventUiBuilders[key] || memoize(buildEventUiForKey));
            for (let key in keyInfos) {
                let keyInfo = keyInfos[key];
                let eventStore = eventStores[key] || EMPTY_EVENT_STORE;
                let buildEventUi = this.eventUiBuilders[key];
                splitProps[key] = {
                    businessHours: keyInfo.businessHours || props.businessHours,
                    dateSelection: dateSelections[key] || null,
                    eventStore,
                    eventUiBases: buildEventUi(props.eventUiBases[''], keyInfo.ui, individualUi[key]),
                    eventSelection: eventStore.instances[props.eventSelection] ? props.eventSelection : '',
                    eventDrag: eventDrags[key] || null,
                    eventResize: eventResizes[key] || null,
                };
            }
            return splitProps;
        }
        _splitDateSpan(dateSpan) {
            let dateSpans = {};
            if (dateSpan) {
                let keys = this.getKeysForDateSpan(dateSpan);
                for (let key of keys) {
                    dateSpans[key] = dateSpan;
                }
            }
            return dateSpans;
        }
        _getKeysForEventDefs(eventStore) {
            return mapHash(eventStore.defs, (eventDef) => this.getKeysForEventDef(eventDef));
        }
        _splitEventStore(eventStore, defKeys) {
            let {
                defs,
                instances
            } = eventStore;
            let splitStores = {};
            for (let defId in defs) {
                for (let key of defKeys[defId]) {
                    if (!splitStores[key]) {
                        splitStores[key] = createEmptyEventStore();
                    }
                    splitStores[key].defs[defId] = defs[defId];
                }
            }
            for (let instanceId in instances) {
                let instance = instances[instanceId];
                for (let key of defKeys[instance.defId]) {
                    if (splitStores[key]) { // must have already been created
                        splitStores[key].instances[instanceId] = instance;
                    }
                }
            }
            return splitStores;
        }
        _splitIndividualUi(eventUiBases, defKeys) {
            let splitHashes = {};
            for (let defId in eventUiBases) {
                if (defId) { // not the '' key
                    for (let key of defKeys[defId]) {
                        if (!splitHashes[key]) {
                            splitHashes[key] = {};
                        }
                        splitHashes[key][defId] = eventUiBases[defId];
                    }
                }
            }
            return splitHashes;
        }
        _splitInteraction(interaction) {
            let splitStates = {};
            if (interaction) {
                let affectedStores = this._splitEventStore(interaction.affectedEvents, this._getKeysForEventDefs(interaction.affectedEvents));
                // can't rely on defKeys because event data is mutated
                let mutatedKeysByDefId = this._getKeysForEventDefs(interaction.mutatedEvents);
                let mutatedStores = this._splitEventStore(interaction.mutatedEvents, mutatedKeysByDefId);
                let populate = (key) => {
                    if (!splitStates[key]) {
                        splitStates[key] = {
                            affectedEvents: affectedStores[key] || EMPTY_EVENT_STORE,
                            mutatedEvents: mutatedStores[key] || EMPTY_EVENT_STORE,
                            isEvent: interaction.isEvent,
                        };
                    }
                };
                for (let key in affectedStores) {
                    populate(key);
                }
                for (let key in mutatedStores) {
                    populate(key);
                }
            }
            return splitStates;
        }
    }

    function buildEventUiForKey(allUi, eventUiForKey, individualUi) {
        let baseParts = [];
        if (allUi) {
            baseParts.push(allUi);
        }
        if (eventUiForKey) {
            baseParts.push(eventUiForKey);
        }
        let stuff = {
            '': combineEventUis(baseParts),
        };
        if (individualUi) {
            Object.assign(stuff, individualUi);
        }
        return stuff;
    }

    function getDateMeta(date, todayRange, nowDate, dateProfile) {
        return {
            dow: date.getUTCDay(),
            isDisabled: Boolean(dateProfile && (!dateProfile.activeRange || !rangeContainsMarker(dateProfile.activeRange, date))),
            isOther: Boolean(dateProfile && !rangeContainsMarker(dateProfile.currentRange, date)),
            isToday: Boolean(todayRange && rangeContainsMarker(todayRange, date)),
            isPast: Boolean(nowDate ? (date < nowDate) : todayRange ? (date < todayRange.start) : false),
            isFuture: Boolean(nowDate ? (date > nowDate) : todayRange ? (date >= todayRange.end) : false),
        };
    }

    function getDayClassNames(meta, theme) {
        let classNames = [
            'fc-day',
            `fc-day-${DAY_IDS[meta.dow]}`,
        ];
        if (meta.isDisabled) {
            classNames.push('fc-day-disabled');
        } else {
            if (meta.isToday) {
                classNames.push('fc-day-today');
                classNames.push(theme.getClass('today'));
            }
            if (meta.isPast) {
                classNames.push('fc-day-past');
            }
            if (meta.isFuture) {
                classNames.push('fc-day-future');
            }
            if (meta.isOther) {
                classNames.push('fc-day-other');
            }
        }
        return classNames;
    }

    function getSlotClassNames(meta, theme) {
        let classNames = [
            'fc-slot',
            `fc-slot-${DAY_IDS[meta.dow]}`,
        ];
        if (meta.isDisabled) {
            classNames.push('fc-slot-disabled');
        } else {
            if (meta.isToday) {
                classNames.push('fc-slot-today');
                classNames.push(theme.getClass('today'));
            }
            if (meta.isPast) {
                classNames.push('fc-slot-past');
            }
            if (meta.isFuture) {
                classNames.push('fc-slot-future');
            }
        }
        return classNames;
    }

    const DAY_FORMAT = createFormatter({
        year: 'numeric',
        month: 'long',
        day: 'numeric'
    });
    const WEEK_FORMAT = createFormatter({
        week: 'long'
    });

    function buildNavLinkAttrs(context, dateMarker, viewType = 'day', isTabbable = true) {
        const {
            dateEnv,
            options,
            calendarApi
        } = context;
        let dateStr = dateEnv.format(dateMarker, viewType === 'week' ? WEEK_FORMAT : DAY_FORMAT);
        if (options.navLinks) {
            let zonedDate = dateEnv.toDate(dateMarker);
            const handleInteraction = (ev) => {
                let customAction = viewType === 'day' ? options.navLinkDayClick :
                    viewType === 'week' ? options.navLinkWeekClick : null;
                if (typeof customAction === 'function') {
                    customAction.call(calendarApi, dateEnv.toDate(dateMarker), ev);
                } else {
                    if (typeof customAction === 'string') {
                        viewType = customAction;
                    }
                    calendarApi.zoomTo(dateMarker, viewType);
                }
            };
            return Object.assign({
                title: formatWithOrdinals(options.navLinkHint, [dateStr, zonedDate], dateStr),
                'data-navlink': ''
            }, (isTabbable ?
                createAriaClickAttrs(handleInteraction) :
                {
                    onClick: handleInteraction
                }));
        }
        return {
            'aria-label': dateStr
        };
    }

    let _isRtlScrollbarOnLeft = null;

    function getIsRtlScrollbarOnLeft() {
        if (_isRtlScrollbarOnLeft === null) {
            _isRtlScrollbarOnLeft = computeIsRtlScrollbarOnLeft();
        }
        return _isRtlScrollbarOnLeft;
    }

    function computeIsRtlScrollbarOnLeft() {
        let outerEl = document.createElement('div');
        applyStyle(outerEl, {
            position: 'absolute',
            top: -1000,
            left: 0,
            border: 0,
            padding: 0,
            overflow: 'scroll',
            direction: 'rtl',
        });
        outerEl.innerHTML = '<div></div>';
        document.body.appendChild(outerEl);
        let innerEl = outerEl.firstChild;
        let res = innerEl.getBoundingClientRect().left > outerEl.getBoundingClientRect().left;
        removeElement(outerEl);
        return res;
    }

    let _scrollbarWidths;

    function getScrollbarWidths() {
        if (!_scrollbarWidths) {
            _scrollbarWidths = computeScrollbarWidths();
        }
        return _scrollbarWidths;
    }

    function computeScrollbarWidths() {
        let el = document.createElement('div');
        el.style.overflow = 'scroll';
        el.style.position = 'absolute';
        el.style.top = '-9999px';
        el.style.left = '-9999px';
        document.body.appendChild(el);
        let res = computeScrollbarWidthsForEl(el);
        document.body.removeChild(el);
        return res;
    }
    // WARNING: will include border
    function computeScrollbarWidthsForEl(el) {
        return {
            x: el.offsetHeight - el.clientHeight,
            y: el.offsetWidth - el.clientWidth,
        };
    }

    function computeEdges(el, getPadding = false) {
        let computedStyle = window.getComputedStyle(el);
        let borderLeft = parseInt(computedStyle.borderLeftWidth, 10) || 0;
        let borderRight = parseInt(computedStyle.borderRightWidth, 10) || 0;
        let borderTop = parseInt(computedStyle.borderTopWidth, 10) || 0;
        let borderBottom = parseInt(computedStyle.borderBottomWidth, 10) || 0;
        let badScrollbarWidths = computeScrollbarWidthsForEl(el); // includes border!
        let scrollbarLeftRight = badScrollbarWidths.y - borderLeft - borderRight;
        let scrollbarBottom = badScrollbarWidths.x - borderTop - borderBottom;
        let res = {
            borderLeft,
            borderRight,
            borderTop,
            borderBottom,
            scrollbarBottom,
            scrollbarLeft: 0,
            scrollbarRight: 0,
        };
        if (getIsRtlScrollbarOnLeft() && computedStyle.direction === 'rtl') { // is the scrollbar on the left side?
            res.scrollbarLeft = scrollbarLeftRight;
        } else {
            res.scrollbarRight = scrollbarLeftRight;
        }
        if (getPadding) {
            res.paddingLeft = parseInt(computedStyle.paddingLeft, 10) || 0;
            res.paddingRight = parseInt(computedStyle.paddingRight, 10) || 0;
            res.paddingTop = parseInt(computedStyle.paddingTop, 10) || 0;
            res.paddingBottom = parseInt(computedStyle.paddingBottom, 10) || 0;
        }
        return res;
    }

    function computeInnerRect(el, goWithinPadding = false, doFromWindowViewport) {
        let outerRect = doFromWindowViewport ? el.getBoundingClientRect() : computeRect(el);
        let edges = computeEdges(el, goWithinPadding);
        let res = {
            left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
            right: outerRect.right - edges.borderRight - edges.scrollbarRight,
            top: outerRect.top + edges.borderTop,
            bottom: outerRect.bottom - edges.borderBottom - edges.scrollbarBottom,
        };
        if (goWithinPadding) {
            res.left += edges.paddingLeft;
            res.right -= edges.paddingRight;
            res.top += edges.paddingTop;
            res.bottom -= edges.paddingBottom;
        }
        return res;
    }

    function computeRect(el) {
        let rect = el.getBoundingClientRect();
        return {
            left: rect.left + window.scrollX,
            top: rect.top + window.scrollY,
            right: rect.right + window.scrollX,
            bottom: rect.bottom + window.scrollY,
        };
    }

    function computeClippedClientRect(el) {
        let clippingParents = getClippingParents(el);
        let rect = el.getBoundingClientRect();
        for (let clippingParent of clippingParents) {
            let intersection = intersectRects(rect, clippingParent.getBoundingClientRect());
            if (intersection) {
                rect = intersection;
            } else {
                return null;
            }
        }
        return rect;
    }
    // does not return window
    function getClippingParents(el) {
        let parents = [];
        while (el instanceof HTMLElement) { // will stop when gets to document or null
            let computedStyle = window.getComputedStyle(el);
            if (computedStyle.position === 'fixed') {
                break;
            }
            if ((/(auto|scroll)/).test(computedStyle.overflow + computedStyle.overflowY + computedStyle.overflowX)) {
                parents.push(el);
            }
            el = el.parentNode;
        }
        return parents;
    }

    /*
    Records offset information for a set of elements, relative to an origin element.
    Can record the left/right OR the top/bottom OR both.
    Provides methods for querying the cache by position.
    */
    class PositionCache {
        constructor(originEl, els, isHorizontal, isVertical) {
            this.els = els;
            let originClientRect = this.originClientRect = originEl.getBoundingClientRect(); // relative to viewport top-left
            if (isHorizontal) {
                this.buildElHorizontals(originClientRect.left);
            }
            if (isVertical) {
                this.buildElVerticals(originClientRect.top);
            }
        }
        // Populates the left/right internal coordinate arrays
        buildElHorizontals(originClientLeft) {
            let lefts = [];
            let rights = [];
            for (let el of this.els) {
                let rect = el.getBoundingClientRect();
                lefts.push(rect.left - originClientLeft);
                rights.push(rect.right - originClientLeft);
            }
            this.lefts = lefts;
            this.rights = rights;
        }
        // Populates the top/bottom internal coordinate arrays
        buildElVerticals(originClientTop) {
            let tops = [];
            let bottoms = [];
            for (let el of this.els) {
                let rect = el.getBoundingClientRect();
                tops.push(rect.top - originClientTop);
                bottoms.push(rect.bottom - originClientTop);
            }
            this.tops = tops;
            this.bottoms = bottoms;
        }
        // Given a left offset (from document left), returns the index of the el that it horizontally intersects.
        // If no intersection is made, returns undefined.
        leftToIndex(leftPosition) {
            let {
                lefts,
                rights
            } = this;
            let len = lefts.length;
            let i;
            for (i = 0; i < len; i += 1) {
                if (leftPosition >= lefts[i] && leftPosition < rights[i]) {
                    return i;
                }
            }
            return undefined; // TODO: better
        }
        // Given a top offset (from document top), returns the index of the el that it vertically intersects.
        // If no intersection is made, returns undefined.
        topToIndex(topPosition) {
            let {
                tops,
                bottoms
            } = this;
            let len = tops.length;
            let i;
            for (i = 0; i < len; i += 1) {
                if (topPosition >= tops[i] && topPosition < bottoms[i]) {
                    return i;
                }
            }
            return undefined; // TODO: better
        }
        // Gets the width of the element at the given index
        getWidth(leftIndex) {
            return this.rights[leftIndex] - this.lefts[leftIndex];
        }
        // Gets the height of the element at the given index
        getHeight(topIndex) {
            return this.bottoms[topIndex] - this.tops[topIndex];
        }
        similarTo(otherCache) {
            return similarNumArrays(this.tops || [], otherCache.tops || []) &&
                similarNumArrays(this.bottoms || [], otherCache.bottoms || []) &&
                similarNumArrays(this.lefts || [], otherCache.lefts || []) &&
                similarNumArrays(this.rights || [], otherCache.rights || []);
        }
    }

    function similarNumArrays(a, b) {
        const len = a.length;
        if (len !== b.length) {
            return false;
        }
        for (let i = 0; i < len; i++) {
            if (Math.round(a[i]) !== Math.round(b[i])) {
                return false;
            }
        }
        return true;
    }

    /* eslint max-classes-per-file: "off" */
    /*
    An object for getting/setting scroll-related information for an element.
    Internally, this is done very differently for window versus DOM element,
    so this object serves as a common interface.
    */
    class ScrollController {
        getMaxScrollTop() {
            return this.getScrollHeight() - this.getClientHeight();
        }
        getMaxScrollLeft() {
            return this.getScrollWidth() - this.getClientWidth();
        }
        canScrollVertically() {
            return this.getMaxScrollTop() > 0;
        }
        canScrollHorizontally() {
            return this.getMaxScrollLeft() > 0;
        }
        canScrollUp() {
            return this.getScrollTop() > 0;
        }
        canScrollDown() {
            return this.getScrollTop() < this.getMaxScrollTop();
        }
        canScrollLeft() {
            return this.getScrollLeft() > 0;
        }
        canScrollRight() {
            return this.getScrollLeft() < this.getMaxScrollLeft();
        }
    }
    class ElementScrollController extends ScrollController {
        constructor(el) {
            super();
            this.el = el;
        }
        getScrollTop() {
            return this.el.scrollTop;
        }
        getScrollLeft() {
            return this.el.scrollLeft;
        }
        setScrollTop(top) {
            this.el.scrollTop = top;
        }
        setScrollLeft(left) {
            this.el.scrollLeft = left;
        }
        getScrollWidth() {
            return this.el.scrollWidth;
        }
        getScrollHeight() {
            return this.el.scrollHeight;
        }
        getClientHeight() {
            return this.el.clientHeight;
        }
        getClientWidth() {
            return this.el.clientWidth;
        }
    }
    class WindowScrollController extends ScrollController {
        getScrollTop() {
            return window.scrollY;
        }
        getScrollLeft() {
            return window.scrollX;
        }
        setScrollTop(n) {
            window.scroll(window.scrollX, n);
        }
        setScrollLeft(n) {
            window.scroll(n, window.scrollY);
        }
        getScrollWidth() {
            return document.documentElement.scrollWidth;
        }
        getScrollHeight() {
            return document.documentElement.scrollHeight;
        }
        getClientHeight() {
            return document.documentElement.clientHeight;
        }
        getClientWidth() {
            return document.documentElement.clientWidth;
        }
    }

    /*
    an INTERACTABLE date component

    PURPOSES:
    - hook up to fg, fill, and mirror renderers
    - interface for dragging and hits
    */
    class DateComponent extends BaseComponent {
        constructor() {
            super(...arguments);
            this.uid = guid();
        }
        // Hit System
        // -----------------------------------------------------------------------------------------------------------------
        prepareHits() {}
        queryHit(positionLeft, positionTop, elWidth, elHeight) {
            return null; // this should be abstract
        }
        // Pointer Interaction Utils
        // -----------------------------------------------------------------------------------------------------------------
        isValidSegDownEl(el) {
            return !this.props.eventDrag && // HACK
                !this.props.eventResize && // HACK
                !elementClosest(el, '.fc-event-mirror');
        }
        isValidDateDownEl(el) {
            return !elementClosest(el, '.fc-event:not(.fc-bg-event)') &&
                !elementClosest(el, '.fc-more-link') && // a "more.." link
                !elementClosest(el, 'a[data-navlink]') && // a clickable nav link
                !elementClosest(el, '.fc-popover'); // hack
        }
    }

    class NamedTimeZoneImpl {
        constructor(timeZoneName) {
            this.timeZoneName = timeZoneName;
        }
    }

    class SegHierarchy {
        constructor(getEntryThickness = (entry) => {
            // if no thickness known, assume 1 (if 0, so small it always fits)
            return entry.thickness || 1;
        }) {
            this.getEntryThickness = getEntryThickness;
            // settings
            this.strictOrder = false;
            this.allowReslicing = false;
            this.maxCoord = -1; // -1 means no max
            this.maxStackCnt = -1; // -1 means no max
            this.levelCoords = []; // ordered
            this.entriesByLevel = []; // parallel with levelCoords
            this.stackCnts = {}; // TODO: use better technique!?
        }
        addSegs(inputs) {
            let hiddenEntries = [];
            for (let input of inputs) {
                this.insertEntry(input, hiddenEntries);
            }
            return hiddenEntries;
        }
        insertEntry(entry, hiddenEntries) {
            let insertion = this.findInsertion(entry);
            if (this.isInsertionValid(insertion, entry)) {
                this.insertEntryAt(entry, insertion);
            } else {
                this.handleInvalidInsertion(insertion, entry, hiddenEntries);
            }
        }
        isInsertionValid(insertion, entry) {
            return (this.maxCoord === -1 || insertion.levelCoord + this.getEntryThickness(entry) <= this.maxCoord) &&
                (this.maxStackCnt === -1 || insertion.stackCnt < this.maxStackCnt);
        }
        handleInvalidInsertion(insertion, entry, hiddenEntries) {
            if (this.allowReslicing && insertion.touchingEntry) {
                const hiddenEntry = Object.assign(Object.assign({}, entry), {
                    span: intersectSpans(entry.span, insertion.touchingEntry.span)
                });
                hiddenEntries.push(hiddenEntry);
                this.splitEntry(entry, insertion.touchingEntry, hiddenEntries);
            } else {
                hiddenEntries.push(entry);
            }
        }
        /*
        Does NOT add what hit the `barrier` into hiddenEntries. Should already be done.
        */
        splitEntry(entry, barrier, hiddenEntries) {
            let entrySpan = entry.span;
            let barrierSpan = barrier.span;
            if (entrySpan.start < barrierSpan.start) {
                this.insertEntry({
                    index: entry.index,
                    thickness: entry.thickness,
                    span: {
                        start: entrySpan.start,
                        end: barrierSpan.start
                    },
                }, hiddenEntries);
            }
            if (entrySpan.end > barrierSpan.end) {
                this.insertEntry({
                    index: entry.index,
                    thickness: entry.thickness,
                    span: {
                        start: barrierSpan.end,
                        end: entrySpan.end
                    },
                }, hiddenEntries);
            }
        }
        insertEntryAt(entry, insertion) {
            let {
                entriesByLevel,
                levelCoords
            } = this;
            if (insertion.lateral === -1) {
                // create a new level
                insertAt(levelCoords, insertion.level, insertion.levelCoord);
                insertAt(entriesByLevel, insertion.level, [entry]);
            } else {
                // insert into existing level
                insertAt(entriesByLevel[insertion.level], insertion.lateral, entry);
            }
            this.stackCnts[buildEntryKey(entry)] = insertion.stackCnt;
        }
        /*
        does not care about limits
        */
        findInsertion(newEntry) {
            let {
                levelCoords,
                entriesByLevel,
                strictOrder,
                stackCnts
            } = this;
            let levelCnt = levelCoords.length;
            let candidateCoord = 0;
            let touchingLevel = -1;
            let touchingLateral = -1;
            let touchingEntry = null;
            let stackCnt = 0;
            for (let trackingLevel = 0; trackingLevel < levelCnt; trackingLevel += 1) {
                const trackingCoord = levelCoords[trackingLevel];
                // if the current level is past the placed entry, we have found a good empty space and can stop.
                // if strictOrder, keep finding more lateral intersections.
                if (!strictOrder && trackingCoord >= candidateCoord + this.getEntryThickness(newEntry)) {
                    break;
                }
                let trackingEntries = entriesByLevel[trackingLevel];
                let trackingEntry;
                let searchRes = binarySearch(trackingEntries, newEntry.span.start, getEntrySpanEnd); // find first entry after newEntry's end
                let lateralIndex = searchRes[0] + searchRes[1]; // if exact match (which doesn't collide), go to next one
                while ( // loop through entries that horizontally intersect
                    (trackingEntry = trackingEntries[lateralIndex]) && // but not past the whole entry list
                    trackingEntry.span.start < newEntry.span.end // and not entirely past newEntry
                ) {
                    let trackingEntryBottom = trackingCoord + this.getEntryThickness(trackingEntry);
                    // intersects into the top of the candidate?
                    if (trackingEntryBottom > candidateCoord) {
                        candidateCoord = trackingEntryBottom;
                        touchingEntry = trackingEntry;
                        touchingLevel = trackingLevel;
                        touchingLateral = lateralIndex;
                    }
                    // butts up against top of candidate? (will happen if just intersected as well)
                    if (trackingEntryBottom === candidateCoord) {
                        // accumulate the highest possible stackCnt of the trackingEntries that butt up
                        stackCnt = Math.max(stackCnt, stackCnts[buildEntryKey(trackingEntry)] + 1);
                    }
                    lateralIndex += 1;
                }
            }
            // the destination level will be after touchingEntry's level. find it
            let destLevel = 0;
            if (touchingEntry) {
                destLevel = touchingLevel + 1;
                while (destLevel < levelCnt && levelCoords[destLevel] < candidateCoord) {
                    destLevel += 1;
                }
            }
            // if adding to an existing level, find where to insert
            let destLateral = -1;
            if (destLevel < levelCnt && levelCoords[destLevel] === candidateCoord) {
                destLateral = binarySearch(entriesByLevel[destLevel], newEntry.span.end, getEntrySpanEnd)[0];
            }
            return {
                touchingLevel,
                touchingLateral,
                touchingEntry,
                stackCnt,
                levelCoord: candidateCoord,
                level: destLevel,
                lateral: destLateral,
            };
        }
        // sorted by levelCoord (lowest to highest)
        toRects() {
            let {
                entriesByLevel,
                levelCoords
            } = this;
            let levelCnt = entriesByLevel.length;
            let rects = [];
            for (let level = 0; level < levelCnt; level += 1) {
                let entries = entriesByLevel[level];
                let levelCoord = levelCoords[level];
                for (let entry of entries) {
                    rects.push(Object.assign(Object.assign({}, entry), {
                        thickness: this.getEntryThickness(entry),
                        levelCoord
                    }));
                }
            }
            return rects;
        }
    }

    function getEntrySpanEnd(entry) {
        return entry.span.end;
    }

    function buildEntryKey(entry) {
        return entry.index + ':' + entry.span.start;
    }
    // returns groups with entries sorted by input order
    function groupIntersectingEntries(entries) {
        let merges = [];
        for (let entry of entries) {
            let filteredMerges = [];
            let hungryMerge = {
                span: entry.span,
                entries: [entry],
            };
            for (let merge of merges) {
                if (intersectSpans(merge.span, hungryMerge.span)) {
                    hungryMerge = {
                        entries: merge.entries.concat(hungryMerge.entries),
                        span: joinSpans(merge.span, hungryMerge.span),
                    };
                } else {
                    filteredMerges.push(merge);
                }
            }
            filteredMerges.push(hungryMerge);
            merges = filteredMerges;
        }
        return merges;
    }

    function joinSpans(span0, span1) {
        return {
            start: Math.min(span0.start, span1.start),
            end: Math.max(span0.end, span1.end),
        };
    }

    function intersectSpans(span0, span1) {
        let start = Math.max(span0.start, span1.start);
        let end = Math.min(span0.end, span1.end);
        if (start < end) {
            return {
                start,
                end
            };
        }
        return null;
    }
    // general util
    // ---------------------------------------------------------------------------------------------------------------------
    function insertAt(arr, index, item) {
        arr.splice(index, 0, item);
    }

    function binarySearch(a, searchVal, getItemVal) {
        let startIndex = 0;
        let endIndex = a.length; // exclusive
        if (!endIndex || searchVal < getItemVal(a[startIndex])) { // no items OR before first item
            return [0, 0];
        }
        if (searchVal > getItemVal(a[endIndex - 1])) { // after last item
            return [endIndex, 0];
        }
        while (startIndex < endIndex) {
            let middleIndex = Math.floor(startIndex + (endIndex - startIndex) / 2);
            let middleVal = getItemVal(a[middleIndex]);
            if (searchVal < middleVal) {
                endIndex = middleIndex;
            } else if (searchVal > middleVal) {
                startIndex = middleIndex + 1;
            } else { // equal!
                return [middleIndex, 1];
            }
        }
        return [startIndex, 0];
    }

    /*
    An abstraction for a dragging interaction originating on an event.
    Does higher-level things than PointerDragger, such as possibly:
    - a "mirror" that moves with the pointer
    - a minimum number of pixels or other criteria for a true drag to begin

    subclasses must emit:
    - pointerdown
    - dragstart
    - dragmove
    - pointerup
    - dragend
    */
    class ElementDragging {
        constructor(el, selector) {
            this.emitter = new Emitter();
        }
        destroy() {}
        setMirrorIsVisible(bool) {
            // optional if subclass doesn't want to support a mirror
        }
        setMirrorNeedsRevert(bool) {
            // optional if subclass doesn't want to support a mirror
        }
        setAutoScrollEnabled(bool) {
            // optional
        }
    }

    // TODO: get rid of this in favor of options system,
    // tho it's really easy to access this globally rather than pass thru options.
    const config = {};

    /*
    Information about what will happen when an external element is dragged-and-dropped
    onto a calendar. Contains information for creating an event.
    */
    const DRAG_META_REFINERS = {
        startTime: createDuration,
        duration: createDuration,
        create: Boolean,
        sourceId: String,
    };

    function parseDragMeta(raw) {
        let {
            refined,
            extra
        } = refineProps(raw, DRAG_META_REFINERS);
        return {
            startTime: refined.startTime || null,
            duration: refined.duration || null,
            create: refined.create != null ? refined.create : true,
            sourceId: refined.sourceId,
            leftoverProps: extra,
        };
    }

    // Computes a default column header formatting string if `colFormat` is not explicitly defined
    function computeFallbackHeaderFormat(datesRepDistinctDays, dayCnt) {
        // if more than one week row, or if there are a lot of columns with not much space,
        // put just the day numbers will be in each cell
        if (!datesRepDistinctDays || dayCnt > 10) {
            return createFormatter({
                weekday: 'short'
            }); // "Sat"
        }
        if (dayCnt > 1) {
            return createFormatter({
                weekday: 'short',
                month: 'numeric',
                day: 'numeric',
                omitCommas: true
            }); // "Sat 11/12"
        }
        return createFormatter({
            weekday: 'long'
        }); // "Saturday"
    }

    const CLASS_NAME = 'fc-col-header-cell'; // do the cushion too? no
    function renderInner$1(renderProps) {
        return renderProps.text;
    }

    // BAD name for this class now. used in the Header
    class TableDateCell extends BaseComponent {
        render() {
            let {
                dateEnv,
                options,
                theme,
                viewApi
            } = this.context;
            let {
                props
            } = this;
            let {
                date,
                dateProfile
            } = props;
            let dayMeta = getDateMeta(date, props.todayRange, null, dateProfile);
            let classNames = [CLASS_NAME].concat(getDayClassNames(dayMeta, theme));
            let text = dateEnv.format(date, props.dayHeaderFormat);
            // if colCnt is 1, we are already in a day-view and don't need a navlink
            let navLinkAttrs = (!dayMeta.isDisabled && props.colCnt > 1) ?
                buildNavLinkAttrs(this.context, date) :
                {};
            let publicDate = dateEnv.toDate(date);
            // workaround for Luxon (and maybe moment) returning prior-days when start-of-day
            // in DST gap: https://github.com/fullcalendar/fullcalendar/issues/7633
            if (dateEnv.namedTimeZoneImpl) {
                publicDate = addMs(publicDate, 3600000); // add an hour
            }
            let renderProps = Object.assign(Object.assign(Object.assign({
                date: publicDate,
                view: viewApi
            }, props.extraRenderProps), {
                text
            }), dayMeta);
            return (y(ContentContainer, {
                elTag: "th",
                elClasses: classNames,
                elAttrs: Object.assign({
                    role: 'columnheader',
                    colSpan: props.colSpan,
                    'data-date': !dayMeta.isDisabled ? formatDayString(date) : undefined
                }, props.extraDataAttrs),
                renderProps: renderProps,
                generatorName: "dayHeaderContent",
                customGenerator: options.dayHeaderContent,
                defaultGenerator: renderInner$1,
                classNameGenerator: options.dayHeaderClassNames,
                didMount: options.dayHeaderDidMount,
                willUnmount: options.dayHeaderWillUnmount
            }, (InnerContainer) => (y("div", {
                className: "fc-scrollgrid-sync-inner"
            }, !dayMeta.isDisabled && (y(InnerContainer, {
                elTag: "a",
                elAttrs: navLinkAttrs,
                elClasses: [
                    'fc-col-header-cell-cushion',
                    props.isSticky && 'fc-sticky',
                ]
            }))))));
        }
    }

    const WEEKDAY_FORMAT = createFormatter({
        weekday: 'long'
    });
    class TableDowCell extends BaseComponent {
        render() {
            let {
                props
            } = this;
            let {
                dateEnv,
                theme,
                viewApi,
                options
            } = this.context;
            let date = addDays(new Date(259200000), props.dow); // start with Sun, 04 Jan 1970 00:00:00 GMT
            let dateMeta = {
                dow: props.dow,
                isDisabled: false,
                isFuture: false,
                isPast: false,
                isToday: false,
                isOther: false,
            };
            let text = dateEnv.format(date, props.dayHeaderFormat);
            let renderProps = Object.assign(Object.assign(Object.assign(Object.assign({ // TODO: make this public?
                date
            }, dateMeta), {
                view: viewApi
            }), props.extraRenderProps), {
                text
            });
            return (y(ContentContainer, {
                elTag: "th",
                elClasses: [
                    CLASS_NAME,
                    ...getDayClassNames(dateMeta, theme),
                    ...(props.extraClassNames || []),
                ],
                elAttrs: Object.assign({
                    role: 'columnheader',
                    colSpan: props.colSpan
                }, props.extraDataAttrs),
                renderProps: renderProps,
                generatorName: "dayHeaderContent",
                customGenerator: options.dayHeaderContent,
                defaultGenerator: renderInner$1,
                classNameGenerator: options.dayHeaderClassNames,
                didMount: options.dayHeaderDidMount,
                willUnmount: options.dayHeaderWillUnmount
            }, (InnerContent) => (y("div", {
                    className: "fc-scrollgrid-sync-inner"
                },
                y(InnerContent, {
                    elTag: "a",
                    elClasses: [
                        'fc-col-header-cell-cushion',
                        props.isSticky && 'fc-sticky',
                    ],
                    elAttrs: {
                        'aria-label': dateEnv.format(date, WEEKDAY_FORMAT),
                    }
                })))));
        }
    }

    class DayHeader extends BaseComponent {
        constructor() {
            super(...arguments);
            this.createDayHeaderFormatter = memoize(createDayHeaderFormatter);
        }
        render() {
            let {
                context
            } = this;
            let {
                dates,
                dateProfile,
                datesRepDistinctDays,
                renderIntro
            } = this.props;
            let dayHeaderFormat = this.createDayHeaderFormatter(context.options.dayHeaderFormat, datesRepDistinctDays, dates.length);
            return (y(NowTimer, {
                unit: "day"
            }, (nowDate, todayRange) => (y("tr", {
                    role: "row"
                },
                renderIntro && renderIntro('day'),
                dates.map((date) => (datesRepDistinctDays ? (y(TableDateCell, {
                    key: date.toISOString(),
                    date: date,
                    dateProfile: dateProfile,
                    todayRange: todayRange,
                    colCnt: dates.length,
                    dayHeaderFormat: dayHeaderFormat
                })) : (y(TableDowCell, {
                    key: date.getUTCDay(),
                    dow: date.getUTCDay(),
                    dayHeaderFormat: dayHeaderFormat
                }))))))));
        }
    }

    function createDayHeaderFormatter(explicitFormat, datesRepDistinctDays, dateCnt) {
        return explicitFormat || computeFallbackHeaderFormat(datesRepDistinctDays, dateCnt);
    }

    class DaySeriesModel {
        constructor(range, dateProfileGenerator) {
            let date = range.start;
            let {
                end
            } = range;
            let indices = [];
            let dates = [];
            let dayIndex = -1;
            while (date < end) { // loop each day from start to end
                if (dateProfileGenerator.isHiddenDay(date)) {
                    indices.push(dayIndex + 0.5); // mark that it's between indices
                } else {
                    dayIndex += 1;
                    indices.push(dayIndex);
                    dates.push(date);
                }
                date = addDays(date, 1);
            }
            this.dates = dates;
            this.indices = indices;
            this.cnt = dates.length;
        }
        sliceRange(range) {
            let firstIndex = this.getDateDayIndex(range.start); // inclusive first index
            let lastIndex = this.getDateDayIndex(addDays(range.end, -1)); // inclusive last index
            let clippedFirstIndex = Math.max(0, firstIndex);
            let clippedLastIndex = Math.min(this.cnt - 1, lastIndex);
            // deal with in-between indices
            clippedFirstIndex = Math.ceil(clippedFirstIndex); // in-between starts round to next cell
            clippedLastIndex = Math.floor(clippedLastIndex); // in-between ends round to prev cell
            if (clippedFirstIndex <= clippedLastIndex) {
                return {
                    firstIndex: clippedFirstIndex,
                    lastIndex: clippedLastIndex,
                    isStart: firstIndex === clippedFirstIndex,
                    isEnd: lastIndex === clippedLastIndex,
                };
            }
            return null;
        }
        // Given a date, returns its chronolocial cell-index from the first cell of the grid.
        // If the date lies between cells (because of hiddenDays), returns a floating-point value between offsets.
        // If before the first offset, returns a negative number.
        // If after the last offset, returns an offset past the last cell offset.
        // Only works for *start* dates of cells. Will not work for exclusive end dates for cells.
        getDateDayIndex(date) {
            let {
                indices
            } = this;
            let dayOffset = Math.floor(diffDays(this.dates[0], date));
            if (dayOffset < 0) {
                return indices[0] - 1;
            }
            if (dayOffset >= indices.length) {
                return indices[indices.length - 1] + 1;
            }
            return indices[dayOffset];
        }
    }

    class DayTableModel {
        constructor(daySeries, breakOnWeeks) {
            let {
                dates
            } = daySeries;
            let daysPerRow;
            let firstDay;
            let rowCnt;
            if (breakOnWeeks) {
                // count columns until the day-of-week repeats
                firstDay = dates[0].getUTCDay();
                for (daysPerRow = 1; daysPerRow < dates.length; daysPerRow += 1) {
                    if (dates[daysPerRow].getUTCDay() === firstDay) {
                        break;
                    }
                }
                rowCnt = Math.ceil(dates.length / daysPerRow);
            } else {
                rowCnt = 1;
                daysPerRow = dates.length;
            }
            this.rowCnt = rowCnt;
            this.colCnt = daysPerRow;
            this.daySeries = daySeries;
            this.cells = this.buildCells();
            this.headerDates = this.buildHeaderDates();
        }
        buildCells() {
            let rows = [];
            for (let row = 0; row < this.rowCnt; row += 1) {
                let cells = [];
                for (let col = 0; col < this.colCnt; col += 1) {
                    cells.push(this.buildCell(row, col));
                }
                rows.push(cells);
            }
            return rows;
        }
        buildCell(row, col) {
            let date = this.daySeries.dates[row * this.colCnt + col];
            return {
                key: date.toISOString(),
                date,
            };
        }
        buildHeaderDates() {
            let dates = [];
            for (let col = 0; col < this.colCnt; col += 1) {
                dates.push(this.cells[0][col].date);
            }
            return dates;
        }
        sliceRange(range) {
            let {
                colCnt
            } = this;
            let seriesSeg = this.daySeries.sliceRange(range);
            let segs = [];
            if (seriesSeg) {
                let {
                    firstIndex,
                    lastIndex
                } = seriesSeg;
                let index = firstIndex;
                while (index <= lastIndex) {
                    let row = Math.floor(index / colCnt);
                    let nextIndex = Math.min((row + 1) * colCnt, lastIndex + 1);
                    segs.push({
                        row,
                        firstCol: index % colCnt,
                        lastCol: (nextIndex - 1) % colCnt,
                        isStart: seriesSeg.isStart && index === firstIndex,
                        isEnd: seriesSeg.isEnd && (nextIndex - 1) === lastIndex,
                    });
                    index = nextIndex;
                }
            }
            return segs;
        }
    }

    class Slicer {
        constructor() {
            this.sliceBusinessHours = memoize(this._sliceBusinessHours);
            this.sliceDateSelection = memoize(this._sliceDateSpan);
            this.sliceEventStore = memoize(this._sliceEventStore);
            this.sliceEventDrag = memoize(this._sliceInteraction);
            this.sliceEventResize = memoize(this._sliceInteraction);
            this.forceDayIfListItem = false; // hack
        }
        sliceProps(props, dateProfile, nextDayThreshold, context, ...extraArgs) {
            let {
                eventUiBases
            } = props;
            let eventSegs = this.sliceEventStore(props.eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs);
            return {
                dateSelectionSegs: this.sliceDateSelection(props.dateSelection, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs),
                businessHourSegs: this.sliceBusinessHours(props.businessHours, dateProfile, nextDayThreshold, context, ...extraArgs),
                fgEventSegs: eventSegs.fg,
                bgEventSegs: eventSegs.bg,
                eventDrag: this.sliceEventDrag(props.eventDrag, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
                eventResize: this.sliceEventResize(props.eventResize, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs),
                eventSelection: props.eventSelection,
            }; // TODO: give interactionSegs?
        }
        sliceNowDate( // does not memoize
            date, dateProfile, nextDayThreshold, context, ...extraArgs) {
            return this._sliceDateSpan({
                    range: {
                        start: date,
                        end: addMs(date, 1)
                    },
                    allDay: false
                }, // add 1 ms, protect against null range
                dateProfile, nextDayThreshold, {}, context, ...extraArgs);
        }
        _sliceBusinessHours(businessHours, dateProfile, nextDayThreshold, context, ...extraArgs) {
            if (!businessHours) {
                return [];
            }
            return this._sliceEventStore(expandRecurring(businessHours, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), context), {}, dateProfile, nextDayThreshold, ...extraArgs).bg;
        }
        _sliceEventStore(eventStore, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
            if (eventStore) {
                let rangeRes = sliceEventStore(eventStore, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
                return {
                    bg: this.sliceEventRanges(rangeRes.bg, extraArgs),
                    fg: this.sliceEventRanges(rangeRes.fg, extraArgs),
                };
            }
            return {
                bg: [],
                fg: []
            };
        }
        _sliceInteraction(interaction, eventUiBases, dateProfile, nextDayThreshold, ...extraArgs) {
            if (!interaction) {
                return null;
            }
            let rangeRes = sliceEventStore(interaction.mutatedEvents, eventUiBases, computeActiveRange(dateProfile, Boolean(nextDayThreshold)), nextDayThreshold);
            return {
                segs: this.sliceEventRanges(rangeRes.fg, extraArgs),
                affectedInstances: interaction.affectedEvents.instances,
                isEvent: interaction.isEvent,
            };
        }
        _sliceDateSpan(dateSpan, dateProfile, nextDayThreshold, eventUiBases, context, ...extraArgs) {
            if (!dateSpan) {
                return [];
            }
            let activeRange = computeActiveRange(dateProfile, Boolean(nextDayThreshold));
            let activeDateSpanRange = intersectRanges(dateSpan.range, activeRange);
            if (activeDateSpanRange) {
                dateSpan = Object.assign(Object.assign({}, dateSpan), {
                    range: activeDateSpanRange
                });
                let eventRange = fabricateEventRange(dateSpan, eventUiBases, context);
                let segs = this.sliceRange(dateSpan.range, ...extraArgs);
                for (let seg of segs) {
                    seg.eventRange = eventRange;
                }
                return segs;
            }
            return [];
        }
        /*
        "complete" seg means it has component and eventRange
        */
        sliceEventRanges(eventRanges, extraArgs) {
            let segs = [];
            for (let eventRange of eventRanges) {
                segs.push(...this.sliceEventRange(eventRange, extraArgs));
            }
            return segs;
        }
        /*
        "complete" seg means it has component and eventRange
        */
        sliceEventRange(eventRange, extraArgs) {
            let dateRange = eventRange.range;
            // hack to make multi-day events that are being force-displayed as list-items to take up only one day
            if (this.forceDayIfListItem && eventRange.ui.display === 'list-item') {
                dateRange = {
                    start: dateRange.start,
                    end: addDays(dateRange.start, 1),
                };
            }
            let segs = this.sliceRange(dateRange, ...extraArgs);
            for (let seg of segs) {
                seg.eventRange = eventRange;
                seg.isStart = eventRange.isStart && seg.isStart;
                seg.isEnd = eventRange.isEnd && seg.isEnd;
            }
            return segs;
        }
    }
    /*
    for incorporating slotMinTime/slotMaxTime if appropriate
    TODO: should be part of DateProfile!
    TimelineDateProfile already does this btw
    */
    function computeActiveRange(dateProfile, isComponentAllDay) {
        let range = dateProfile.activeRange;
        if (isComponentAllDay) {
            return range;
        }
        return {
            start: addMs(range.start, dateProfile.slotMinTime.milliseconds),
            end: addMs(range.end, dateProfile.slotMaxTime.milliseconds - 864e5), // 864e5 = ms in a day
        };
    }

    // high-level segmenting-aware tester functions
    // ------------------------------------------------------------------------------------------------------------------------
    function isInteractionValid(interaction, dateProfile, context) {
        let {
            instances
        } = interaction.mutatedEvents;
        for (let instanceId in instances) {
            if (!rangeContainsRange(dateProfile.validRange, instances[instanceId].range)) {
                return false;
            }
        }
        return isNewPropsValid({
            eventDrag: interaction
        }, context); // HACK: the eventDrag props is used for ALL interactions
    }

    function isDateSelectionValid(dateSelection, dateProfile, context) {
        if (!rangeContainsRange(dateProfile.validRange, dateSelection.range)) {
            return false;
        }
        return isNewPropsValid({
            dateSelection
        }, context);
    }

    function isNewPropsValid(newProps, context) {
        let calendarState = context.getCurrentData();
        let props = Object.assign({
            businessHours: calendarState.businessHours,
            dateSelection: '',
            eventStore: calendarState.eventStore,
            eventUiBases: calendarState.eventUiBases,
            eventSelection: '',
            eventDrag: null,
            eventResize: null
        }, newProps);
        return (context.pluginHooks.isPropsValid || isPropsValid)(props, context);
    }

    function isPropsValid(state, context, dateSpanMeta = {}, filterConfig) {
        if (state.eventDrag && !isInteractionPropsValid(state, context, dateSpanMeta, filterConfig)) {
            return false;
        }
        if (state.dateSelection && !isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig)) {
            return false;
        }
        return true;
    }
    // Moving Event Validation
    // ------------------------------------------------------------------------------------------------------------------------
    function isInteractionPropsValid(state, context, dateSpanMeta, filterConfig) {
        let currentState = context.getCurrentData();
        let interaction = state.eventDrag; // HACK: the eventDrag props is used for ALL interactions
        let subjectEventStore = interaction.mutatedEvents;
        let subjectDefs = subjectEventStore.defs;
        let subjectInstances = subjectEventStore.instances;
        let subjectConfigs = compileEventUis(subjectDefs, interaction.isEvent ?
            state.eventUiBases : {
                '': currentState.selectionConfig
            });
        if (filterConfig) {
            subjectConfigs = mapHash(subjectConfigs, filterConfig);
        }
        // exclude the subject events. TODO: exclude defs too?
        let otherEventStore = excludeInstances(state.eventStore, interaction.affectedEvents.instances);
        let otherDefs = otherEventStore.defs;
        let otherInstances = otherEventStore.instances;
        let otherConfigs = compileEventUis(otherDefs, state.eventUiBases);
        for (let subjectInstanceId in subjectInstances) {
            let subjectInstance = subjectInstances[subjectInstanceId];
            let subjectRange = subjectInstance.range;
            let subjectConfig = subjectConfigs[subjectInstance.defId];
            let subjectDef = subjectDefs[subjectInstance.defId];
            // constraint
            if (!allConstraintsPass(subjectConfig.constraints, subjectRange, otherEventStore, state.businessHours, context)) {
                return false;
            }
            // overlap
            let {
                eventOverlap
            } = context.options;
            let eventOverlapFunc = typeof eventOverlap === 'function' ? eventOverlap : null;
            for (let otherInstanceId in otherInstances) {
                let otherInstance = otherInstances[otherInstanceId];
                // intersect! evaluate
                if (rangesIntersect(subjectRange, otherInstance.range)) {
                    let otherOverlap = otherConfigs[otherInstance.defId].overlap;
                    // consider the other event's overlap. only do this if the subject event is a "real" event
                    if (otherOverlap === false && interaction.isEvent) {
                        return false;
                    }
                    if (subjectConfig.overlap === false) {
                        return false;
                    }
                    if (eventOverlapFunc && !eventOverlapFunc(new EventImpl(context, otherDefs[otherInstance.defId], otherInstance), // still event
                            new EventImpl(context, subjectDef, subjectInstance))) {
                        return false;
                    }
                }
            }
            // allow (a function)
            let calendarEventStore = currentState.eventStore; // need global-to-calendar, not local to component (splittable)state
            for (let subjectAllow of subjectConfig.allows) {
                let subjectDateSpan = Object.assign(Object.assign({}, dateSpanMeta), {
                    range: subjectInstance.range,
                    allDay: subjectDef.allDay
                });
                let origDef = calendarEventStore.defs[subjectDef.defId];
                let origInstance = calendarEventStore.instances[subjectInstanceId];
                let eventApi;
                if (origDef) { // was previously in the calendar
                    eventApi = new EventImpl(context, origDef, origInstance);
                } else { // was an external event
                    eventApi = new EventImpl(context, subjectDef); // no instance, because had no dates
                }
                if (!subjectAllow(buildDateSpanApiWithContext(subjectDateSpan, context), eventApi)) {
                    return false;
                }
            }
        }
        return true;
    }
    // Date Selection Validation
    // ------------------------------------------------------------------------------------------------------------------------
    function isDateSelectionPropsValid(state, context, dateSpanMeta, filterConfig) {
        let relevantEventStore = state.eventStore;
        let relevantDefs = relevantEventStore.defs;
        let relevantInstances = relevantEventStore.instances;
        let selection = state.dateSelection;
        let selectionRange = selection.range;
        let {
            selectionConfig
        } = context.getCurrentData();
        if (filterConfig) {
            selectionConfig = filterConfig(selectionConfig);
        }
        // constraint
        if (!allConstraintsPass(selectionConfig.constraints, selectionRange, relevantEventStore, state.businessHours, context)) {
            return false;
        }
        // overlap
        let {
            selectOverlap
        } = context.options;
        let selectOverlapFunc = typeof selectOverlap === 'function' ? selectOverlap : null;
        for (let relevantInstanceId in relevantInstances) {
            let relevantInstance = relevantInstances[relevantInstanceId];
            // intersect! evaluate
            if (rangesIntersect(selectionRange, relevantInstance.range)) {
                if (selectionConfig.overlap === false) {
                    return false;
                }
                if (selectOverlapFunc && !selectOverlapFunc(new EventImpl(context, relevantDefs[relevantInstance.defId], relevantInstance), null)) {
                    return false;
                }
            }
        }
        // allow (a function)
        for (let selectionAllow of selectionConfig.allows) {
            let fullDateSpan = Object.assign(Object.assign({}, dateSpanMeta), selection);
            if (!selectionAllow(buildDateSpanApiWithContext(fullDateSpan, context), null)) {
                return false;
            }
        }
        return true;
    }
    // Constraint Utils
    // ------------------------------------------------------------------------------------------------------------------------
    function allConstraintsPass(constraints, subjectRange, otherEventStore, businessHoursUnexpanded, context) {
        for (let constraint of constraints) {
            if (!anyRangesContainRange(constraintToRanges(constraint, subjectRange, otherEventStore, businessHoursUnexpanded, context), subjectRange)) {
                return false;
            }
        }
        return true;
    }

    function constraintToRanges(constraint, subjectRange, // for expanding a recurring constraint, or expanding business hours
        otherEventStore, // for if constraint is an even group ID
        businessHoursUnexpanded, // for if constraint is 'businessHours'
        context) {
        if (constraint === 'businessHours') {
            return eventStoreToRanges(expandRecurring(businessHoursUnexpanded, subjectRange, context));
        }
        if (typeof constraint === 'string') { // an group ID
            return eventStoreToRanges(filterEventStoreDefs(otherEventStore, (eventDef) => eventDef.groupId === constraint));
        }
        if (typeof constraint === 'object' && constraint) { // non-null object
            return eventStoreToRanges(expandRecurring(constraint, subjectRange, context));
        }
        return []; // if it's false
    }
    // TODO: move to event-store file?
    function eventStoreToRanges(eventStore) {
        let {
            instances
        } = eventStore;
        let ranges = [];
        for (let instanceId in instances) {
            ranges.push(instances[instanceId].range);
        }
        return ranges;
    }
    // TODO: move to geom file?
    function anyRangesContainRange(outerRanges, innerRange) {
        for (let outerRange of outerRanges) {
            if (rangeContainsRange(outerRange, innerRange)) {
                return true;
            }
        }
        return false;
    }

    const VISIBLE_HIDDEN_RE = /^(visible|hidden)$/;
    class Scroller extends BaseComponent {
        constructor() {
            super(...arguments);
            this.handleEl = (el) => {
                this.el = el;
                setRef(this.props.elRef, el);
            };
        }
        render() {
            let {
                props
            } = this;
            let {
                liquid,
                liquidIsAbsolute
            } = props;
            let isAbsolute = liquid && liquidIsAbsolute;
            let className = ['fc-scroller'];
            if (liquid) {
                if (liquidIsAbsolute) {
                    className.push('fc-scroller-liquid-absolute');
                } else {
                    className.push('fc-scroller-liquid');
                }
            }
            return (y("div", {
                ref: this.handleEl,
                className: className.join(' '),
                style: {
                    overflowX: props.overflowX,
                    overflowY: props.overflowY,
                    left: (isAbsolute && -(props.overcomeLeft || 0)) || '',
                    right: (isAbsolute && -(props.overcomeRight || 0)) || '',
                    bottom: (isAbsolute && -(props.overcomeBottom || 0)) || '',
                    marginLeft: (!isAbsolute && -(props.overcomeLeft || 0)) || '',
                    marginRight: (!isAbsolute && -(props.overcomeRight || 0)) || '',
                    marginBottom: (!isAbsolute && -(props.overcomeBottom || 0)) || '',
                    maxHeight: props.maxHeight || '',
                }
            }, props.children));
        }
        needsXScrolling() {
            if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
                return false;
            }
            // testing scrollWidth>clientWidth is unreliable cross-browser when pixel heights aren't integers.
            // much more reliable to see if children are taller than the scroller, even tho doesn't account for
            // inner-child margins and absolute positioning
            let {
                el
            } = this;
            let realClientWidth = this.el.getBoundingClientRect().width - this.getYScrollbarWidth();
            let {
                children
            } = el;
            for (let i = 0; i < children.length; i += 1) {
                let childEl = children[i];
                if (childEl.getBoundingClientRect().width > realClientWidth) {
                    return true;
                }
            }
            return false;
        }
        needsYScrolling() {
            if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
                return false;
            }
            // testing scrollHeight>clientHeight is unreliable cross-browser when pixel heights aren't integers.
            // much more reliable to see if children are taller than the scroller, even tho doesn't account for
            // inner-child margins and absolute positioning
            let {
                el
            } = this;
            let realClientHeight = this.el.getBoundingClientRect().height - this.getXScrollbarWidth();
            let {
                children
            } = el;
            for (let i = 0; i < children.length; i += 1) {
                let childEl = children[i];
                if (childEl.getBoundingClientRect().height > realClientHeight) {
                    return true;
                }
            }
            return false;
        }
        getXScrollbarWidth() {
            if (VISIBLE_HIDDEN_RE.test(this.props.overflowX)) {
                return 0;
            }
            return this.el.offsetHeight - this.el.clientHeight; // only works because we guarantee no borders. TODO: add to CSS with important?
        }
        getYScrollbarWidth() {
            if (VISIBLE_HIDDEN_RE.test(this.props.overflowY)) {
                return 0;
            }
            return this.el.offsetWidth - this.el.clientWidth; // only works because we guarantee no borders. TODO: add to CSS with important?
        }
    }

    /*
    TODO: somehow infer OtherArgs from masterCallback?
    TODO: infer RefType from masterCallback if provided
    */
    class RefMap {
        constructor(masterCallback) {
            this.masterCallback = masterCallback;
            this.currentMap = {};
            this.depths = {};
            this.callbackMap = {};
            this.handleValue = (val, key) => {
                let {
                    depths,
                    currentMap
                } = this;
                let removed = false;
                let added = false;
                if (val !== null) {
                    // for bug... ACTUALLY: can probably do away with this now that callers don't share numeric indices anymore
                    removed = (key in currentMap);
                    currentMap[key] = val;
                    depths[key] = (depths[key] || 0) + 1;
                    added = true;
                } else {
                    depths[key] -= 1;
                    if (!depths[key]) {
                        delete currentMap[key];
                        delete this.callbackMap[key];
                        removed = true;
                    }
                }
                if (this.masterCallback) {
                    if (removed) {
                        this.masterCallback(null, String(key));
                    }
                    if (added) {
                        this.masterCallback(val, String(key));
                    }
                }
            };
        }
        createRef(key) {
            let refCallback = this.callbackMap[key];
            if (!refCallback) {
                refCallback = this.callbackMap[key] = (val) => {
                    this.handleValue(val, String(key));
                };
            }
            return refCallback;
        }
        // TODO: check callers that don't care about order. should use getAll instead
        // NOTE: this method has become less valuable now that we are encouraged to map order by some other index
        // TODO: provide ONE array-export function, buildArray, which fails on non-numeric indexes. caller can manipulate and "collect"
        collect(startIndex, endIndex, step) {
            return collectFromHash(this.currentMap, startIndex, endIndex, step);
        }
        getAll() {
            return hashValuesToArray(this.currentMap);
        }
    }

    function computeShrinkWidth(chunkEls) {
        let shrinkCells = findElements(chunkEls, '.fc-scrollgrid-shrink');
        let largestWidth = 0;
        for (let shrinkCell of shrinkCells) {
            largestWidth = Math.max(largestWidth, computeSmallestCellWidth(shrinkCell));
        }
        return Math.ceil(largestWidth); // <table> elements work best with integers. round up to ensure contents fits
    }

    function getSectionHasLiquidHeight(props, sectionConfig) {
        return props.liquid && sectionConfig.liquid; // does the section do liquid-height? (need to have whole scrollgrid liquid-height as well)
    }

    function getAllowYScrolling(props, sectionConfig) {
        return sectionConfig.maxHeight != null || // if its possible for the height to max out, we might need scrollbars
            getSectionHasLiquidHeight(props, sectionConfig); // if the section is liquid height, it might condense enough to require scrollbars
    }
    // TODO: ONLY use `arg`. force out internal function to use same API
    function renderChunkContent(sectionConfig, chunkConfig, arg, isHeader) {
        let {
            expandRows
        } = arg;
        let content = typeof chunkConfig.content === 'function' ?
            chunkConfig.content(arg) :
            y('table', {
                role: 'presentation',
                className: [
                    chunkConfig.tableClassName,
                    sectionConfig.syncRowHeights ? 'fc-scrollgrid-sync-table' : '',
                ].join(' '),
                style: {
                    minWidth: arg.tableMinWidth,
                    width: arg.clientWidth,
                    height: expandRows ? arg.clientHeight : '', // css `height` on a <table> serves as a min-height
                },
            }, arg.tableColGroupNode, y(isHeader ? 'thead' : 'tbody', {
                    role: 'presentation',
                }, typeof chunkConfig.rowContent === 'function' ?
                chunkConfig.rowContent(arg) :
                chunkConfig.rowContent));
        return content;
    }

    function isColPropsEqual(cols0, cols1) {
        return isArraysEqual(cols0, cols1, isPropsEqual);
    }

    function renderMicroColGroup(cols, shrinkWidth) {
        let colNodes = [];
        /*
        for ColProps with spans, it would have been great to make a single <col span="">
        HOWEVER, Chrome was getting messing up distributing the width to <td>/<th> elements with colspans.
        SOLUTION: making individual <col> elements makes Chrome behave.
        */
        for (let colProps of cols) {
            let span = colProps.span || 1;
            for (let i = 0; i < span; i += 1) {
                colNodes.push(y("col", {
                    style: {
                        width: colProps.width === 'shrink' ? sanitizeShrinkWidth(shrinkWidth) : (colProps.width || ''),
                        minWidth: colProps.minWidth || '',
                    }
                }));
            }
        }
        return y('colgroup', {}, ...colNodes);
    }

    function sanitizeShrinkWidth(shrinkWidth) {
        /* why 4? if we do 0, it will kill any border, which are needed for computeSmallestCellWidth
        4 accounts for 2 2-pixel borders. TODO: better solution? */
        return shrinkWidth == null ? 4 : shrinkWidth;
    }

    function hasShrinkWidth(cols) {
        for (let col of cols) {
            if (col.width === 'shrink') {
                return true;
            }
        }
        return false;
    }

    function getScrollGridClassNames(liquid, context) {
        let classNames = [
            'fc-scrollgrid',
            context.theme.getClass('table'),
        ];
        if (liquid) {
            classNames.push('fc-scrollgrid-liquid');
        }
        return classNames;
    }

    function getSectionClassNames(sectionConfig, wholeTableVGrow) {
        let classNames = [
            'fc-scrollgrid-section',
            `fc-scrollgrid-section-${sectionConfig.type}`,
            sectionConfig.className, // used?
        ];
        if (wholeTableVGrow && sectionConfig.liquid && sectionConfig.maxHeight == null) {
            classNames.push('fc-scrollgrid-section-liquid');
        }
        if (sectionConfig.isSticky) {
            classNames.push('fc-scrollgrid-section-sticky');
        }
        return classNames;
    }

    function renderScrollShim(arg) {
        return (y("div", {
            className: "fc-scrollgrid-sticky-shim",
            style: {
                width: arg.clientWidth,
                minWidth: arg.tableMinWidth,
            }
        }));
    }

    function getStickyHeaderDates(options) {
        let {
            stickyHeaderDates
        } = options;
        if (stickyHeaderDates == null || stickyHeaderDates === 'auto') {
            stickyHeaderDates = options.height === 'auto' || options.viewHeight === 'auto';
        }
        return stickyHeaderDates;
    }

    function getStickyFooterScrollbar(options) {
        let {
            stickyFooterScrollbar
        } = options;
        if (stickyFooterScrollbar == null || stickyFooterScrollbar === 'auto') {
            stickyFooterScrollbar = options.height === 'auto' || options.viewHeight === 'auto';
        }
        return stickyFooterScrollbar;
    }

    class SimpleScrollGrid extends BaseComponent {
        constructor() {
            super(...arguments);
            this.processCols = memoize((a) => a, isColPropsEqual); // so we get same `cols` props every time
            // yucky to memoize VNodes, but much more efficient for consumers
            this.renderMicroColGroup = memoize(renderMicroColGroup);
            this.scrollerRefs = new RefMap();
            this.scrollerElRefs = new RefMap(this._handleScrollerEl.bind(this));
            this.state = {
                shrinkWidth: null,
                forceYScrollbars: false,
                scrollerClientWidths: {},
                scrollerClientHeights: {},
            };
            // TODO: can do a really simple print-view. dont need to join rows
            this.handleSizing = () => {
                this.safeSetState(Object.assign({
                    shrinkWidth: this.computeShrinkWidth()
                }, this.computeScrollerDims()));
            };
        }
        render() {
            let {
                props,
                state,
                context
            } = this;
            let sectionConfigs = props.sections || [];
            let cols = this.processCols(props.cols);
            let microColGroupNode = this.renderMicroColGroup(cols, state.shrinkWidth);
            let classNames = getScrollGridClassNames(props.liquid, context);
            if (props.collapsibleWidth) {
                classNames.push('fc-scrollgrid-collapsible');
            }
            // TODO: make DRY
            let configCnt = sectionConfigs.length;
            let configI = 0;
            let currentConfig;
            let headSectionNodes = [];
            let bodySectionNodes = [];
            let footSectionNodes = [];
            while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'header') {
                headSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
                configI += 1;
            }
            while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'body') {
                bodySectionNodes.push(this.renderSection(currentConfig, microColGroupNode, false));
                configI += 1;
            }
            while (configI < configCnt && (currentConfig = sectionConfigs[configI]).type === 'footer') {
                footSectionNodes.push(this.renderSection(currentConfig, microColGroupNode, true));
                configI += 1;
            }
            // firefox bug: when setting height on table and there is a thead or tfoot,
            // the necessary height:100% on the liquid-height body section forces the *whole* table to be taller. (bug #5524)
            // use getCanVGrowWithinCell as a way to detect table-stupid firefox.
            // if so, use a simpler dom structure, jam everything into a lone tbody.
            let isBuggy = !getCanVGrowWithinCell();
            const roleAttrs = {
                role: 'rowgroup'
            };
            return y('table', {
                role: 'grid',
                className: classNames.join(' '),
                style: {
                    height: props.height
                },
            }, Boolean(!isBuggy && headSectionNodes.length) && y('thead', roleAttrs, ...headSectionNodes), Boolean(!isBuggy && bodySectionNodes.length) && y('tbody', roleAttrs, ...bodySectionNodes), Boolean(!isBuggy && footSectionNodes.length) && y('tfoot', roleAttrs, ...footSectionNodes), isBuggy && y('tbody', roleAttrs, ...headSectionNodes, ...bodySectionNodes, ...footSectionNodes));
        }
        renderSection(sectionConfig, microColGroupNode, isHeader) {
            if ('outerContent' in sectionConfig) {
                return (y(_, {
                    key: sectionConfig.key
                }, sectionConfig.outerContent));
            }
            return (y("tr", {
                key: sectionConfig.key,
                role: "presentation",
                className: getSectionClassNames(sectionConfig, this.props.liquid).join(' ')
            }, this.renderChunkTd(sectionConfig, microColGroupNode, sectionConfig.chunk, isHeader)));
        }
        renderChunkTd(sectionConfig, microColGroupNode, chunkConfig, isHeader) {
            if ('outerContent' in chunkConfig) {
                return chunkConfig.outerContent;
            }
            let {
                props
            } = this;
            let {
                forceYScrollbars,
                scrollerClientWidths,
                scrollerClientHeights
            } = this.state;
            let needsYScrolling = getAllowYScrolling(props, sectionConfig); // TODO: do lazily. do in section config?
            let isLiquid = getSectionHasLiquidHeight(props, sectionConfig);
            // for `!props.liquid` - is WHOLE scrollgrid natural height?
            // TODO: do same thing in advanced scrollgrid? prolly not b/c always has horizontal scrollbars
            let overflowY = !props.liquid ? 'visible' :
                forceYScrollbars ? 'scroll' :
                !needsYScrolling ? 'hidden' :
                'auto';
            let sectionKey = sectionConfig.key;
            let content = renderChunkContent(sectionConfig, chunkConfig, {
                tableColGroupNode: microColGroupNode,
                tableMinWidth: '',
                clientWidth: (!props.collapsibleWidth && scrollerClientWidths[sectionKey] !== undefined) ? scrollerClientWidths[sectionKey] : null,
                clientHeight: scrollerClientHeights[sectionKey] !== undefined ? scrollerClientHeights[sectionKey] : null,
                expandRows: sectionConfig.expandRows,
                syncRowHeights: false,
                rowSyncHeights: [],
                reportRowHeightChange: () => {},
            }, isHeader);
            return y(isHeader ? 'th' : 'td', {
                ref: chunkConfig.elRef,
                role: 'presentation',
            }, y("div", {
                    className: `fc-scroller-harness${isLiquid ? ' fc-scroller-harness-liquid' : ''}`
                },
                y(Scroller, {
                    ref: this.scrollerRefs.createRef(sectionKey),
                    elRef: this.scrollerElRefs.createRef(sectionKey),
                    overflowY: overflowY,
                    overflowX: !props.liquid ? 'visible' : 'hidden' /* natural height? */ ,
                    maxHeight: sectionConfig.maxHeight,
                    liquid: isLiquid,
                    liquidIsAbsolute // because its within a harness
                    : true
                }, content)));
        }
        _handleScrollerEl(scrollerEl, key) {
            let section = getSectionByKey(this.props.sections, key);
            if (section) {
                setRef(section.chunk.scrollerElRef, scrollerEl);
            }
        }
        componentDidMount() {
            this.handleSizing();
            this.context.addResizeHandler(this.handleSizing);
        }
        componentDidUpdate() {
            // TODO: need better solution when state contains non-sizing things
            this.handleSizing();
        }
        componentWillUnmount() {
            this.context.removeResizeHandler(this.handleSizing);
        }
        computeShrinkWidth() {
            return hasShrinkWidth(this.props.cols) ?
                computeShrinkWidth(this.scrollerElRefs.getAll()) :
                0;
        }
        computeScrollerDims() {
            let scrollbarWidth = getScrollbarWidths();
            let {
                scrollerRefs,
                scrollerElRefs
            } = this;
            let forceYScrollbars = false;
            let scrollerClientWidths = {};
            let scrollerClientHeights = {};
            for (let sectionKey in scrollerRefs.currentMap) {
                let scroller = scrollerRefs.currentMap[sectionKey];
                if (scroller && scroller.needsYScrolling()) {
                    forceYScrollbars = true;
                    break;
                }
            }
            for (let section of this.props.sections) {
                let sectionKey = section.key;
                let scrollerEl = scrollerElRefs.currentMap[sectionKey];
                if (scrollerEl) {
                    let harnessEl = scrollerEl.parentNode; // TODO: weird way to get this. need harness b/c doesn't include table borders
                    scrollerClientWidths[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().width - (forceYScrollbars ?
                        scrollbarWidth.y // use global because scroller might not have scrollbars yet but will need them in future
                        :
                        0));
                    scrollerClientHeights[sectionKey] = Math.floor(harnessEl.getBoundingClientRect().height);
                }
            }
            return {
                forceYScrollbars,
                scrollerClientWidths,
                scrollerClientHeights
            };
        }
    }
    SimpleScrollGrid.addStateEquality({
        scrollerClientWidths: isPropsEqual,
        scrollerClientHeights: isPropsEqual,
    });

    function getSectionByKey(sections, key) {
        for (let section of sections) {
            if (section.key === key) {
                return section;
            }
        }
        return null;
    }

    class EventContainer extends BaseComponent {
        constructor() {
            super(...arguments);
            // memo
            this.buildPublicEvent = memoize((context, eventDef, eventInstance) => new EventImpl(context, eventDef, eventInstance));
            this.handleEl = (el) => {
                this.el = el;
                setRef(this.props.elRef, el);
                if (el) {
                    setElSeg(el, this.props.seg);
                }
            };
        }
        render() {
            const {
                props,
                context
            } = this;
            const {
                options
            } = context;
            const {
                seg
            } = props;
            const {
                eventRange
            } = seg;
            const {
                ui
            } = eventRange;
            const renderProps = {
                event: this.buildPublicEvent(context, eventRange.def, eventRange.instance),
                view: context.viewApi,
                timeText: props.timeText,
                textColor: ui.textColor,
                backgroundColor: ui.backgroundColor,
                borderColor: ui.borderColor,
                isDraggable: !props.disableDragging && computeSegDraggable(seg, context),
                isStartResizable: !props.disableResizing && computeSegStartResizable(seg, context),
                isEndResizable: !props.disableResizing && computeSegEndResizable(seg),
                isMirror: Boolean(props.isDragging || props.isResizing || props.isDateSelecting),
                isStart: Boolean(seg.isStart),
                isEnd: Boolean(seg.isEnd),
                isPast: Boolean(props.isPast),
                isFuture: Boolean(props.isFuture),
                isToday: Boolean(props.isToday),
                isSelected: Boolean(props.isSelected),
                isDragging: Boolean(props.isDragging),
                isResizing: Boolean(props.isResizing),
            };
            return (y(ContentContainer, {
                elRef: this.handleEl,
                elTag: props.elTag,
                elAttrs: props.elAttrs,
                elClasses: [
                    ...getEventClassNames(renderProps),
                    ...seg.eventRange.ui.classNames,
                    ...(props.elClasses || []),
                ],
                elStyle: props.elStyle,
                renderProps: renderProps,
                generatorName: "eventContent",
                customGenerator: options.eventContent,
                defaultGenerator: props.defaultGenerator,
                classNameGenerator: options.eventClassNames,
                didMount: options.eventDidMount,
                willUnmount: options.eventWillUnmount
            }, props.children));
        }
        componentDidUpdate(prevProps) {
            if (this.el && this.props.seg !== prevProps.seg) {
                setElSeg(this.el, this.props.seg);
            }
        }
    }

    // should not be a purecomponent
    class StandardEvent extends BaseComponent {
        render() {
            let {
                props,
                context
            } = this;
            let {
                options
            } = context;
            let {
                seg
            } = props;
            let {
                ui
            } = seg.eventRange;
            let timeFormat = options.eventTimeFormat || props.defaultTimeFormat;
            let timeText = buildSegTimeText(seg, timeFormat, context, props.defaultDisplayEventTime, props.defaultDisplayEventEnd);
            return (y(EventContainer, Object.assign({}, props /* includes elRef */ , {
                elTag: "a",
                elStyle: {
                    borderColor: ui.borderColor,
                    backgroundColor: ui.backgroundColor,
                },
                elAttrs: getSegAnchorAttrs(seg, context),
                defaultGenerator: renderInnerContent$1$1,
                timeText: timeText
            }), (InnerContent, eventContentArg) => (y(_, null,
                y(InnerContent, {
                    elTag: "div",
                    elClasses: ['fc-event-main'],
                    elStyle: {
                        color: eventContentArg.textColor
                    }
                }),
                Boolean(eventContentArg.isStartResizable) && (y("div", {
                    className: "fc-event-resizer fc-event-resizer-start"
                })),
                Boolean(eventContentArg.isEndResizable) && (y("div", {
                    className: "fc-event-resizer fc-event-resizer-end"
                }))))));
        }
    }
    StandardEvent.addPropsEquality({
        seg: isPropsEqual,
    });

    function renderInnerContent$1$1(innerProps) {
        return (y("div", {
                className: "fc-event-main-frame"
            },
            innerProps.timeText && (y("div", {
                className: "fc-event-time"
            }, innerProps.timeText)),
            y("div", {
                    className: "fc-event-title-container"
                },
                y("div", {
                    className: "fc-event-title fc-sticky"
                }, innerProps.event.title || y(_, null, "\u00A0")))));
    }

    const NowIndicatorContainer = (props) => (y(ViewContextType.Consumer, null, (context) => {
        let {
            options
        } = context;
        let renderProps = {
            isAxis: props.isAxis,
            date: context.dateEnv.toDate(props.date),
            view: context.viewApi,
        };
        return (y(ContentContainer, {
            elRef: props.elRef,
            elTag: props.elTag || 'div',
            elAttrs: props.elAttrs,
            elClasses: props.elClasses,
            elStyle: props.elStyle,
            renderProps: renderProps,
            generatorName: "nowIndicatorContent",
            customGenerator: options.nowIndicatorContent,
            classNameGenerator: options.nowIndicatorClassNames,
            didMount: options.nowIndicatorDidMount,
            willUnmount: options.nowIndicatorWillUnmount
        }, props.children));
    }));

    const DAY_NUM_FORMAT = createFormatter({
        day: 'numeric'
    });
    class DayCellContainer extends BaseComponent {
        constructor() {
            super(...arguments);
            this.refineRenderProps = memoizeObjArg(refineRenderProps);
        }
        render() {
            let {
                props,
                context
            } = this;
            let {
                options
            } = context;
            let renderProps = this.refineRenderProps({
                date: props.date,
                dateProfile: props.dateProfile,
                todayRange: props.todayRange,
                isMonthStart: props.isMonthStart || false,
                showDayNumber: props.showDayNumber,
                extraRenderProps: props.extraRenderProps,
                viewApi: context.viewApi,
                dateEnv: context.dateEnv,
                monthStartFormat: options.monthStartFormat,
            });
            return (y(ContentContainer, {
                elRef: props.elRef,
                elTag: props.elTag,
                elAttrs: Object.assign(Object.assign({}, props.elAttrs), (renderProps.isDisabled ? {} : {
                    'data-date': formatDayString(props.date)
                })),
                elClasses: [
                    ...getDayClassNames(renderProps, context.theme),
                    ...(props.elClasses || []),
                ],
                elStyle: props.elStyle,
                renderProps: renderProps,
                generatorName: "dayCellContent",
                customGenerator: options.dayCellContent,
                defaultGenerator: props.defaultGenerator,
                classNameGenerator:
                    // don't use custom classNames if disabled
                    renderProps.isDisabled ? undefined : options.dayCellClassNames,
                didMount: options.dayCellDidMount,
                willUnmount: options.dayCellWillUnmount
            }, props.children));
        }
    }

    function hasCustomDayCellContent(options) {
        return Boolean(options.dayCellContent || hasCustomRenderingHandler('dayCellContent', options));
    }

    function refineRenderProps(raw) {
        let {
            date,
            dateEnv,
            dateProfile,
            isMonthStart
        } = raw;
        let dayMeta = getDateMeta(date, raw.todayRange, null, dateProfile);
        let dayNumberText = raw.showDayNumber ? (dateEnv.format(date, isMonthStart ? raw.monthStartFormat : DAY_NUM_FORMAT)) : '';
        return Object.assign(Object.assign(Object.assign({
            date: dateEnv.toDate(date),
            view: raw.viewApi
        }, dayMeta), {
            isMonthStart,
            dayNumberText
        }), raw.extraRenderProps);
    }

    class BgEvent extends BaseComponent {
        render() {
            let {
                props
            } = this;
            let {
                seg
            } = props;
            return (y(EventContainer, {
                elTag: "div",
                elClasses: ['fc-bg-event'],
                elStyle: {
                    backgroundColor: seg.eventRange.ui.backgroundColor
                },
                defaultGenerator: renderInnerContent$3,
                seg: seg,
                timeText: "",
                isDragging: false,
                isResizing: false,
                isDateSelecting: false,
                isSelected: false,
                isPast: props.isPast,
                isFuture: props.isFuture,
                isToday: props.isToday,
                disableDragging: true,
                disableResizing: true
            }));
        }
    }

    function renderInnerContent$3(props) {
        let {
            title
        } = props.event;
        return title && (y("div", {
            className: "fc-event-title"
        }, props.event.title));
    }

    function renderFill(fillType) {
        return (y("div", {
            className: `fc-${fillType}`
        }));
    }

    const WeekNumberContainer = (props) => (y(ViewContextType.Consumer, null, (context) => {
        let {
            dateEnv,
            options
        } = context;
        let {
            date
        } = props;
        let format = options.weekNumberFormat || props.defaultFormat;
        let num = dateEnv.computeWeekNumber(date); // TODO: somehow use for formatting as well?
        let text = dateEnv.format(date, format);
        let renderProps = {
            num,
            text,
            date
        };
        return (y(ContentContainer // why isn't WeekNumberContentArg being auto-detected?
            , {
                elRef: props.elRef,
                elTag: props.elTag,
                elAttrs: props.elAttrs,
                elClasses: props.elClasses,
                elStyle: props.elStyle,
                renderProps: renderProps,
                generatorName: "weekNumberContent",
                customGenerator: options.weekNumberContent,
                defaultGenerator: renderInner,
                classNameGenerator: options.weekNumberClassNames,
                didMount: options.weekNumberDidMount,
                willUnmount: options.weekNumberWillUnmount
            }, props.children));
    }));

    function renderInner(innerProps) {
        return innerProps.text;
    }

    const PADDING_FROM_VIEWPORT = 10;
    class Popover extends BaseComponent {
        constructor() {
            super(...arguments);
            this.state = {
                titleId: getUniqueDomId(),
            };
            this.handleRootEl = (el) => {
                this.rootEl = el;
                if (this.props.elRef) {
                    setRef(this.props.elRef, el);
                }
            };
            // Triggered when the user clicks *anywhere* in the document, for the autoHide feature
            this.handleDocumentMouseDown = (ev) => {
                // only hide the popover if the click happened outside the popover
                const target = getEventTargetViaRoot(ev);
                if (!this.rootEl.contains(target)) {
                    this.handleCloseClick();
                }
            };
            this.handleDocumentKeyDown = (ev) => {
                if (ev.key === 'Escape') {
                    this.handleCloseClick();
                }
            };
            this.handleCloseClick = () => {
                let {
                    onClose
                } = this.props;
                if (onClose) {
                    onClose();
                }
            };
        }
        render() {
            let {
                theme,
                options
            } = this.context;
            let {
                props,
                state
            } = this;
            let classNames = [
                'fc-popover',
                theme.getClass('popover'),
            ].concat(props.extraClassNames || []);
            return j(y("div", Object.assign({}, props.extraAttrs, {
                    id: props.id,
                    className: classNames.join(' '),
                    "aria-labelledby": state.titleId,
                    ref: this.handleRootEl
                }),
                y("div", {
                        className: 'fc-popover-header ' + theme.getClass('popoverHeader')
                    },
                    y("span", {
                        className: "fc-popover-title",
                        id: state.titleId
                    }, props.title),
                    y("span", {
                        className: 'fc-popover-close ' + theme.getIconClass('close'),
                        title: options.closeHint,
                        onClick: this.handleCloseClick
                    })),
                y("div", {
                    className: 'fc-popover-body ' + theme.getClass('popoverContent')
                }, props.children)), props.parentEl);
        }
        componentDidMount() {
            document.addEventListener('mousedown', this.handleDocumentMouseDown);
            document.addEventListener('keydown', this.handleDocumentKeyDown);
            this.updateSize();
        }
        componentWillUnmount() {
            document.removeEventListener('mousedown', this.handleDocumentMouseDown);
            document.removeEventListener('keydown', this.handleDocumentKeyDown);
        }
        updateSize() {
            let {
                isRtl
            } = this.context;
            let {
                alignmentEl,
                alignGridTop
            } = this.props;
            let {
                rootEl
            } = this;
            let alignmentRect = computeClippedClientRect(alignmentEl);
            if (alignmentRect) {
                let popoverDims = rootEl.getBoundingClientRect();
                // position relative to viewport
                let popoverTop = alignGridTop ?
                    elementClosest(alignmentEl, '.fc-scrollgrid').getBoundingClientRect().top :
                    alignmentRect.top;
                let popoverLeft = isRtl ? alignmentRect.right - popoverDims.width : alignmentRect.left;
                // constrain
                popoverTop = Math.max(popoverTop, PADDING_FROM_VIEWPORT);
                popoverLeft = Math.min(popoverLeft, document.documentElement.clientWidth - PADDING_FROM_VIEWPORT - popoverDims.width);
                popoverLeft = Math.max(popoverLeft, PADDING_FROM_VIEWPORT);
                let origin = rootEl.offsetParent.getBoundingClientRect();
                applyStyle(rootEl, {
                    top: popoverTop - origin.top,
                    left: popoverLeft - origin.left,
                });
            }
        }
    }

    class MorePopover extends DateComponent {
        constructor() {
            super(...arguments);
            this.handleRootEl = (rootEl) => {
                this.rootEl = rootEl;
                if (rootEl) {
                    this.context.registerInteractiveComponent(this, {
                        el: rootEl,
                        useEventCenter: false,
                    });
                } else {
                    this.context.unregisterInteractiveComponent(this);
                }
            };
        }
        render() {
            let {
                options,
                dateEnv
            } = this.context;
            let {
                props
            } = this;
            let {
                startDate,
                todayRange,
                dateProfile
            } = props;
            let title = dateEnv.format(startDate, options.dayPopoverFormat);
            return (y(DayCellContainer, {
                elRef: this.handleRootEl,
                date: startDate,
                dateProfile: dateProfile,
                todayRange: todayRange
            }, (InnerContent, renderProps, elAttrs) => (y(Popover, {
                    elRef: elAttrs.ref,
                    id: props.id,
                    title: title,
                    extraClassNames: ['fc-more-popover'].concat(elAttrs.className || []),
                    extraAttrs: elAttrs /* TODO: make these time-based when not whole-day? */ ,
                    parentEl: props.parentEl,
                    alignmentEl: props.alignmentEl,
                    alignGridTop: props.alignGridTop,
                    onClose: props.onClose
                },
                hasCustomDayCellContent(options) && (y(InnerContent, {
                    elTag: "div",
                    elClasses: ['fc-more-popover-misc']
                })),
                props.children))));
        }
        queryHit(positionLeft, positionTop, elWidth, elHeight) {
            let {
                rootEl,
                props
            } = this;
            if (positionLeft >= 0 && positionLeft < elWidth &&
                positionTop >= 0 && positionTop < elHeight) {
                return {
                    dateProfile: props.dateProfile,
                    dateSpan: Object.assign({
                        allDay: !props.forceTimed,
                        range: {
                            start: props.startDate,
                            end: props.endDate,
                        }
                    }, props.extraDateSpan),
                    dayEl: rootEl,
                    rect: {
                        left: 0,
                        top: 0,
                        right: elWidth,
                        bottom: elHeight,
                    },
                    layer: 1, // important when comparing with hits from other components
                };
            }
            return null;
        }
    }

    class MoreLinkContainer extends BaseComponent {
        constructor() {
            super(...arguments);
            this.state = {
                isPopoverOpen: false,
                popoverId: getUniqueDomId(),
            };
            this.handleLinkEl = (linkEl) => {
                this.linkEl = linkEl;
                if (this.props.elRef) {
                    setRef(this.props.elRef, linkEl);
                }
            };
            this.handleClick = (ev) => {
                let {
                    props,
                    context
                } = this;
                let {
                    moreLinkClick
                } = context.options;
                let date = computeRange(props).start;

                function buildPublicSeg(seg) {
                    let {
                        def,
                        instance,
                        range
                    } = seg.eventRange;
                    return {
                        event: new EventImpl(context, def, instance),
                        start: context.dateEnv.toDate(range.start),
                        end: context.dateEnv.toDate(range.end),
                        isStart: seg.isStart,
                        isEnd: seg.isEnd,
                    };
                }
                if (typeof moreLinkClick === 'function') {
                    moreLinkClick = moreLinkClick({
                        date,
                        allDay: Boolean(props.allDayDate),
                        allSegs: props.allSegs.map(buildPublicSeg),
                        hiddenSegs: props.hiddenSegs.map(buildPublicSeg),
                        jsEvent: ev,
                        view: context.viewApi,
                    });
                }
                if (!moreLinkClick || moreLinkClick === 'popover') {
                    this.setState({
                        isPopoverOpen: true
                    });
                } else if (typeof moreLinkClick === 'string') { // a view name
                    context.calendarApi.zoomTo(date, moreLinkClick);
                }
            };
            this.handlePopoverClose = () => {
                this.setState({
                    isPopoverOpen: false
                });
            };
        }
        render() {
            let {
                props,
                state
            } = this;
            return (y(ViewContextType.Consumer, null, (context) => {
                let {
                    viewApi,
                    options,
                    calendarApi
                } = context;
                let {
                    moreLinkText
                } = options;
                let {
                    moreCnt
                } = props;
                let range = computeRange(props);
                let text = typeof moreLinkText === 'function' // TODO: eventually use formatWithOrdinals
                    ?
                    moreLinkText.call(calendarApi, moreCnt) :
                    `+${moreCnt} ${moreLinkText}`;
                let hint = formatWithOrdinals(options.moreLinkHint, [moreCnt], text);
                let renderProps = {
                    num: moreCnt,
                    shortText: `+${moreCnt}`,
                    text,
                    view: viewApi,
                };
                return (y(_, null,
                    Boolean(props.moreCnt) && (y(ContentContainer, {
                        elTag: props.elTag || 'a',
                        elRef: this.handleLinkEl,
                        elClasses: [
                            ...(props.elClasses || []),
                            'fc-more-link',
                        ],
                        elStyle: props.elStyle,
                        elAttrs: Object.assign(Object.assign(Object.assign({}, props.elAttrs), createAriaClickAttrs(this.handleClick)), {
                            title: hint,
                            'aria-expanded': state.isPopoverOpen,
                            'aria-controls': state.isPopoverOpen ? state.popoverId : ''
                        }),
                        renderProps: renderProps,
                        generatorName: "moreLinkContent",
                        customGenerator: options.moreLinkContent,
                        defaultGenerator: props.defaultGenerator || renderMoreLinkInner$1,
                        classNameGenerator: options.moreLinkClassNames,
                        didMount: options.moreLinkDidMount,
                        willUnmount: options.moreLinkWillUnmount
                    }, props.children)),
                    state.isPopoverOpen && (y(MorePopover, {
                        id: state.popoverId,
                        startDate: range.start,
                        endDate: range.end,
                        dateProfile: props.dateProfile,
                        todayRange: props.todayRange,
                        extraDateSpan: props.extraDateSpan,
                        parentEl: this.parentEl,
                        alignmentEl: props.alignmentElRef ?
                            props.alignmentElRef.current : this.linkEl,
                        alignGridTop: props.alignGridTop,
                        forceTimed: props.forceTimed,
                        onClose: this.handlePopoverClose
                    }, props.popoverContent()))));
            }));
        }
        componentDidMount() {
            this.updateParentEl();
        }
        componentDidUpdate() {
            this.updateParentEl();
        }
        updateParentEl() {
            if (this.linkEl) {
                this.parentEl = elementClosest(this.linkEl, '.fc-view-harness');
            }
        }
    }

    function renderMoreLinkInner$1(props) {
        return props.text;
    }

    function computeRange(props) {
        if (props.allDayDate) {
            return {
                start: props.allDayDate,
                end: addDays(props.allDayDate, 1),
            };
        }
        let {
            hiddenSegs
        } = props;
        return {
            start: computeEarliestSegStart(hiddenSegs),
            end: computeLatestSegEnd(hiddenSegs),
        };
    }

    function computeEarliestSegStart(segs) {
        return segs.reduce(pickEarliestStart).eventRange.range.start;
    }

    function pickEarliestStart(seg0, seg1) {
        return seg0.eventRange.range.start < seg1.eventRange.range.start ? seg0 : seg1;
    }

    function computeLatestSegEnd(segs) {
        return segs.reduce(pickLatestEnd).eventRange.range.end;
    }

    function pickLatestEnd(seg0, seg1) {
        return seg0.eventRange.range.end > seg1.eventRange.range.end ? seg0 : seg1;
    }

    class Store {
        constructor() {
            this.handlers = [];
        }
        set(value) {
            this.currentValue = value;
            for (let handler of this.handlers) {
                handler(value);
            }
        }
        subscribe(handler) {
            this.handlers.push(handler);
            if (this.currentValue !== undefined) {
                handler(this.currentValue);
            }
        }
    }

    /*
    Subscribers will get a LIST of CustomRenderings
    */
    class CustomRenderingStore extends Store {
        constructor() {
            super(...arguments);
            this.map = new Map();
        }
        // for consistent order
        handle(customRendering) {
            const {
                map
            } = this;
            let updated = false;
            if (customRendering.isActive) {
                map.set(customRendering.id, customRendering);
                updated = true;
            } else if (map.has(customRendering.id)) {
                map.delete(customRendering.id);
                updated = true;
            }
            if (updated) {
                this.set(map);
            }
        }
    }

    var internal = {
        __proto__: null,
        BASE_OPTION_DEFAULTS: BASE_OPTION_DEFAULTS,
        BaseComponent: BaseComponent,
        BgEvent: BgEvent,
        CalendarImpl: CalendarImpl,
        CalendarRoot: CalendarRoot,
        ContentContainer: ContentContainer,
        CustomRenderingStore: CustomRenderingStore,
        DateComponent: DateComponent,
        DateEnv: DateEnv,
        DateProfileGenerator: DateProfileGenerator,
        DayCellContainer: DayCellContainer,
        DayHeader: DayHeader,
        DaySeriesModel: DaySeriesModel,
        DayTableModel: DayTableModel,
        DelayedRunner: DelayedRunner,
        ElementDragging: ElementDragging,
        ElementScrollController: ElementScrollController,
        Emitter: Emitter,
        EventContainer: EventContainer,
        EventImpl: EventImpl,
        Interaction: Interaction,
        MoreLinkContainer: MoreLinkContainer,
        NamedTimeZoneImpl: NamedTimeZoneImpl,
        NowIndicatorContainer: NowIndicatorContainer,
        NowTimer: NowTimer,
        PositionCache: PositionCache,
        RefMap: RefMap,
        ScrollController: ScrollController,
        ScrollResponder: ScrollResponder,
        Scroller: Scroller,
        SegHierarchy: SegHierarchy,
        SimpleScrollGrid: SimpleScrollGrid,
        Slicer: Slicer,
        Splitter: Splitter,
        StandardEvent: StandardEvent,
        TableDateCell: TableDateCell,
        TableDowCell: TableDowCell,
        Theme: Theme,
        ViewContainer: ViewContainer,
        ViewContextType: ViewContextType,
        WeekNumberContainer: WeekNumberContainer,
        WindowScrollController: WindowScrollController,
        addDays: addDays,
        addDurations: addDurations,
        addMs: addMs,
        addWeeks: addWeeks,
        allowContextMenu: allowContextMenu,
        allowSelection: allowSelection,
        applyMutationToEventStore: applyMutationToEventStore,
        applyStyle: applyStyle,
        asCleanDays: asCleanDays,
        asRoughMinutes: asRoughMinutes,
        asRoughMs: asRoughMs,
        asRoughSeconds: asRoughSeconds,
        binarySearch: binarySearch,
        buildElAttrs: buildElAttrs,
        buildEntryKey: buildEntryKey,
        buildEventApis: buildEventApis,
        buildEventRangeKey: buildEventRangeKey,
        buildIsoString: buildIsoString,
        buildNavLinkAttrs: buildNavLinkAttrs,
        buildSegTimeText: buildSegTimeText,
        collectFromHash: collectFromHash,
        combineEventUis: combineEventUis,
        compareByFieldSpecs: compareByFieldSpecs,
        compareNumbers: compareNumbers,
        compareObjs: compareObjs,
        computeEarliestSegStart: computeEarliestSegStart,
        computeEdges: computeEdges,
        computeFallbackHeaderFormat: computeFallbackHeaderFormat,
        computeInnerRect: computeInnerRect,
        computeRect: computeRect,
        computeShrinkWidth: computeShrinkWidth,
        computeVisibleDayRange: computeVisibleDayRange,
        config: config,
        constrainPoint: constrainPoint,
        createDuration: createDuration,
        createEmptyEventStore: createEmptyEventStore,
        createEventInstance: createEventInstance,
        createEventUi: createEventUi,
        createFormatter: createFormatter,
        diffDates: diffDates,
        diffDayAndTime: diffDayAndTime,
        diffDays: diffDays,
        diffPoints: diffPoints,
        diffWeeks: diffWeeks,
        diffWholeDays: diffWholeDays,
        diffWholeWeeks: diffWholeWeeks,
        disableCursor: disableCursor,
        elementClosest: elementClosest,
        elementMatches: elementMatches,
        enableCursor: enableCursor,
        eventTupleToStore: eventTupleToStore,
        filterHash: filterHash,
        findDirectChildren: findDirectChildren,
        findElements: findElements,
        flexibleCompare: flexibleCompare,
        formatDayString: formatDayString,
        formatIsoMonthStr: formatIsoMonthStr,
        formatIsoTimeString: formatIsoTimeString,
        getAllowYScrolling: getAllowYScrolling,
        getCanVGrowWithinCell: getCanVGrowWithinCell,
        getClippingParents: getClippingParents,
        getDateMeta: getDateMeta,
        getDayClassNames: getDayClassNames,
        getDefaultEventEnd: getDefaultEventEnd,
        getElSeg: getElSeg,
        getEntrySpanEnd: getEntrySpanEnd,
        getEventTargetViaRoot: getEventTargetViaRoot,
        getIsRtlScrollbarOnLeft: getIsRtlScrollbarOnLeft,
        getRectCenter: getRectCenter,
        getRelevantEvents: getRelevantEvents,
        getScrollGridClassNames: getScrollGridClassNames,
        getScrollbarWidths: getScrollbarWidths,
        getSectionClassNames: getSectionClassNames,
        getSectionHasLiquidHeight: getSectionHasLiquidHeight,
        getSegAnchorAttrs: getSegAnchorAttrs,
        getSegMeta: getSegMeta,
        getSlotClassNames: getSlotClassNames,
        getStickyFooterScrollbar: getStickyFooterScrollbar,
        getStickyHeaderDates: getStickyHeaderDates,
        getUniqueDomId: getUniqueDomId,
        greatestDurationDenominator: greatestDurationDenominator,
        groupIntersectingEntries: groupIntersectingEntries,
        guid: guid,
        hasBgRendering: hasBgRendering,
        hasCustomDayCellContent: hasCustomDayCellContent,
        hasShrinkWidth: hasShrinkWidth,
        identity: identity,
        injectStyles: injectStyles,
        interactionSettingsStore: interactionSettingsStore,
        interactionSettingsToStore: interactionSettingsToStore,
        intersectRanges: intersectRanges,
        intersectRects: intersectRects,
        intersectSpans: intersectSpans,
        isArraysEqual: isArraysEqual,
        isColPropsEqual: isColPropsEqual,
        isDateSelectionValid: isDateSelectionValid,
        isDateSpansEqual: isDateSpansEqual,
        isInt: isInt,
        isInteractionValid: isInteractionValid,
        isMultiDayRange: isMultiDayRange,
        isPropsEqual: isPropsEqual,
        isPropsValid: isPropsValid,
        isValidDate: isValidDate,
        mapHash: mapHash,
        memoize: memoize,
        memoizeArraylike: memoizeArraylike,
        memoizeHashlike: memoizeHashlike,
        memoizeObjArg: memoizeObjArg,
        mergeEventStores: mergeEventStores,
        multiplyDuration: multiplyDuration,
        padStart: padStart,
        parseBusinessHours: parseBusinessHours,
        parseClassNames: parseClassNames,
        parseDragMeta: parseDragMeta,
        parseEventDef: parseEventDef,
        parseFieldSpecs: parseFieldSpecs,
        parseMarker: parse,
        pointInsideRect: pointInsideRect,
        preventContextMenu: preventContextMenu,
        preventDefault: preventDefault,
        preventSelection: preventSelection,
        rangeContainsMarker: rangeContainsMarker,
        rangeContainsRange: rangeContainsRange,
        rangesEqual: rangesEqual,
        rangesIntersect: rangesIntersect,
        refineEventDef: refineEventDef,
        refineProps: refineProps,
        removeElement: removeElement,
        removeExact: removeExact,
        renderChunkContent: renderChunkContent,
        renderFill: renderFill,
        renderMicroColGroup: renderMicroColGroup,
        renderScrollShim: renderScrollShim,
        requestJson: requestJson,
        sanitizeShrinkWidth: sanitizeShrinkWidth,
        setRef: setRef,
        sliceEventStore: sliceEventStore,
        sortEventSegs: sortEventSegs,
        startOfDay: startOfDay,
        translateRect: translateRect,
        triggerDateSelect: triggerDateSelect,
        unpromisify: unpromisify,
        whenTransitionDone: whenTransitionDone,
        wholeDivideDurations: wholeDivideDurations
    };

    var preact = {
        __proto__: null,
        createPortal: j,
        createContext: createContext,
        flushSync: flushSync,
        Component: x$1,
        Fragment: _,
        cloneElement: F$1,
        createElement: y,
        createRef: d,
        h: y,
        hydrate: E,
        get isValidElement() {
            return i$1;
        },
        get options() {
            return l$1;
        },
        render: D$1,
        toChildArray: j$2
    };

    const globalLocales = [];

    const MINIMAL_RAW_EN_LOCALE = {
        code: 'en',
        week: {
            dow: 0,
            doy: 4, // 4 days need to be within the year to be considered the first week
        },
        direction: 'ltr',
        buttonText: {
            prev: 'prev',
            next: 'next',
            prevYear: 'prev year',
            nextYear: 'next year',
            year: 'year',
            today: 'today',
            month: 'month',
            week: 'week',
            day: 'day',
            list: 'list',
        },
        weekText: 'W',
        weekTextLong: 'Week',
        closeHint: 'Close',
        timeHint: 'Time',
        eventHint: 'Event',
        allDayText: 'all-day',
        moreLinkText: 'more',
        noEventsText: 'No events to display',
    };
    const RAW_EN_LOCALE = Object.assign(Object.assign({}, MINIMAL_RAW_EN_LOCALE), {
        // Includes things we don't want other locales to inherit,
        // things that derive from other translatable strings.
        buttonHints: {
            prev: 'Previous $0',
            next: 'Next $0',
            today(buttonText, unit) {
                return (unit === 'day') ?
                    'Today' :
                    `This ${buttonText}`;
            },
        },
        viewHint: '$0 view',
        navLinkHint: 'Go to $0',
        moreLinkHint(eventCnt) {
            return `Show ${eventCnt} more event${eventCnt === 1 ? '' : 's'}`;
        }
    });

    function organizeRawLocales(explicitRawLocales) {
        let defaultCode = explicitRawLocales.length > 0 ? explicitRawLocales[0].code : 'en';
        let allRawLocales = globalLocales.concat(explicitRawLocales);
        let rawLocaleMap = {
            en: RAW_EN_LOCALE,
        };
        for (let rawLocale of allRawLocales) {
            rawLocaleMap[rawLocale.code] = rawLocale;
        }
        return {
            map: rawLocaleMap,
            defaultCode,
        };
    }

    function buildLocale(inputSingular, available) {
        if (typeof inputSingular === 'object' && !Array.isArray(inputSingular)) {
            return parseLocale(inputSingular.code, [inputSingular.code], inputSingular);
        }
        return queryLocale(inputSingular, available);
    }

    function queryLocale(codeArg, available) {
        let codes = [].concat(codeArg || []); // will convert to array
        let raw = queryRawLocale(codes, available) || RAW_EN_LOCALE;
        return parseLocale(codeArg, codes, raw);
    }

    function queryRawLocale(codes, available) {
        for (let i = 0; i < codes.length; i += 1) {
            let parts = codes[i].toLocaleLowerCase().split('-');
            for (let j = parts.length; j > 0; j -= 1) {
                let simpleId = parts.slice(0, j).join('-');
                if (available[simpleId]) {
                    return available[simpleId];
                }
            }
        }
        return null;
    }

    function parseLocale(codeArg, codes, raw) {
        let merged = mergeProps([MINIMAL_RAW_EN_LOCALE, raw], ['buttonText']);
        delete merged.code; // don't want this part of the options
        let {
            week
        } = merged;
        delete merged.week;
        return {
            codeArg,
            codes,
            week,
            simpleNumberFormat: new Intl.NumberFormat(codeArg),
            options: merged,
        };
    }

    // TODO: easier way to add new hooks? need to update a million things
    function createPlugin(input) {
        return {
            id: guid(),
            name: input.name,
            premiumReleaseDate: input.premiumReleaseDate ? new Date(input.premiumReleaseDate) : undefined,
            deps: input.deps || [],
            reducers: input.reducers || [],
            isLoadingFuncs: input.isLoadingFuncs || [],
            contextInit: [].concat(input.contextInit || []),
            eventRefiners: input.eventRefiners || {},
            eventDefMemberAdders: input.eventDefMemberAdders || [],
            eventSourceRefiners: input.eventSourceRefiners || {},
            isDraggableTransformers: input.isDraggableTransformers || [],
            eventDragMutationMassagers: input.eventDragMutationMassagers || [],
            eventDefMutationAppliers: input.eventDefMutationAppliers || [],
            dateSelectionTransformers: input.dateSelectionTransformers || [],
            datePointTransforms: input.datePointTransforms || [],
            dateSpanTransforms: input.dateSpanTransforms || [],
            views: input.views || {},
            viewPropsTransformers: input.viewPropsTransformers || [],
            isPropsValid: input.isPropsValid || null,
            externalDefTransforms: input.externalDefTransforms || [],
            viewContainerAppends: input.viewContainerAppends || [],
            eventDropTransformers: input.eventDropTransformers || [],
            componentInteractions: input.componentInteractions || [],
            calendarInteractions: input.calendarInteractions || [],
            themeClasses: input.themeClasses || {},
            eventSourceDefs: input.eventSourceDefs || [],
            cmdFormatter: input.cmdFormatter,
            recurringTypes: input.recurringTypes || [],
            namedTimeZonedImpl: input.namedTimeZonedImpl,
            initialView: input.initialView || '',
            elementDraggingImpl: input.elementDraggingImpl,
            optionChangeHandlers: input.optionChangeHandlers || {},
            scrollGridImpl: input.scrollGridImpl || null,
            listenerRefiners: input.listenerRefiners || {},
            optionRefiners: input.optionRefiners || {},
            propSetHandlers: input.propSetHandlers || {},
        };
    }

    function buildPluginHooks(pluginDefs, globalDefs) {
        let currentPluginIds = {};
        let hooks = {
            premiumReleaseDate: undefined,
            reducers: [],
            isLoadingFuncs: [],
            contextInit: [],
            eventRefiners: {},
            eventDefMemberAdders: [],
            eventSourceRefiners: {},
            isDraggableTransformers: [],
            eventDragMutationMassagers: [],
            eventDefMutationAppliers: [],
            dateSelectionTransformers: [],
            datePointTransforms: [],
            dateSpanTransforms: [],
            views: {},
            viewPropsTransformers: [],
            isPropsValid: null,
            externalDefTransforms: [],
            viewContainerAppends: [],
            eventDropTransformers: [],
            componentInteractions: [],
            calendarInteractions: [],
            themeClasses: {},
            eventSourceDefs: [],
            cmdFormatter: null,
            recurringTypes: [],
            namedTimeZonedImpl: null,
            initialView: '',
            elementDraggingImpl: null,
            optionChangeHandlers: {},
            scrollGridImpl: null,
            listenerRefiners: {},
            optionRefiners: {},
            propSetHandlers: {},
        };

        function addDefs(defs) {
            for (let def of defs) {
                const pluginName = def.name;
                const currentId = currentPluginIds[pluginName];
                if (currentId === undefined) {
                    currentPluginIds[pluginName] = def.id;
                    addDefs(def.deps);
                    hooks = combineHooks(hooks, def);
                } else if (currentId !== def.id) {
                    // different ID than the one already added
                    console.warn(`Duplicate plugin '${pluginName}'`);
                }
            }
        }
        if (pluginDefs) {
            addDefs(pluginDefs);
        }
        addDefs(globalDefs);
        return hooks;
    }

    function buildBuildPluginHooks() {
        let currentOverrideDefs = [];
        let currentGlobalDefs = [];
        let currentHooks;
        return (overrideDefs, globalDefs) => {
            if (!currentHooks || !isArraysEqual(overrideDefs, currentOverrideDefs) || !isArraysEqual(globalDefs, currentGlobalDefs)) {
                currentHooks = buildPluginHooks(overrideDefs, globalDefs);
            }
            currentOverrideDefs = overrideDefs;
            currentGlobalDefs = globalDefs;
            return currentHooks;
        };
    }

    function combineHooks(hooks0, hooks1) {
        return {
            premiumReleaseDate: compareOptionalDates(hooks0.premiumReleaseDate, hooks1.premiumReleaseDate),
            reducers: hooks0.reducers.concat(hooks1.reducers),
            isLoadingFuncs: hooks0.isLoadingFuncs.concat(hooks1.isLoadingFuncs),
            contextInit: hooks0.contextInit.concat(hooks1.contextInit),
            eventRefiners: Object.assign(Object.assign({}, hooks0.eventRefiners), hooks1.eventRefiners),
            eventDefMemberAdders: hooks0.eventDefMemberAdders.concat(hooks1.eventDefMemberAdders),
            eventSourceRefiners: Object.assign(Object.assign({}, hooks0.eventSourceRefiners), hooks1.eventSourceRefiners),
            isDraggableTransformers: hooks0.isDraggableTransformers.concat(hooks1.isDraggableTransformers),
            eventDragMutationMassagers: hooks0.eventDragMutationMassagers.concat(hooks1.eventDragMutationMassagers),
            eventDefMutationAppliers: hooks0.eventDefMutationAppliers.concat(hooks1.eventDefMutationAppliers),
            dateSelectionTransformers: hooks0.dateSelectionTransformers.concat(hooks1.dateSelectionTransformers),
            datePointTransforms: hooks0.datePointTransforms.concat(hooks1.datePointTransforms),
            dateSpanTransforms: hooks0.dateSpanTransforms.concat(hooks1.dateSpanTransforms),
            views: Object.assign(Object.assign({}, hooks0.views), hooks1.views),
            viewPropsTransformers: hooks0.viewPropsTransformers.concat(hooks1.viewPropsTransformers),
            isPropsValid: hooks1.isPropsValid || hooks0.isPropsValid,
            externalDefTransforms: hooks0.externalDefTransforms.concat(hooks1.externalDefTransforms),
            viewContainerAppends: hooks0.viewContainerAppends.concat(hooks1.viewContainerAppends),
            eventDropTransformers: hooks0.eventDropTransformers.concat(hooks1.eventDropTransformers),
            calendarInteractions: hooks0.calendarInteractions.concat(hooks1.calendarInteractions),
            componentInteractions: hooks0.componentInteractions.concat(hooks1.componentInteractions),
            themeClasses: Object.assign(Object.assign({}, hooks0.themeClasses), hooks1.themeClasses),
            eventSourceDefs: hooks0.eventSourceDefs.concat(hooks1.eventSourceDefs),
            cmdFormatter: hooks1.cmdFormatter || hooks0.cmdFormatter,
            recurringTypes: hooks0.recurringTypes.concat(hooks1.recurringTypes),
            namedTimeZonedImpl: hooks1.namedTimeZonedImpl || hooks0.namedTimeZonedImpl,
            initialView: hooks0.initialView || hooks1.initialView,
            elementDraggingImpl: hooks0.elementDraggingImpl || hooks1.elementDraggingImpl,
            optionChangeHandlers: Object.assign(Object.assign({}, hooks0.optionChangeHandlers), hooks1.optionChangeHandlers),
            scrollGridImpl: hooks1.scrollGridImpl || hooks0.scrollGridImpl,
            listenerRefiners: Object.assign(Object.assign({}, hooks0.listenerRefiners), hooks1.listenerRefiners),
            optionRefiners: Object.assign(Object.assign({}, hooks0.optionRefiners), hooks1.optionRefiners),
            propSetHandlers: Object.assign(Object.assign({}, hooks0.propSetHandlers), hooks1.propSetHandlers),
        };
    }

    function compareOptionalDates(date0, date1) {
        if (date0 === undefined) {
            return date1;
        }
        if (date1 === undefined) {
            return date0;
        }
        return new Date(Math.max(date0.valueOf(), date1.valueOf()));
    }

    class StandardTheme extends Theme {}
    StandardTheme.prototype.classes = {
        root: 'fc-theme-standard',
        tableCellShaded: 'fc-cell-shaded',
        buttonGroup: 'fc-button-group',
        button: 'fc-button fc-button-primary',
        buttonActive: 'fc-button-active',
    };
    StandardTheme.prototype.baseIconClass = 'fc-icon';
    StandardTheme.prototype.iconClasses = {
        close: 'fc-icon-x',
        prev: 'fc-icon-chevron-left',
        next: 'fc-icon-chevron-right',
        prevYear: 'fc-icon-chevrons-left',
        nextYear: 'fc-icon-chevrons-right',
    };
    StandardTheme.prototype.rtlIconClasses = {
        prev: 'fc-icon-chevron-right',
        next: 'fc-icon-chevron-left',
        prevYear: 'fc-icon-chevrons-right',
        nextYear: 'fc-icon-chevrons-left',
    };
    StandardTheme.prototype.iconOverrideOption = 'buttonIcons'; // TODO: make TS-friendly
    StandardTheme.prototype.iconOverrideCustomButtonOption = 'icon';
    StandardTheme.prototype.iconOverridePrefix = 'fc-icon-';

    function compileViewDefs(defaultConfigs, overrideConfigs) {
        let hash = {};
        let viewType;
        for (viewType in defaultConfigs) {
            ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
        }
        for (viewType in overrideConfigs) {
            ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs);
        }
        return hash;
    }

    function ensureViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
        if (hash[viewType]) {
            return hash[viewType];
        }
        let viewDef = buildViewDef(viewType, hash, defaultConfigs, overrideConfigs);
        if (viewDef) {
            hash[viewType] = viewDef;
        }
        return viewDef;
    }

    function buildViewDef(viewType, hash, defaultConfigs, overrideConfigs) {
        let defaultConfig = defaultConfigs[viewType];
        let overrideConfig = overrideConfigs[viewType];
        let queryProp = (name) => ((defaultConfig && defaultConfig[name] !== null) ? defaultConfig[name] :
            ((overrideConfig && overrideConfig[name] !== null) ? overrideConfig[name] : null));
        let theComponent = queryProp('component');
        let superType = queryProp('superType');
        let superDef = null;
        if (superType) {
            if (superType === viewType) {
                throw new Error('Can\'t have a custom view type that references itself');
            }
            superDef = ensureViewDef(superType, hash, defaultConfigs, overrideConfigs);
        }
        if (!theComponent && superDef) {
            theComponent = superDef.component;
        }
        if (!theComponent) {
            return null; // don't throw a warning, might be settings for a single-unit view
        }
        return {
            type: viewType,
            component: theComponent,
            defaults: Object.assign(Object.assign({}, (superDef ? superDef.defaults : {})), (defaultConfig ? defaultConfig.rawOptions : {})),
            overrides: Object.assign(Object.assign({}, (superDef ? superDef.overrides : {})), (overrideConfig ? overrideConfig.rawOptions : {})),
        };
    }

    function parseViewConfigs(inputs) {
        return mapHash(inputs, parseViewConfig);
    }

    function parseViewConfig(input) {
        let rawOptions = typeof input === 'function' ? {
                component: input
            } :
            input;
        let {
            component
        } = rawOptions;
        if (rawOptions.content) {
            // TODO: remove content/classNames/didMount/etc from options?
            component = createViewHookComponent(rawOptions);
        } else if (component && !(component.prototype instanceof BaseComponent)) {
            // WHY?: people were using `component` property for `content`
            // TODO: converge on one setting name
            component = createViewHookComponent(Object.assign(Object.assign({}, rawOptions), {
                content: component
            }));
        }
        return {
            superType: rawOptions.type,
            component: component,
            rawOptions, // includes type and component too :(
        };
    }

    function createViewHookComponent(options) {
        return (viewProps) => (y(ViewContextType.Consumer, null, (context) => (y(ContentContainer, {
            elTag: "div",
            elClasses: buildViewClassNames(context.viewSpec),
            renderProps: Object.assign(Object.assign({}, viewProps), {
                nextDayThreshold: context.options.nextDayThreshold
            }),
            generatorName: undefined,
            customGenerator: options.content,
            classNameGenerator: options.classNames,
            didMount: options.didMount,
            willUnmount: options.willUnmount
        }))));
    }

    function buildViewSpecs(defaultInputs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
        let defaultConfigs = parseViewConfigs(defaultInputs);
        let overrideConfigs = parseViewConfigs(optionOverrides.views);
        let viewDefs = compileViewDefs(defaultConfigs, overrideConfigs);
        return mapHash(viewDefs, (viewDef) => buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults));
    }

    function buildViewSpec(viewDef, overrideConfigs, optionOverrides, dynamicOptionOverrides, localeDefaults) {
        let durationInput = viewDef.overrides.duration ||
            viewDef.defaults.duration ||
            dynamicOptionOverrides.duration ||
            optionOverrides.duration;
        let duration = null;
        let durationUnit = '';
        let singleUnit = '';
        let singleUnitOverrides = {};
        if (durationInput) {
            duration = createDurationCached(durationInput);
            if (duration) { // valid?
                let denom = greatestDurationDenominator(duration);
                durationUnit = denom.unit;
                if (denom.value === 1) {
                    singleUnit = durationUnit;
                    singleUnitOverrides = overrideConfigs[durationUnit] ? overrideConfigs[durationUnit].rawOptions : {};
                }
            }
        }
        let queryButtonText = (optionsSubset) => {
            let buttonTextMap = optionsSubset.buttonText || {};
            let buttonTextKey = viewDef.defaults.buttonTextKey;
            if (buttonTextKey != null && buttonTextMap[buttonTextKey] != null) {
                return buttonTextMap[buttonTextKey];
            }
            if (buttonTextMap[viewDef.type] != null) {
                return buttonTextMap[viewDef.type];
            }
            if (buttonTextMap[singleUnit] != null) {
                return buttonTextMap[singleUnit];
            }
            return null;
        };
        let queryButtonTitle = (optionsSubset) => {
            let buttonHints = optionsSubset.buttonHints || {};
            let buttonKey = viewDef.defaults.buttonTextKey; // use same key as text
            if (buttonKey != null && buttonHints[buttonKey] != null) {
                return buttonHints[buttonKey];
            }
            if (buttonHints[viewDef.type] != null) {
                return buttonHints[viewDef.type];
            }
            if (buttonHints[singleUnit] != null) {
                return buttonHints[singleUnit];
            }
            return null;
        };
        return {
            type: viewDef.type,
            component: viewDef.component,
            duration,
            durationUnit,
            singleUnit,
            optionDefaults: viewDef.defaults,
            optionOverrides: Object.assign(Object.assign({}, singleUnitOverrides), viewDef.overrides),
            buttonTextOverride: queryButtonText(dynamicOptionOverrides) ||
                queryButtonText(optionOverrides) || // constructor-specified buttonText lookup hash takes precedence
                viewDef.overrides.buttonText,
            buttonTextDefault: queryButtonText(localeDefaults) ||
                viewDef.defaults.buttonText ||
                queryButtonText(BASE_OPTION_DEFAULTS) ||
                viewDef.type,
            // not DRY
            buttonTitleOverride: queryButtonTitle(dynamicOptionOverrides) ||
                queryButtonTitle(optionOverrides) ||
                viewDef.overrides.buttonHint,
            buttonTitleDefault: queryButtonTitle(localeDefaults) ||
                viewDef.defaults.buttonHint ||
                queryButtonTitle(BASE_OPTION_DEFAULTS),
            // will eventually fall back to buttonText
        };
    }
    // hack to get memoization working
    let durationInputMap = {};

    function createDurationCached(durationInput) {
        let json = JSON.stringify(durationInput);
        let res = durationInputMap[json];
        if (res === undefined) {
            res = createDuration(durationInput);
            durationInputMap[json] = res;
        }
        return res;
    }

    function reduceViewType(viewType, action) {
        switch (action.type) {
            case 'CHANGE_VIEW_TYPE':
                viewType = action.viewType;
        }
        return viewType;
    }

    function reduceCurrentDate(currentDate, action) {
        switch (action.type) {
            case 'CHANGE_DATE':
                return action.dateMarker;
            default:
                return currentDate;
        }
    }
    // should be initialized once and stay constant
    // this will change too
    function getInitialDate(options, dateEnv, nowManager) {
        let initialDateInput = options.initialDate;
        // compute the initial ambig-timezone date
        if (initialDateInput != null) {
            return dateEnv.createMarker(initialDateInput);
        }
        return nowManager.getDateMarker();
    }

    function reduceDynamicOptionOverrides(dynamicOptionOverrides, action) {
        switch (action.type) {
            case 'SET_OPTION':
                return Object.assign(Object.assign({}, dynamicOptionOverrides), {
                    [action.optionName]: action.rawOptionValue
                });
            default:
                return dynamicOptionOverrides;
        }
    }

    function reduceDateProfile(currentDateProfile, action, currentDate, dateProfileGenerator) {
        let dp;
        switch (action.type) {
            case 'CHANGE_VIEW_TYPE':
                return dateProfileGenerator.build(action.dateMarker || currentDate);
            case 'CHANGE_DATE':
                return dateProfileGenerator.build(action.dateMarker);
            case 'PREV':
                dp = dateProfileGenerator.buildPrev(currentDateProfile, currentDate);
                if (dp.isValid) {
                    return dp;
                }
                break;
            case 'NEXT':
                dp = dateProfileGenerator.buildNext(currentDateProfile, currentDate);
                if (dp.isValid) {
                    return dp;
                }
                break;
        }
        return currentDateProfile;
    }

    function initEventSources(calendarOptions, dateProfile, context) {
        let activeRange = dateProfile ? dateProfile.activeRange : null;
        return addSources({}, parseInitialSources(calendarOptions, context), activeRange, context);
    }

    function reduceEventSources(eventSources, action, dateProfile, context) {
        let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
        switch (action.type) {
            case 'ADD_EVENT_SOURCES': // already parsed
                return addSources(eventSources, action.sources, activeRange, context);
            case 'REMOVE_EVENT_SOURCE':
                return removeSource(eventSources, action.sourceId);
            case 'PREV': // TODO: how do we track all actions that affect dateProfile :(
            case 'NEXT':
            case 'CHANGE_DATE':
            case 'CHANGE_VIEW_TYPE':
                if (dateProfile) {
                    return fetchDirtySources(eventSources, activeRange, context);
                }
                return eventSources;
            case 'FETCH_EVENT_SOURCES':
                return fetchSourcesByIds(eventSources, action.sourceIds ? // why no type?
                    arrayToHash(action.sourceIds) :
                    excludeStaticSources(eventSources, context), activeRange, action.isRefetch || false, context);
            case 'RECEIVE_EVENTS':
            case 'RECEIVE_EVENT_ERROR':
                return receiveResponse(eventSources, action.sourceId, action.fetchId, action.fetchRange);
            case 'REMOVE_ALL_EVENT_SOURCES':
                return {};
            default:
                return eventSources;
        }
    }

    function reduceEventSourcesNewTimeZone(eventSources, dateProfile, context) {
        let activeRange = dateProfile ? dateProfile.activeRange : null; // need this check?
        return fetchSourcesByIds(eventSources, excludeStaticSources(eventSources, context), activeRange, true, context);
    }

    function computeEventSourcesLoading(eventSources) {
        for (let sourceId in eventSources) {
            if (eventSources[sourceId].isFetching) {
                return true;
            }
        }
        return false;
    }

    function addSources(eventSourceHash, sources, fetchRange, context) {
        let hash = {};
        for (let source of sources) {
            hash[source.sourceId] = source;
        }
        if (fetchRange) {
            hash = fetchDirtySources(hash, fetchRange, context);
        }
        return Object.assign(Object.assign({}, eventSourceHash), hash);
    }

    function removeSource(eventSourceHash, sourceId) {
        return filterHash(eventSourceHash, (eventSource) => eventSource.sourceId !== sourceId);
    }

    function fetchDirtySources(sourceHash, fetchRange, context) {
        return fetchSourcesByIds(sourceHash, filterHash(sourceHash, (eventSource) => isSourceDirty(eventSource, fetchRange, context)), fetchRange, false, context);
    }

    function isSourceDirty(eventSource, fetchRange, context) {
        if (!doesSourceNeedRange(eventSource, context)) {
            return !eventSource.latestFetchId;
        }
        return !context.options.lazyFetching ||
            !eventSource.fetchRange ||
            eventSource.isFetching || // always cancel outdated in-progress fetches
            fetchRange.start < eventSource.fetchRange.start ||
            fetchRange.end > eventSource.fetchRange.end;
    }

    function fetchSourcesByIds(prevSources, sourceIdHash, fetchRange, isRefetch, context) {
        let nextSources = {};
        for (let sourceId in prevSources) {
            let source = prevSources[sourceId];
            if (sourceIdHash[sourceId]) {
                nextSources[sourceId] = fetchSource(source, fetchRange, isRefetch, context);
            } else {
                nextSources[sourceId] = source;
            }
        }
        return nextSources;
    }

    function fetchSource(eventSource, fetchRange, isRefetch, context) {
        let {
            options,
            calendarApi
        } = context;
        let sourceDef = context.pluginHooks.eventSourceDefs[eventSource.sourceDefId];
        let fetchId = guid();
        sourceDef.fetch({
            eventSource,
            range: fetchRange,
            isRefetch,
            context,
        }, (res) => {
            let {
                rawEvents
            } = res;
            if (options.eventSourceSuccess) {
                rawEvents = options.eventSourceSuccess.call(calendarApi, rawEvents, res.response) || rawEvents;
            }
            if (eventSource.success) {
                rawEvents = eventSource.success.call(calendarApi, rawEvents, res.response) || rawEvents;
            }
            context.dispatch({
                type: 'RECEIVE_EVENTS',
                sourceId: eventSource.sourceId,
                fetchId,
                fetchRange,
                rawEvents,
            });
        }, (error) => {
            let errorHandled = false;
            if (options.eventSourceFailure) {
                options.eventSourceFailure.call(calendarApi, error);
                errorHandled = true;
            }
            if (eventSource.failure) {
                eventSource.failure(error);
                errorHandled = true;
            }
            if (!errorHandled) {
                console.warn(error.message, error);
            }
            context.dispatch({
                type: 'RECEIVE_EVENT_ERROR',
                sourceId: eventSource.sourceId,
                fetchId,
                fetchRange,
                error,
            });
        });
        return Object.assign(Object.assign({}, eventSource), {
            isFetching: true,
            latestFetchId: fetchId
        });
    }

    function receiveResponse(sourceHash, sourceId, fetchId, fetchRange) {
        let eventSource = sourceHash[sourceId];
        if (eventSource && // not already removed
            fetchId === eventSource.latestFetchId) {
            return Object.assign(Object.assign({}, sourceHash), {
                [sourceId]: Object.assign(Object.assign({}, eventSource), {
                    isFetching: false,
                    fetchRange
                })
            });
        }
        return sourceHash;
    }

    function excludeStaticSources(eventSources, context) {
        return filterHash(eventSources, (eventSource) => doesSourceNeedRange(eventSource, context));
    }

    function parseInitialSources(rawOptions, context) {
        let refiners = buildEventSourceRefiners(context);
        let rawSources = [].concat(rawOptions.eventSources || []);
        let sources = []; // parsed
        if (rawOptions.initialEvents) {
            rawSources.unshift(rawOptions.initialEvents);
        }
        if (rawOptions.events) {
            rawSources.unshift(rawOptions.events);
        }
        for (let rawSource of rawSources) {
            let source = parseEventSource(rawSource, context, refiners);
            if (source) {
                sources.push(source);
            }
        }
        return sources;
    }

    function doesSourceNeedRange(eventSource, context) {
        let defs = context.pluginHooks.eventSourceDefs;
        return !defs[eventSource.sourceDefId].ignoreRange;
    }

    function reduceDateSelection(currentSelection, action) {
        switch (action.type) {
            case 'UNSELECT_DATES':
                return null;
            case 'SELECT_DATES':
                return action.selection;
            default:
                return currentSelection;
        }
    }

    function reduceSelectedEvent(currentInstanceId, action) {
        switch (action.type) {
            case 'UNSELECT_EVENT':
                return '';
            case 'SELECT_EVENT':
                return action.eventInstanceId;
            default:
                return currentInstanceId;
        }
    }

    function reduceEventDrag(currentDrag, action) {
        let newDrag;
        switch (action.type) {
            case 'UNSET_EVENT_DRAG':
                return null;
            case 'SET_EVENT_DRAG':
                newDrag = action.state;
                return {
                    affectedEvents: newDrag.affectedEvents,
                        mutatedEvents: newDrag.mutatedEvents,
                        isEvent: newDrag.isEvent,
                };
            default:
                return currentDrag;
        }
    }

    function reduceEventResize(currentResize, action) {
        let newResize;
        switch (action.type) {
            case 'UNSET_EVENT_RESIZE':
                return null;
            case 'SET_EVENT_RESIZE':
                newResize = action.state;
                return {
                    affectedEvents: newResize.affectedEvents,
                        mutatedEvents: newResize.mutatedEvents,
                        isEvent: newResize.isEvent,
                };
            default:
                return currentResize;
        }
    }

    function parseToolbars(calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
        let header = calendarOptions.headerToolbar ? parseToolbar(calendarOptions.headerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
        let footer = calendarOptions.footerToolbar ? parseToolbar(calendarOptions.footerToolbar, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) : null;
        return {
            header,
            footer
        };
    }

    function parseToolbar(sectionStrHash, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi) {
        let sectionWidgets = {};
        let viewsWithButtons = [];
        let hasTitle = false;
        for (let sectionName in sectionStrHash) {
            let sectionStr = sectionStrHash[sectionName];
            let sectionRes = parseSection(sectionStr, calendarOptions, calendarOptionOverrides, theme, viewSpecs, calendarApi);
            sectionWidgets[sectionName] = sectionRes.widgets;
            viewsWithButtons.push(...sectionRes.viewsWithButtons);
            hasTitle = hasTitle || sectionRes.hasTitle;
        }
        return {
            sectionWidgets,
            viewsWithButtons,
            hasTitle
        };
    }
    /*
    BAD: querying icons and text here. should be done at render time
    */
    function parseSection(sectionStr, calendarOptions, // defaults+overrides, then refined
        calendarOptionOverrides, // overrides only!, unrefined :(
        theme, viewSpecs, calendarApi) {
        let isRtl = calendarOptions.direction === 'rtl';
        let calendarCustomButtons = calendarOptions.customButtons || {};
        let calendarButtonTextOverrides = calendarOptionOverrides.buttonText || {};
        let calendarButtonText = calendarOptions.buttonText || {};
        let calendarButtonHintOverrides = calendarOptionOverrides.buttonHints || {};
        let calendarButtonHints = calendarOptions.buttonHints || {};
        let sectionSubstrs = sectionStr ? sectionStr.split(' ') : [];
        let viewsWithButtons = [];
        let hasTitle = false;
        let widgets = sectionSubstrs.map((buttonGroupStr) => (buttonGroupStr.split(',').map((buttonName) => {
            if (buttonName === 'title') {
                hasTitle = true;
                return {
                    buttonName
                };
            }
            let customButtonProps;
            let viewSpec;
            let buttonClick;
            let buttonIcon; // only one of these will be set
            let buttonText; // "
            let buttonHint;
            // ^ for the title="" attribute, for accessibility
            if ((customButtonProps = calendarCustomButtons[buttonName])) {
                buttonClick = (ev) => {
                    if (customButtonProps.click) {
                        customButtonProps.click.call(ev.target, ev, ev.target); // TODO: use Calendar this context?
                    }
                };
                (buttonIcon = theme.getCustomButtonIconClass(customButtonProps)) ||
                (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
                (buttonText = customButtonProps.text);
                buttonHint = customButtonProps.hint || customButtonProps.text;
            } else if ((viewSpec = viewSpecs[buttonName])) {
                viewsWithButtons.push(buttonName);
                buttonClick = () => {
                    calendarApi.changeView(buttonName);
                };
                (buttonText = viewSpec.buttonTextOverride) ||
                (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
                (buttonText = viewSpec.buttonTextDefault);
                let textFallback = viewSpec.buttonTextOverride ||
                    viewSpec.buttonTextDefault;
                buttonHint = formatWithOrdinals(viewSpec.buttonTitleOverride ||
                    viewSpec.buttonTitleDefault ||
                    calendarOptions.viewHint, [textFallback, buttonName], // view-name = buttonName
                    textFallback);
            } else if (calendarApi[buttonName]) { // a calendarApi method
                buttonClick = () => {
                    calendarApi[buttonName]();
                };
                (buttonText = calendarButtonTextOverrides[buttonName]) ||
                (buttonIcon = theme.getIconClass(buttonName, isRtl)) ||
                (buttonText = calendarButtonText[buttonName]); // everything else is considered default
                if (buttonName === 'prevYear' || buttonName === 'nextYear') {
                    let prevOrNext = buttonName === 'prevYear' ? 'prev' : 'next';
                    buttonHint = formatWithOrdinals(calendarButtonHintOverrides[prevOrNext] ||
                        calendarButtonHints[prevOrNext], [
                            calendarButtonText.year || 'year',
                            'year',
                        ], calendarButtonText[buttonName]);
                } else {
                    buttonHint = (navUnit) => formatWithOrdinals(calendarButtonHintOverrides[buttonName] ||
                        calendarButtonHints[buttonName], [
                            calendarButtonText[navUnit] || navUnit,
                            navUnit,
                        ], calendarButtonText[buttonName]);
                }
            }
            return {
                buttonName,
                buttonClick,
                buttonIcon,
                buttonText,
                buttonHint
            };
        })));
        return {
            widgets,
            viewsWithButtons,
            hasTitle
        };
    }

    // always represents the current view. otherwise, it'd need to change value every time date changes
    class ViewImpl {
        constructor(type, getCurrentData, dateEnv) {
            this.type = type;
            this.getCurrentData = getCurrentData;
            this.dateEnv = dateEnv;
        }
        get calendar() {
            return this.getCurrentData().calendarApi;
        }
        get title() {
            return this.getCurrentData().viewTitle;
        }
        get activeStart() {
            return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.start);
        }
        get activeEnd() {
            return this.dateEnv.toDate(this.getCurrentData().dateProfile.activeRange.end);
        }
        get currentStart() {
            return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.start);
        }
        get currentEnd() {
            return this.dateEnv.toDate(this.getCurrentData().dateProfile.currentRange.end);
        }
        getOption(name) {
            return this.getCurrentData().options[name]; // are the view-specific options
        }
    }

    let eventSourceDef$2 = {
        ignoreRange: true,
        parseMeta(refined) {
            if (Array.isArray(refined.events)) {
                return refined.events;
            }
            return null;
        },
        fetch(arg, successCallback) {
            successCallback({
                rawEvents: arg.eventSource.meta,
            });
        },
    };
    const arrayEventSourcePlugin = createPlugin({
        name: 'array-event-source',
        eventSourceDefs: [eventSourceDef$2],
    });

    let eventSourceDef$1 = {
        parseMeta(refined) {
            if (typeof refined.events === 'function') {
                return refined.events;
            }
            return null;
        },
        fetch(arg, successCallback, errorCallback) {
            const {
                dateEnv
            } = arg.context;
            const func = arg.eventSource.meta;
            unpromisify(func.bind(null, buildRangeApiWithTimeZone(arg.range, dateEnv)), (rawEvents) => successCallback({
                rawEvents
            }), errorCallback);
        },
    };
    const funcEventSourcePlugin = createPlugin({
        name: 'func-event-source',
        eventSourceDefs: [eventSourceDef$1],
    });

    const JSON_FEED_EVENT_SOURCE_REFINERS = {
        method: String,
        extraParams: identity,
        startParam: String,
        endParam: String,
        timeZoneParam: String,
    };

    let eventSourceDef = {
        parseMeta(refined) {
            if (refined.url && (refined.format === 'json' || !refined.format)) {
                return {
                    url: refined.url,
                    format: 'json',
                    method: (refined.method || 'GET').toUpperCase(),
                    extraParams: refined.extraParams,
                    startParam: refined.startParam,
                    endParam: refined.endParam,
                    timeZoneParam: refined.timeZoneParam,
                };
            }
            return null;
        },
        fetch(arg, successCallback, errorCallback) {
            const {
                meta
            } = arg.eventSource;
            const requestParams = buildRequestParams(meta, arg.range, arg.context);
            requestJson(meta.method, meta.url, requestParams).then(([rawEvents, response]) => {
                successCallback({
                    rawEvents,
                    response
                });
            }, errorCallback);
        },
    };
    const jsonFeedEventSourcePlugin = createPlugin({
        name: 'json-event-source',
        eventSourceRefiners: JSON_FEED_EVENT_SOURCE_REFINERS,
        eventSourceDefs: [eventSourceDef],
    });

    function buildRequestParams(meta, range, context) {
        let {
            dateEnv,
            options
        } = context;
        let startParam;
        let endParam;
        let timeZoneParam;
        let customRequestParams;
        let params = {};
        startParam = meta.startParam;
        if (startParam == null) {
            startParam = options.startParam;
        }
        endParam = meta.endParam;
        if (endParam == null) {
            endParam = options.endParam;
        }
        timeZoneParam = meta.timeZoneParam;
        if (timeZoneParam == null) {
            timeZoneParam = options.timeZoneParam;
        }
        // retrieve any outbound GET/POST data from the options
        if (typeof meta.extraParams === 'function') {
            // supplied as a function that returns a key/value object
            customRequestParams = meta.extraParams();
        } else {
            // probably supplied as a straight key/value object
            customRequestParams = meta.extraParams || {};
        }
        Object.assign(params, customRequestParams);
        params[startParam] = dateEnv.formatIso(range.start);
        params[endParam] = dateEnv.formatIso(range.end);
        if (dateEnv.timeZone !== 'local') {
            params[timeZoneParam] = dateEnv.timeZone;
        }
        return params;
    }

    const SIMPLE_RECURRING_REFINERS = {
        daysOfWeek: identity,
        startTime: createDuration,
        endTime: createDuration,
        duration: createDuration,
        startRecur: identity,
        endRecur: identity,
    };

    let recurring = {
        parse(refined, dateEnv) {
            if (refined.daysOfWeek || refined.startTime || refined.endTime || refined.startRecur || refined.endRecur) {
                let recurringData = {
                    daysOfWeek: refined.daysOfWeek || null,
                    startTime: refined.startTime || null,
                    endTime: refined.endTime || null,
                    startRecur: refined.startRecur ? dateEnv.createMarker(refined.startRecur) : null,
                    endRecur: refined.endRecur ? dateEnv.createMarker(refined.endRecur) : null,
                    dateEnv,
                };
                let duration;
                if (refined.duration) {
                    duration = refined.duration;
                }
                if (!duration && refined.startTime && refined.endTime) {
                    duration = subtractDurations(refined.endTime, refined.startTime);
                }
                return {
                    allDayGuess: Boolean(!refined.startTime && !refined.endTime),
                    duration,
                    typeData: recurringData, // doesn't need endTime anymore but oh well
                };
            }
            return null;
        },
        expand(typeData, framingRange, dateEnv) {
            let clippedFramingRange = intersectRanges(framingRange, {
                start: typeData.startRecur,
                end: typeData.endRecur
            });
            if (clippedFramingRange) {
                return expandRanges(typeData.daysOfWeek, typeData.startTime, typeData.dateEnv, dateEnv, clippedFramingRange);
            }
            return [];
        },
    };
    const simpleRecurringEventsPlugin = createPlugin({
        name: 'simple-recurring-event',
        recurringTypes: [recurring],
        eventRefiners: SIMPLE_RECURRING_REFINERS,
    });

    function expandRanges(daysOfWeek, startTime, eventDateEnv, calendarDateEnv, framingRange) {
        let dowHash = daysOfWeek ? arrayToHash(daysOfWeek) : null;
        let dayMarker = startOfDay(framingRange.start);
        let endMarker = framingRange.end;
        let instanceStarts = [];
        // https://github.com/fullcalendar/fullcalendar/issues/7934
        if (startTime) {
            if (startTime.milliseconds < 0) {
                // possible for next-day to have negative business hours that go into current day
                endMarker = addDays(endMarker, 1);
            } else if (startTime.milliseconds >= 1000 * 60 * 60 * 24) {
                // possible for prev-day to have >24hr business hours that go into current day
                dayMarker = addDays(dayMarker, -1);
            }
        }
        while (dayMarker < endMarker) {
            let instanceStart;
            // if everyday, or this particular day-of-week
            if (!dowHash || dowHash[dayMarker.getUTCDay()]) {
                if (startTime) {
                    instanceStart = calendarDateEnv.add(dayMarker, startTime);
                } else {
                    instanceStart = dayMarker;
                }
                instanceStarts.push(calendarDateEnv.createMarker(eventDateEnv.toDate(instanceStart)));
            }
            dayMarker = addDays(dayMarker, 1);
        }
        return instanceStarts;
    }

    const changeHandlerPlugin = createPlugin({
        name: 'change-handler',
        optionChangeHandlers: {
            events(events, context) {
                handleEventSources([events], context);
            },
            eventSources: handleEventSources,
        },
    });
    /*
    BUG: if `event` was supplied, all previously-given `eventSources` will be wiped out
    */
    function handleEventSources(inputs, context) {
        let unfoundSources = hashValuesToArray(context.getCurrentData().eventSources);
        if (unfoundSources.length === 1 &&
            inputs.length === 1 &&
            Array.isArray(unfoundSources[0]._raw) &&
            Array.isArray(inputs[0])) {
            context.dispatch({
                type: 'RESET_RAW_EVENTS',
                sourceId: unfoundSources[0].sourceId,
                rawEvents: inputs[0],
            });
            return;
        }
        let newInputs = [];
        for (let input of inputs) {
            let inputFound = false;
            for (let i = 0; i < unfoundSources.length; i += 1) {
                if (unfoundSources[i]._raw === input) {
                    unfoundSources.splice(i, 1); // delete
                    inputFound = true;
                    break;
                }
            }
            if (!inputFound) {
                newInputs.push(input);
            }
        }
        for (let unfoundSource of unfoundSources) {
            context.dispatch({
                type: 'REMOVE_EVENT_SOURCE',
                sourceId: unfoundSource.sourceId,
            });
        }
        for (let newInput of newInputs) {
            context.calendarApi.addEventSource(newInput);
        }
    }

    function handleDateProfile(dateProfile, context) {
        context.emitter.trigger('datesSet', Object.assign(Object.assign({}, buildRangeApiWithTimeZone(dateProfile.activeRange, context.dateEnv)), {
            view: context.viewApi
        }));
    }

    function handleEventStore(eventStore, context) {
        let {
            emitter
        } = context;
        if (emitter.hasHandlers('eventsSet')) {
            emitter.trigger('eventsSet', buildEventApis(eventStore, context));
        }
    }

    /*
    this array is exposed on the root namespace so that UMD plugins can add to it.
    see the rollup-bundles script.
    */
    const globalPlugins = [
        arrayEventSourcePlugin,
        funcEventSourcePlugin,
        jsonFeedEventSourcePlugin,
        simpleRecurringEventsPlugin,
        changeHandlerPlugin,
        createPlugin({
            name: 'misc',
            isLoadingFuncs: [
                (state) => computeEventSourcesLoading(state.eventSources),
            ],
            propSetHandlers: {
                dateProfile: handleDateProfile,
                eventStore: handleEventStore,
            },
        }),
    ];

    class TaskRunner {
        constructor(runTaskOption, drainedOption) {
            this.runTaskOption = runTaskOption;
            this.drainedOption = drainedOption;
            this.queue = [];
            this.delayedRunner = new DelayedRunner(this.drain.bind(this));
        }
        request(task, delay) {
            this.queue.push(task);
            this.delayedRunner.request(delay);
        }
        pause(scope) {
            this.delayedRunner.pause(scope);
        }
        resume(scope, force) {
            this.delayedRunner.resume(scope, force);
        }
        drain() {
            let {
                queue
            } = this;
            while (queue.length) {
                let completedTasks = [];
                let task;
                while ((task = queue.shift())) {
                    this.runTask(task);
                    completedTasks.push(task);
                }
                this.drained(completedTasks);
            } // keep going, in case new tasks were added in the drained handler
        }
        runTask(task) {
            if (this.runTaskOption) {
                this.runTaskOption(task);
            }
        }
        drained(completedTasks) {
            if (this.drainedOption) {
                this.drainedOption(completedTasks);
            }
        }
    }

    // Computes what the title at the top of the calendarApi should be for this view
    function buildTitle(dateProfile, viewOptions, dateEnv) {
        let range;
        // for views that span a large unit of time, show the proper interval, ignoring stray days before and after
        if (/^(year|month)$/.test(dateProfile.currentRangeUnit)) {
            range = dateProfile.currentRange;
        } else { // for day units or smaller, use the actual day range
            range = dateProfile.activeRange;
        }
        return dateEnv.formatRange(range.start, range.end, createFormatter(viewOptions.titleFormat || buildTitleFormat(dateProfile)), {
            isEndExclusive: dateProfile.isRangeAllDay,
            defaultSeparator: viewOptions.titleRangeSeparator,
        });
    }
    // Generates the format string that should be used to generate the title for the current date range.
    // Attempts to compute the most appropriate format if not explicitly specified with `titleFormat`.
    function buildTitleFormat(dateProfile) {
        let {
            currentRangeUnit
        } = dateProfile;
        if (currentRangeUnit === 'year') {
            return {
                year: 'numeric'
            };
        }
        if (currentRangeUnit === 'month') {
            return {
                year: 'numeric',
                month: 'long'
            }; // like "September 2014"
        }
        let days = diffWholeDays(dateProfile.currentRange.start, dateProfile.currentRange.end);
        if (days !== null && days > 1) {
            // multi-day range. shorter, like "Sep 9 - 10 2014"
            return {
                year: 'numeric',
                month: 'short',
                day: 'numeric'
            };
        }
        // one day. longer, like "September 9 2014"
        return {
            year: 'numeric',
            month: 'long',
            day: 'numeric'
        };
    }

    /*
    TODO: test switching timezones when NO timezone plugin
    */
    class CalendarNowManager {
        constructor() {
            this.resetListeners = new Set();
        }
        handleInput(dateEnv, // will change if timezone setup changed
            nowInput) {
            const oldDateEnv = this.dateEnv;
            if (dateEnv !== oldDateEnv) {
                if (typeof nowInput === 'function') {
                    this.nowFn = nowInput;
                } else if (!oldDateEnv) { // first time?
                    this.nowAnchorDate = dateEnv.toDate(nowInput ?
                        dateEnv.createMarker(nowInput) :
                        dateEnv.createNowMarker());
                    this.nowAnchorQueried = Date.now();
                }
                this.dateEnv = dateEnv;
                // not first time? fire reset handlers
                if (oldDateEnv) {
                    for (const resetListener of this.resetListeners.values()) {
                        resetListener();
                    }
                }
            }
        }
        getDateMarker() {
            return this.nowAnchorDate ?
                this.dateEnv.timestampToMarker(this.nowAnchorDate.valueOf() +
                    (Date.now() - this.nowAnchorQueried)) :
                this.dateEnv.createMarker(this.nowFn());
        }
        addResetListener(handler) {
            this.resetListeners.add(handler);
        }
        removeResetListener(handler) {
            this.resetListeners.delete(handler);
        }
    }

    // in future refactor, do the redux-style function(state=initial) for initial-state
    // also, whatever is happening in constructor, have it happen in action queue too
    class CalendarDataManager {
        constructor(props) {
            this.computeCurrentViewData = memoize(this._computeCurrentViewData);
            this.organizeRawLocales = memoize(organizeRawLocales);
            this.buildLocale = memoize(buildLocale);
            this.buildPluginHooks = buildBuildPluginHooks();
            this.buildDateEnv = memoize(buildDateEnv$1);
            this.buildTheme = memoize(buildTheme);
            this.parseToolbars = memoize(parseToolbars);
            this.buildViewSpecs = memoize(buildViewSpecs);
            this.buildDateProfileGenerator = memoizeObjArg(buildDateProfileGenerator);
            this.buildViewApi = memoize(buildViewApi);
            this.buildViewUiProps = memoizeObjArg(buildViewUiProps);
            this.buildEventUiBySource = memoize(buildEventUiBySource, isPropsEqual);
            this.buildEventUiBases = memoize(buildEventUiBases);
            this.parseContextBusinessHours = memoizeObjArg(parseContextBusinessHours);
            this.buildTitle = memoize(buildTitle);
            this.nowManager = new CalendarNowManager();
            this.emitter = new Emitter();
            this.actionRunner = new TaskRunner(this._handleAction.bind(this), this.updateData.bind(this));
            this.currentCalendarOptionsInput = {};
            this.currentCalendarOptionsRefined = {};
            this.currentViewOptionsInput = {};
            this.currentViewOptionsRefined = {};
            this.currentCalendarOptionsRefiners = {};
            this.optionsForRefining = [];
            this.optionsForHandling = [];
            this.getCurrentData = () => this.data;
            this.dispatch = (action) => {
                this.actionRunner.request(action); // protects against recursive calls to _handleAction
            };
            this.props = props;
            this.actionRunner.pause();
            this.nowManager = new CalendarNowManager();
            let dynamicOptionOverrides = {};
            let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
            let currentViewType = optionsData.calendarOptions.initialView || optionsData.pluginHooks.initialView;
            let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
            // wire things up
            // TODO: not DRY
            props.calendarApi.currentDataManager = this;
            this.emitter.setThisContext(props.calendarApi);
            this.emitter.setOptions(currentViewData.options);
            let calendarContext = {
                nowManager: this.nowManager,
                dateEnv: optionsData.dateEnv,
                options: optionsData.calendarOptions,
                pluginHooks: optionsData.pluginHooks,
                calendarApi: props.calendarApi,
                dispatch: this.dispatch,
                emitter: this.emitter,
                getCurrentData: this.getCurrentData,
            };
            let currentDate = getInitialDate(optionsData.calendarOptions, optionsData.dateEnv, this.nowManager);
            let dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
            if (!rangeContainsMarker(dateProfile.activeRange, currentDate)) {
                currentDate = dateProfile.currentRange.start;
            }
            // needs to be after setThisContext
            for (let callback of optionsData.pluginHooks.contextInit) {
                callback(calendarContext);
            }
            // NOT DRY
            let eventSources = initEventSources(optionsData.calendarOptions, dateProfile, calendarContext);
            let initialState = {
                dynamicOptionOverrides,
                currentViewType,
                currentDate,
                dateProfile,
                businessHours: this.parseContextBusinessHours(calendarContext),
                eventSources,
                eventUiBases: {},
                eventStore: createEmptyEventStore(),
                renderableEventStore: createEmptyEventStore(),
                dateSelection: null,
                eventSelection: '',
                eventDrag: null,
                eventResize: null,
                selectionConfig: this.buildViewUiProps(calendarContext).selectionConfig,
            };
            let contextAndState = Object.assign(Object.assign({}, calendarContext), initialState);
            for (let reducer of optionsData.pluginHooks.reducers) {
                Object.assign(initialState, reducer(null, null, contextAndState));
            }
            if (computeIsLoading(initialState, calendarContext)) {
                this.emitter.trigger('loading', true); // NOT DRY
            }
            this.state = initialState;
            this.updateData();
            this.actionRunner.resume();
        }
        resetOptions(optionOverrides, changedOptionNames) {
            let {
                props
            } = this;
            if (changedOptionNames === undefined) {
                props.optionOverrides = optionOverrides;
            } else {
                props.optionOverrides = Object.assign(Object.assign({}, (props.optionOverrides || {})), optionOverrides);
                this.optionsForRefining.push(...changedOptionNames);
            }
            if (changedOptionNames === undefined || changedOptionNames.length) {
                this.actionRunner.request({
                    type: 'NOTHING',
                });
            }
        }
        _handleAction(action) {
            let {
                props,
                state,
                emitter
            } = this;
            let dynamicOptionOverrides = reduceDynamicOptionOverrides(state.dynamicOptionOverrides, action);
            let optionsData = this.computeOptionsData(props.optionOverrides, dynamicOptionOverrides, props.calendarApi);
            let currentViewType = reduceViewType(state.currentViewType, action);
            let currentViewData = this.computeCurrentViewData(currentViewType, optionsData, props.optionOverrides, dynamicOptionOverrides);
            // wire things up
            // TODO: not DRY
            props.calendarApi.currentDataManager = this;
            emitter.setThisContext(props.calendarApi);
            emitter.setOptions(currentViewData.options);
            let calendarContext = {
                nowManager: this.nowManager,
                dateEnv: optionsData.dateEnv,
                options: optionsData.calendarOptions,
                pluginHooks: optionsData.pluginHooks,
                calendarApi: props.calendarApi,
                dispatch: this.dispatch,
                emitter,
                getCurrentData: this.getCurrentData,
            };
            let {
                currentDate,
                dateProfile
            } = state;
            if (this.data && this.data.dateProfileGenerator !== currentViewData.dateProfileGenerator) { // hack
                dateProfile = currentViewData.dateProfileGenerator.build(currentDate);
            }
            currentDate = reduceCurrentDate(currentDate, action);
            dateProfile = reduceDateProfile(dateProfile, action, currentDate, currentViewData.dateProfileGenerator);
            if (action.type === 'PREV' || // TODO: move this logic into DateProfileGenerator
                action.type === 'NEXT' || // "
                !rangeContainsMarker(dateProfile.currentRange, currentDate)) {
                currentDate = dateProfile.currentRange.start;
            }
            let eventSources = reduceEventSources(state.eventSources, action, dateProfile, calendarContext);
            let eventStore = reduceEventStore(state.eventStore, action, eventSources, dateProfile, calendarContext);
            let isEventsLoading = computeEventSourcesLoading(eventSources); // BAD. also called in this func in computeIsLoading
            let renderableEventStore = (isEventsLoading && !currentViewData.options.progressiveEventRendering) ?
                (state.renderableEventStore || eventStore) : // try from previous state
                eventStore;
            let {
                eventUiSingleBase,
                selectionConfig
            } = this.buildViewUiProps(calendarContext); // will memoize obj
            let eventUiBySource = this.buildEventUiBySource(eventSources);
            let eventUiBases = this.buildEventUiBases(renderableEventStore.defs, eventUiSingleBase, eventUiBySource);
            let newState = {
                dynamicOptionOverrides,
                currentViewType,
                currentDate,
                dateProfile,
                eventSources,
                eventStore,
                renderableEventStore,
                selectionConfig,
                eventUiBases,
                businessHours: this.parseContextBusinessHours(calendarContext),
                dateSelection: reduceDateSelection(state.dateSelection, action),
                eventSelection: reduceSelectedEvent(state.eventSelection, action),
                eventDrag: reduceEventDrag(state.eventDrag, action),
                eventResize: reduceEventResize(state.eventResize, action),
            };
            let contextAndState = Object.assign(Object.assign({}, calendarContext), newState);
            for (let reducer of optionsData.pluginHooks.reducers) {
                Object.assign(newState, reducer(state, action, contextAndState)); // give the OLD state, for old value
            }
            let wasLoading = computeIsLoading(state, calendarContext);
            let isLoading = computeIsLoading(newState, calendarContext);
            // TODO: use propSetHandlers in plugin system
            if (!wasLoading && isLoading) {
                emitter.trigger('loading', true);
            } else if (wasLoading && !isLoading) {
                emitter.trigger('loading', false);
            }
            this.state = newState;
            if (props.onAction) {
                props.onAction(action);
            }
        }
        updateData() {
            let {
                props,
                state
            } = this;
            let oldData = this.data;
            let optionsData = this.computeOptionsData(props.optionOverrides, state.dynamicOptionOverrides, props.calendarApi);
            let currentViewData = this.computeCurrentViewData(state.currentViewType, optionsData, props.optionOverrides, state.dynamicOptionOverrides);
            let data = this.data = Object.assign(Object.assign(Object.assign({
                nowManager: this.nowManager,
                viewTitle: this.buildTitle(state.dateProfile, currentViewData.options, optionsData.dateEnv),
                calendarApi: props.calendarApi,
                dispatch: this.dispatch,
                emitter: this.emitter,
                getCurrentData: this.getCurrentData
            }, optionsData), currentViewData), state);
            let changeHandlers = optionsData.pluginHooks.optionChangeHandlers;
            let oldCalendarOptions = oldData && oldData.calendarOptions;
            let newCalendarOptions = optionsData.calendarOptions;
            if (oldCalendarOptions && oldCalendarOptions !== newCalendarOptions) {
                if (oldCalendarOptions.timeZone !== newCalendarOptions.timeZone) {
                    // hack
                    state.eventSources = data.eventSources = reduceEventSourcesNewTimeZone(data.eventSources, state.dateProfile, data);
                    state.eventStore = data.eventStore = rezoneEventStoreDates(data.eventStore, oldData.dateEnv, data.dateEnv);
                    state.renderableEventStore = data.renderableEventStore = rezoneEventStoreDates(data.renderableEventStore, oldData.dateEnv, data.dateEnv);
                }
                for (let optionName in changeHandlers) {
                    if (this.optionsForHandling.indexOf(optionName) !== -1 ||
                        oldCalendarOptions[optionName] !== newCalendarOptions[optionName]) {
                        changeHandlers[optionName](newCalendarOptions[optionName], data);
                    }
                }
            }
            this.optionsForHandling = [];
            if (props.onData) {
                props.onData(data);
            }
        }
        computeOptionsData(optionOverrides, dynamicOptionOverrides, calendarApi) {
            // TODO: blacklist options that are handled by optionChangeHandlers
            if (!this.optionsForRefining.length &&
                optionOverrides === this.stableOptionOverrides &&
                dynamicOptionOverrides === this.stableDynamicOptionOverrides) {
                return this.stableCalendarOptionsData;
            }
            let {
                refinedOptions,
                pluginHooks,
                localeDefaults,
                availableLocaleData,
                extra,
            } = this.processRawCalendarOptions(optionOverrides, dynamicOptionOverrides);
            warnUnknownOptions(extra);
            let dateEnv = this.buildDateEnv(refinedOptions.timeZone, refinedOptions.locale, refinedOptions.weekNumberCalculation, refinedOptions.firstDay, refinedOptions.weekText, pluginHooks, availableLocaleData, refinedOptions.defaultRangeSeparator);
            let viewSpecs = this.buildViewSpecs(pluginHooks.views, this.stableOptionOverrides, this.stableDynamicOptionOverrides, localeDefaults);
            let theme = this.buildTheme(refinedOptions, pluginHooks);
            let toolbarConfig = this.parseToolbars(refinedOptions, this.stableOptionOverrides, theme, viewSpecs, calendarApi);
            return this.stableCalendarOptionsData = {
                calendarOptions: refinedOptions,
                pluginHooks,
                dateEnv,
                viewSpecs,
                theme,
                toolbarConfig,
                localeDefaults,
                availableRawLocales: availableLocaleData.map,
            };
        }
        // always called from behind a memoizer
        processRawCalendarOptions(optionOverrides, dynamicOptionOverrides) {
            let {
                locales,
                locale
            } = mergeRawOptions([
                BASE_OPTION_DEFAULTS,
                optionOverrides,
                dynamicOptionOverrides,
            ]);
            let availableLocaleData = this.organizeRawLocales(locales);
            let availableRawLocales = availableLocaleData.map;
            let localeDefaults = this.buildLocale(locale || availableLocaleData.defaultCode, availableRawLocales).options;
            let pluginHooks = this.buildPluginHooks(optionOverrides.plugins || [], globalPlugins);
            let refiners = this.currentCalendarOptionsRefiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
            let extra = {};
            let raw = mergeRawOptions([
                BASE_OPTION_DEFAULTS,
                localeDefaults,
                optionOverrides,
                dynamicOptionOverrides,
            ]);
            let refined = {};
            let currentRaw = this.currentCalendarOptionsInput;
            let currentRefined = this.currentCalendarOptionsRefined;
            let anyChanges = false;
            for (let optionName in raw) {
                if (this.optionsForRefining.indexOf(optionName) === -1 && (raw[optionName] === currentRaw[optionName] || (COMPLEX_OPTION_COMPARATORS[optionName] &&
                        (optionName in currentRaw) &&
                        COMPLEX_OPTION_COMPARATORS[optionName](currentRaw[optionName], raw[optionName])))) {
                    refined[optionName] = currentRefined[optionName];
                } else if (refiners[optionName]) {
                    refined[optionName] = refiners[optionName](raw[optionName]);
                    anyChanges = true;
                } else {
                    extra[optionName] = currentRaw[optionName];
                }
            }
            if (anyChanges) {
                this.currentCalendarOptionsInput = raw;
                this.currentCalendarOptionsRefined = refined;
                this.stableOptionOverrides = optionOverrides;
                this.stableDynamicOptionOverrides = dynamicOptionOverrides;
            }
            this.optionsForHandling.push(...this.optionsForRefining);
            this.optionsForRefining = [];
            return {
                rawOptions: this.currentCalendarOptionsInput,
                refinedOptions: this.currentCalendarOptionsRefined,
                pluginHooks,
                availableLocaleData,
                localeDefaults,
                extra,
            };
        }
        _computeCurrentViewData(viewType, optionsData, optionOverrides, dynamicOptionOverrides) {
            let viewSpec = optionsData.viewSpecs[viewType];
            if (!viewSpec) {
                throw new Error(`viewType "${viewType}" is not available. Please make sure you've loaded all neccessary plugins`);
            }
            let {
                refinedOptions,
                extra
            } = this.processRawViewOptions(viewSpec, optionsData.pluginHooks, optionsData.localeDefaults, optionOverrides, dynamicOptionOverrides);
            warnUnknownOptions(extra);
            this.nowManager.handleInput(optionsData.dateEnv, refinedOptions.now);
            let dateProfileGenerator = this.buildDateProfileGenerator({
                dateProfileGeneratorClass: viewSpec.optionDefaults.dateProfileGeneratorClass,
                nowManager: this.nowManager,
                duration: viewSpec.duration,
                durationUnit: viewSpec.durationUnit,
                usesMinMaxTime: viewSpec.optionDefaults.usesMinMaxTime,
                dateEnv: optionsData.dateEnv,
                calendarApi: this.props.calendarApi,
                slotMinTime: refinedOptions.slotMinTime,
                slotMaxTime: refinedOptions.slotMaxTime,
                showNonCurrentDates: refinedOptions.showNonCurrentDates,
                dayCount: refinedOptions.dayCount,
                dateAlignment: refinedOptions.dateAlignment,
                dateIncrement: refinedOptions.dateIncrement,
                hiddenDays: refinedOptions.hiddenDays,
                weekends: refinedOptions.weekends,
                validRangeInput: refinedOptions.validRange,
                visibleRangeInput: refinedOptions.visibleRange,
                fixedWeekCount: refinedOptions.fixedWeekCount,
            });
            let viewApi = this.buildViewApi(viewType, this.getCurrentData, optionsData.dateEnv);
            return {
                viewSpec,
                options: refinedOptions,
                dateProfileGenerator,
                viewApi
            };
        }
        processRawViewOptions(viewSpec, pluginHooks, localeDefaults, optionOverrides, dynamicOptionOverrides) {
            let raw = mergeRawOptions([
                BASE_OPTION_DEFAULTS,
                viewSpec.optionDefaults,
                localeDefaults,
                optionOverrides,
                viewSpec.optionOverrides,
                dynamicOptionOverrides,
            ]);
            let refiners = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, BASE_OPTION_REFINERS), CALENDAR_LISTENER_REFINERS), CALENDAR_OPTION_REFINERS), VIEW_OPTION_REFINERS), pluginHooks.listenerRefiners), pluginHooks.optionRefiners);
            let refined = {};
            let currentRaw = this.currentViewOptionsInput;
            let currentRefined = this.currentViewOptionsRefined;
            let anyChanges = false;
            let extra = {};
            for (let optionName in raw) {
                if (raw[optionName] === currentRaw[optionName] ||
                    (COMPLEX_OPTION_COMPARATORS[optionName] &&
                        COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], currentRaw[optionName]))) {
                    refined[optionName] = currentRefined[optionName];
                } else {
                    if (raw[optionName] === this.currentCalendarOptionsInput[optionName] ||
                        (COMPLEX_OPTION_COMPARATORS[optionName] &&
                            COMPLEX_OPTION_COMPARATORS[optionName](raw[optionName], this.currentCalendarOptionsInput[optionName]))) {
                        if (optionName in this.currentCalendarOptionsRefined) { // might be an "extra" prop
                            refined[optionName] = this.currentCalendarOptionsRefined[optionName];
                        }
                    } else if (refiners[optionName]) {
                        refined[optionName] = refiners[optionName](raw[optionName]);
                    } else {
                        extra[optionName] = raw[optionName];
                    }
                    anyChanges = true;
                }
            }
            if (anyChanges) {
                this.currentViewOptionsInput = raw;
                this.currentViewOptionsRefined = refined;
            }
            return {
                rawOptions: this.currentViewOptionsInput,
                refinedOptions: this.currentViewOptionsRefined,
                extra,
            };
        }
    }

    function buildDateEnv$1(timeZone, explicitLocale, weekNumberCalculation, firstDay, weekText, pluginHooks, availableLocaleData, defaultSeparator) {
        let locale = buildLocale(explicitLocale || availableLocaleData.defaultCode, availableLocaleData.map);
        return new DateEnv({
            calendarSystem: 'gregory',
            timeZone,
            namedTimeZoneImpl: pluginHooks.namedTimeZonedImpl,
            locale,
            weekNumberCalculation,
            firstDay,
            weekText,
            cmdFormatter: pluginHooks.cmdFormatter,
            defaultSeparator,
        });
    }

    function buildTheme(options, pluginHooks) {
        let ThemeClass = pluginHooks.themeClasses[options.themeSystem] || StandardTheme;
        return new ThemeClass(options);
    }

    function buildDateProfileGenerator(props) {
        let DateProfileGeneratorClass = props.dateProfileGeneratorClass || DateProfileGenerator;
        return new DateProfileGeneratorClass(props);
    }

    function buildViewApi(type, getCurrentData, dateEnv) {
        return new ViewImpl(type, getCurrentData, dateEnv);
    }

    function buildEventUiBySource(eventSources) {
        return mapHash(eventSources, (eventSource) => eventSource.ui);
    }

    function buildEventUiBases(eventDefs, eventUiSingleBase, eventUiBySource) {
        let eventUiBases = {
            '': eventUiSingleBase
        };
        for (let defId in eventDefs) {
            let def = eventDefs[defId];
            if (def.sourceId && eventUiBySource[def.sourceId]) {
                eventUiBases[defId] = eventUiBySource[def.sourceId];
            }
        }
        return eventUiBases;
    }

    function buildViewUiProps(calendarContext) {
        let {
            options
        } = calendarContext;
        return {
            eventUiSingleBase: createEventUi({
                display: options.eventDisplay,
                editable: options.editable,
                startEditable: options.eventStartEditable,
                durationEditable: options.eventDurationEditable,
                constraint: options.eventConstraint,
                overlap: typeof options.eventOverlap === 'boolean' ? options.eventOverlap : undefined,
                allow: options.eventAllow,
                backgroundColor: options.eventBackgroundColor,
                borderColor: options.eventBorderColor,
                textColor: options.eventTextColor,
                color: options.eventColor,
                // classNames: options.eventClassNames // render hook will handle this
            }, calendarContext),
            selectionConfig: createEventUi({
                constraint: options.selectConstraint,
                overlap: typeof options.selectOverlap === 'boolean' ? options.selectOverlap : undefined,
                allow: options.selectAllow,
            }, calendarContext),
        };
    }

    function computeIsLoading(state, context) {
        for (let isLoadingFunc of context.pluginHooks.isLoadingFuncs) {
            if (isLoadingFunc(state)) {
                return true;
            }
        }
        return false;
    }

    function parseContextBusinessHours(calendarContext) {
        return parseBusinessHours(calendarContext.options.businessHours, calendarContext);
    }

    function warnUnknownOptions(options, viewName) {
        for (let optionName in options) {
            console.warn(`Unknown option '${optionName}'` +
                (viewName ? ` for view '${viewName}'` : ''));
        }
    }

    class ToolbarSection extends BaseComponent {
        render() {
            let children = this.props.widgetGroups.map((widgetGroup) => this.renderWidgetGroup(widgetGroup));
            return y('div', {
                className: 'fc-toolbar-chunk'
            }, ...children);
        }
        renderWidgetGroup(widgetGroup) {
            let {
                props
            } = this;
            let {
                theme
            } = this.context;
            let children = [];
            let isOnlyButtons = true;
            for (let widget of widgetGroup) {
                let {
                    buttonName,
                    buttonClick,
                    buttonText,
                    buttonIcon,
                    buttonHint
                } = widget;
                if (buttonName === 'title') {
                    isOnlyButtons = false;
                    children.push(y("h2", {
                        className: "fc-toolbar-title",
                        id: props.titleId
                    }, props.title));
                } else {
                    let isPressed = buttonName === props.activeButton;
                    let isDisabled = (!props.isTodayEnabled && buttonName === 'today') ||
                        (!props.isPrevEnabled && buttonName === 'prev') ||
                        (!props.isNextEnabled && buttonName === 'next');
                    let buttonClasses = [`fc-${buttonName}-button`, theme.getClass('button')];
                    if (isPressed) {
                        buttonClasses.push(theme.getClass('buttonActive'));
                    }
                    children.push(y("button", {
                        type: "button",
                        title: typeof buttonHint === 'function' ? buttonHint(props.navUnit) : buttonHint,
                        disabled: isDisabled,
                        "aria-pressed": isPressed,
                        className: buttonClasses.join(' '),
                        onClick: buttonClick
                    }, buttonText || (buttonIcon ? y("span", {
                        className: buttonIcon,
                        role: "img"
                    }) : '')));
                }
            }
            if (children.length > 1) {
                let groupClassName = (isOnlyButtons && theme.getClass('buttonGroup')) || '';
                return y('div', {
                    className: groupClassName
                }, ...children);
            }
            return children[0];
        }
    }

    class Toolbar extends BaseComponent {
        render() {
            let {
                model,
                extraClassName
            } = this.props;
            let forceLtr = false;
            let startContent;
            let endContent;
            let sectionWidgets = model.sectionWidgets;
            let centerContent = sectionWidgets.center;
            if (sectionWidgets.left) {
                forceLtr = true;
                startContent = sectionWidgets.left;
            } else {
                startContent = sectionWidgets.start;
            }
            if (sectionWidgets.right) {
                forceLtr = true;
                endContent = sectionWidgets.right;
            } else {
                endContent = sectionWidgets.end;
            }
            let classNames = [
                extraClassName || '',
                'fc-toolbar',
                forceLtr ? 'fc-toolbar-ltr' : '',
            ];
            return (y("div", {
                    className: classNames.join(' ')
                },
                this.renderSection('start', startContent || []),
                this.renderSection('center', centerContent || []),
                this.renderSection('end', endContent || [])));
        }
        renderSection(key, widgetGroups) {
            let {
                props
            } = this;
            return (y(ToolbarSection, {
                key: key,
                widgetGroups: widgetGroups,
                title: props.title,
                navUnit: props.navUnit,
                activeButton: props.activeButton,
                isTodayEnabled: props.isTodayEnabled,
                isPrevEnabled: props.isPrevEnabled,
                isNextEnabled: props.isNextEnabled,
                titleId: props.titleId
            }));
        }
    }

    class ViewHarness extends BaseComponent {
        constructor() {
            super(...arguments);
            this.state = {
                availableWidth: null,
            };
            this.handleEl = (el) => {
                this.el = el;
                setRef(this.props.elRef, el);
                this.updateAvailableWidth();
            };
            this.handleResize = () => {
                this.updateAvailableWidth();
            };
        }
        render() {
            let {
                props,
                state
            } = this;
            let {
                aspectRatio
            } = props;
            let classNames = [
                'fc-view-harness',
                (aspectRatio || props.liquid || props.height) ?
                'fc-view-harness-active' // harness controls the height
                :
                'fc-view-harness-passive', // let the view do the height
            ];
            let height = '';
            let paddingBottom = '';
            if (aspectRatio) {
                if (state.availableWidth !== null) {
                    height = state.availableWidth / aspectRatio;
                } else {
                    // while waiting to know availableWidth, we can't set height to *zero*
                    // because will cause lots of unnecessary scrollbars within scrollgrid.
                    // BETTER: don't start rendering ANYTHING yet until we know container width
                    // NOTE: why not always use paddingBottom? Causes height oscillation (issue 5606)
                    paddingBottom = `${(1 / aspectRatio) * 100}%`;
                }
            } else {
                height = props.height || '';
            }
            return (y("div", {
                "aria-labelledby": props.labeledById,
                ref: this.handleEl,
                className: classNames.join(' '),
                style: {
                    height,
                    paddingBottom
                }
            }, props.children));
        }
        componentDidMount() {
            this.context.addResizeHandler(this.handleResize);
        }
        componentWillUnmount() {
            this.context.removeResizeHandler(this.handleResize);
        }
        updateAvailableWidth() {
            if (this.el && // needed. but why?
                this.props.aspectRatio // aspectRatio is the only height setting that needs availableWidth
            ) {
                this.setState({
                    availableWidth: this.el.offsetWidth
                });
            }
        }
    }

    /*
    Detects when the user clicks on an event within a DateComponent
    */
    class EventClicking extends Interaction {
        constructor(settings) {
            super(settings);
            this.handleSegClick = (ev, segEl) => {
                let {
                    component
                } = this;
                let {
                    context
                } = component;
                let seg = getElSeg(segEl);
                if (seg && // might be the <div> surrounding the more link
                    component.isValidSegDownEl(ev.target)) {
                    // our way to simulate a link click for elements that can't be <a> tags
                    // grab before trigger fired in case trigger trashes DOM thru rerendering
                    let hasUrlContainer = elementClosest(ev.target, '.fc-event-forced-url');
                    let url = hasUrlContainer ? hasUrlContainer.querySelector('a[href]').href : '';
                    context.emitter.trigger('eventClick', {
                        el: segEl,
                        event: new EventImpl(component.context, seg.eventRange.def, seg.eventRange.instance),
                        jsEvent: ev,
                        view: context.viewApi,
                    });
                    if (url && !ev.defaultPrevented) {
                        window.location.href = url;
                    }
                }
            };
            this.destroy = listenBySelector(settings.el, 'click', '.fc-event', // on both fg and bg events
                this.handleSegClick);
        }
    }

    /*
    Triggers events and adds/removes core classNames when the user's pointer
    enters/leaves event-elements of a component.
    */
    class EventHovering extends Interaction {
        constructor(settings) {
            super(settings);
            // for simulating an eventMouseLeave when the event el is destroyed while mouse is over it
            this.handleEventElRemove = (el) => {
                if (el === this.currentSegEl) {
                    this.handleSegLeave(null, this.currentSegEl);
                }
            };
            this.handleSegEnter = (ev, segEl) => {
                if (getElSeg(segEl)) { // TODO: better way to make sure not hovering over more+ link or its wrapper
                    this.currentSegEl = segEl;
                    this.triggerEvent('eventMouseEnter', ev, segEl);
                }
            };
            this.handleSegLeave = (ev, segEl) => {
                if (this.currentSegEl) {
                    this.currentSegEl = null;
                    this.triggerEvent('eventMouseLeave', ev, segEl);
                }
            };
            this.removeHoverListeners = listenToHoverBySelector(settings.el, '.fc-event', // on both fg and bg events
                this.handleSegEnter, this.handleSegLeave);
        }
        destroy() {
            this.removeHoverListeners();
        }
        triggerEvent(publicEvName, ev, segEl) {
            let {
                component
            } = this;
            let {
                context
            } = component;
            let seg = getElSeg(segEl);
            if (!ev || component.isValidSegDownEl(ev.target)) {
                context.emitter.trigger(publicEvName, {
                    el: segEl,
                    event: new EventImpl(context, seg.eventRange.def, seg.eventRange.instance),
                    jsEvent: ev,
                    view: context.viewApi,
                });
            }
        }
    }

    class CalendarContent extends PureComponent {
        constructor() {
            super(...arguments);
            this.buildViewContext = memoize(buildViewContext);
            this.buildViewPropTransformers = memoize(buildViewPropTransformers);
            this.buildToolbarProps = memoize(buildToolbarProps);
            this.headerRef = d();
            this.footerRef = d();
            this.interactionsStore = {};
            // eslint-disable-next-line
            this.state = {
                viewLabelId: getUniqueDomId(),
            };
            // Component Registration
            // -----------------------------------------------------------------------------------------------------------------
            this.registerInteractiveComponent = (component, settingsInput) => {
                let settings = parseInteractionSettings(component, settingsInput);
                let DEFAULT_INTERACTIONS = [
                    EventClicking,
                    EventHovering,
                ];
                let interactionClasses = DEFAULT_INTERACTIONS.concat(this.props.pluginHooks.componentInteractions);
                let interactions = interactionClasses.map((TheInteractionClass) => new TheInteractionClass(settings));
                this.interactionsStore[component.uid] = interactions;
                interactionSettingsStore[component.uid] = settings;
            };
            this.unregisterInteractiveComponent = (component) => {
                let listeners = this.interactionsStore[component.uid];
                if (listeners) {
                    for (let listener of listeners) {
                        listener.destroy();
                    }
                    delete this.interactionsStore[component.uid];
                }
                delete interactionSettingsStore[component.uid];
            };
            // Resizing
            // -----------------------------------------------------------------------------------------------------------------
            this.resizeRunner = new DelayedRunner(() => {
                this.props.emitter.trigger('_resize', true); // should window resizes be considered "forced" ?
                this.props.emitter.trigger('windowResize', {
                    view: this.props.viewApi
                });
            });
            this.handleWindowResize = (ev) => {
                let {
                    options
                } = this.props;
                if (options.handleWindowResize &&
                    ev.target === window // avoid jqui events
                ) {
                    this.resizeRunner.request(options.windowResizeDelay);
                }
            };
        }
        /*
        renders INSIDE of an outer div
        */
        render() {
            let {
                props
            } = this;
            let {
                toolbarConfig,
                options
            } = props;
            let viewVGrow = false;
            let viewHeight = '';
            let viewAspectRatio;
            if (props.isHeightAuto || props.forPrint) {
                viewHeight = '';
            } else if (options.height != null) {
                viewVGrow = true;
            } else if (options.contentHeight != null) {
                viewHeight = options.contentHeight;
            } else {
                viewAspectRatio = Math.max(options.aspectRatio, 0.5); // prevent from getting too tall
            }
            let viewContext = this.buildViewContext(props.viewSpec, props.viewApi, props.options, props.dateProfileGenerator, props.dateEnv, props.nowManager, props.theme, props.pluginHooks, props.dispatch, props.getCurrentData, props.emitter, props.calendarApi, this.registerInteractiveComponent, this.unregisterInteractiveComponent);
            let viewLabelId = (toolbarConfig.header && toolbarConfig.header.hasTitle) ?
                this.state.viewLabelId :
                undefined;
            return (y(ViewContextType.Provider, {
                    value: viewContext
                },
                y(NowTimer, {
                    unit: "day"
                }, (nowDate) => {
                    let toolbarProps = this.buildToolbarProps(props.viewSpec, props.dateProfile, props.dateProfileGenerator, props.currentDate, nowDate, props.viewTitle);
                    return (y(_, null,
                        toolbarConfig.header && (y(Toolbar, Object.assign({
                            ref: this.headerRef,
                            extraClassName: "fc-header-toolbar",
                            model: toolbarConfig.header,
                            titleId: viewLabelId
                        }, toolbarProps))),
                        y(ViewHarness, {
                                liquid: viewVGrow,
                                height: viewHeight,
                                aspectRatio: viewAspectRatio,
                                labeledById: viewLabelId
                            },
                            this.renderView(props),
                            this.buildAppendContent()),
                        toolbarConfig.footer && (y(Toolbar, Object.assign({
                            ref: this.footerRef,
                            extraClassName: "fc-footer-toolbar",
                            model: toolbarConfig.footer,
                            titleId: ""
                        }, toolbarProps)))));
                })));
        }
        componentDidMount() {
            let {
                props
            } = this;
            this.calendarInteractions = props.pluginHooks.calendarInteractions
                .map((CalendarInteractionClass) => new CalendarInteractionClass(props));
            window.addEventListener('resize', this.handleWindowResize);
            let {
                propSetHandlers
            } = props.pluginHooks;
            for (let propName in propSetHandlers) {
                propSetHandlers[propName](props[propName], props);
            }
        }
        componentDidUpdate(prevProps) {
            let {
                props
            } = this;
            let {
                propSetHandlers
            } = props.pluginHooks;
            for (let propName in propSetHandlers) {
                if (props[propName] !== prevProps[propName]) {
                    propSetHandlers[propName](props[propName], props);
                }
            }
        }
        componentWillUnmount() {
            window.removeEventListener('resize', this.handleWindowResize);
            this.resizeRunner.clear();
            for (let interaction of this.calendarInteractions) {
                interaction.destroy();
            }
            this.props.emitter.trigger('_unmount');
        }
        buildAppendContent() {
            let {
                props
            } = this;
            let children = props.pluginHooks.viewContainerAppends.map((buildAppendContent) => buildAppendContent(props));
            return y(_, {}, ...children);
        }
        renderView(props) {
            let {
                pluginHooks
            } = props;
            let {
                viewSpec
            } = props;
            let viewProps = {
                dateProfile: props.dateProfile,
                businessHours: props.businessHours,
                eventStore: props.renderableEventStore,
                eventUiBases: props.eventUiBases,
                dateSelection: props.dateSelection,
                eventSelection: props.eventSelection,
                eventDrag: props.eventDrag,
                eventResize: props.eventResize,
                isHeightAuto: props.isHeightAuto,
                forPrint: props.forPrint,
            };
            let transformers = this.buildViewPropTransformers(pluginHooks.viewPropsTransformers);
            for (let transformer of transformers) {
                Object.assign(viewProps, transformer.transform(viewProps, props));
            }
            let ViewComponent = viewSpec.component;
            return (y(ViewComponent, Object.assign({}, viewProps)));
        }
    }

    function buildToolbarProps(viewSpec, dateProfile, dateProfileGenerator, currentDate, now, title) {
        // don't force any date-profiles to valid date profiles (the `false`) so that we can tell if it's invalid
        let todayInfo = dateProfileGenerator.build(now, undefined, false); // TODO: need `undefined` or else INFINITE LOOP for some reason
        let prevInfo = dateProfileGenerator.buildPrev(dateProfile, currentDate, false);
        let nextInfo = dateProfileGenerator.buildNext(dateProfile, currentDate, false);
        return {
            title,
            activeButton: viewSpec.type,
            navUnit: viewSpec.singleUnit,
            isTodayEnabled: todayInfo.isValid && !rangeContainsMarker(dateProfile.currentRange, now),
            isPrevEnabled: prevInfo.isValid,
            isNextEnabled: nextInfo.isValid,
        };
    }
    // Plugin
    // -----------------------------------------------------------------------------------------------------------------
    function buildViewPropTransformers(theClasses) {
        return theClasses.map((TheClass) => new TheClass());
    }

    class Calendar extends CalendarImpl {
        constructor(el, optionOverrides = {}) {
            super();
            this.isRendering = false;
            this.isRendered = false;
            this.currentClassNames = [];
            this.customContentRenderId = 0;
            this.handleAction = (action) => {
                // actions we know we want to render immediately
                switch (action.type) {
                    case 'SET_EVENT_DRAG':
                    case 'SET_EVENT_RESIZE':
                        this.renderRunner.tryDrain();
                }
            };
            this.handleData = (data) => {
                this.currentData = data;
                this.renderRunner.request(data.calendarOptions.rerenderDelay);
            };
            this.handleRenderRequest = () => {
                if (this.isRendering) {
                    this.isRendered = true;
                    let {
                        currentData
                    } = this;
                    flushSync(() => {
                        D$1(y(CalendarRoot, {
                            options: currentData.calendarOptions,
                            theme: currentData.theme,
                            emitter: currentData.emitter
                        }, (classNames, height, isHeightAuto, forPrint) => {
                            this.setClassNames(classNames);
                            this.setHeight(height);
                            return (y(RenderId.Provider, {
                                    value: this.customContentRenderId
                                },
                                y(CalendarContent, Object.assign({
                                    isHeightAuto: isHeightAuto,
                                    forPrint: forPrint
                                }, currentData))));
                        }), this.el);
                    });
                } else if (this.isRendered) {
                    this.isRendered = false;
                    D$1(null, this.el);
                    this.setClassNames([]);
                    this.setHeight('');
                }
            };
            ensureElHasStyles(el);
            this.el = el;
            this.renderRunner = new DelayedRunner(this.handleRenderRequest);
            new CalendarDataManager({
                optionOverrides,
                calendarApi: this,
                onAction: this.handleAction,
                onData: this.handleData,
            });
        }
        render() {
            let wasRendering = this.isRendering;
            if (!wasRendering) {
                this.isRendering = true;
            } else {
                this.customContentRenderId += 1;
            }
            this.renderRunner.request();
            if (wasRendering) {
                this.updateSize();
            }
        }
        destroy() {
            if (this.isRendering) {
                this.isRendering = false;
                this.renderRunner.request();
            }
        }
        updateSize() {
            flushSync(() => {
                super.updateSize();
            });
        }
        batchRendering(func) {
            this.renderRunner.pause('batchRendering');
            func();
            this.renderRunner.resume('batchRendering');
        }
        pauseRendering() {
            this.renderRunner.pause('pauseRendering');
        }
        resumeRendering() {
            this.renderRunner.resume('pauseRendering', true);
        }
        resetOptions(optionOverrides, changedOptionNames) {
            this.currentDataManager.resetOptions(optionOverrides, changedOptionNames);
        }
        setClassNames(classNames) {
            if (!isArraysEqual(classNames, this.currentClassNames)) {
                let {
                    classList
                } = this.el;
                for (let className of this.currentClassNames) {
                    classList.remove(className);
                }
                for (let className of classNames) {
                    classList.add(className);
                }
                this.currentClassNames = classNames;
            }
        }
        setHeight(height) {
            applyStyleProp(this.el, 'height', height);
        }
    }

    function formatDate(dateInput, options = {}) {
        let dateEnv = buildDateEnv(options);
        let formatter = createFormatter(options);
        let dateMeta = dateEnv.createMarkerMeta(dateInput);
        if (!dateMeta) { // TODO: warning?
            return '';
        }
        return dateEnv.format(dateMeta.marker, formatter, {
            forcedTzo: dateMeta.forcedTzo,
        });
    }

    function formatRange(startInput, endInput, options) {
        let dateEnv = buildDateEnv(typeof options === 'object' && options ? options : {}); // pass in if non-null object
        let formatter = createFormatter(options);
        let startMeta = dateEnv.createMarkerMeta(startInput);
        let endMeta = dateEnv.createMarkerMeta(endInput);
        if (!startMeta || !endMeta) { // TODO: warning?
            return '';
        }
        return dateEnv.formatRange(startMeta.marker, endMeta.marker, formatter, {
            forcedStartTzo: startMeta.forcedTzo,
            forcedEndTzo: endMeta.forcedTzo,
            isEndExclusive: options.isEndExclusive,
            defaultSeparator: BASE_OPTION_DEFAULTS.defaultRangeSeparator,
        });
    }
    // TODO: more DRY and optimized
    function buildDateEnv(settings) {
        let locale = buildLocale(settings.locale || 'en', organizeRawLocales([]).map); // TODO: don't hardcode 'en' everywhere
        return new DateEnv(Object.assign(Object.assign({
            timeZone: BASE_OPTION_DEFAULTS.timeZone,
            calendarSystem: 'gregory'
        }, settings), {
            locale
        }));
    }

    // HELPERS
    /*
    if nextDayThreshold is specified, slicing is done in an all-day fashion.
    you can get nextDayThreshold from context.nextDayThreshold
    */
    function sliceEvents(props, allDay) {
        return sliceEventStore(props.eventStore, props.eventUiBases, props.dateProfile.activeRange, allDay ? props.nextDayThreshold : null).fg;
    }

    const version = '6.1.21';

    config.touchMouseIgnoreWait = 500;
    let ignoreMouseDepth = 0;
    let listenerCnt = 0;
    let isWindowTouchMoveCancelled = false;
    /*
    Uses a "pointer" abstraction, which monitors UI events for both mouse and touch.
    Tracks when the pointer "drags" on a certain element, meaning down+move+up.

    Also, tracks if there was touch-scrolling.
    Also, can prevent touch-scrolling from happening.
    Also, can fire pointermove events when scrolling happens underneath, even when no real pointer movement.

    emits:
    - pointerdown
    - pointermove
    - pointerup
    */
    class PointerDragging {
        constructor(containerEl) {
            this.subjectEl = null;
            // options that can be directly assigned by caller
            this.selector = ''; // will cause subjectEl in all emitted events to be this element
            this.handleSelector = '';
            this.shouldIgnoreMove = false;
            this.shouldWatchScroll = true; // for simulating pointermove on scroll
            // internal states
            this.isDragging = false;
            this.isTouchDragging = false;
            this.wasTouchScroll = false;
            // Mouse
            // ----------------------------------------------------------------------------------------------------
            this.handleMouseDown = (ev) => {
                if (!this.shouldIgnoreMouse() &&
                    isPrimaryMouseButton(ev) &&
                    this.tryStart(ev)) {
                    let pev = this.createEventFromMouse(ev, true);
                    this.emitter.trigger('pointerdown', pev);
                    this.initScrollWatch(pev);
                    if (!this.shouldIgnoreMove) {
                        document.addEventListener('mousemove', this.handleMouseMove);
                    }
                    document.addEventListener('mouseup', this.handleMouseUp);
                }
            };
            this.handleMouseMove = (ev) => {
                let pev = this.createEventFromMouse(ev);
                this.recordCoords(pev);
                this.emitter.trigger('pointermove', pev);
            };
            this.handleMouseUp = (ev) => {
                document.removeEventListener('mousemove', this.handleMouseMove);
                document.removeEventListener('mouseup', this.handleMouseUp);
                this.emitter.trigger('pointerup', this.createEventFromMouse(ev));
                this.cleanup(); // call last so that pointerup has access to props
            };
            // Touch
            // ----------------------------------------------------------------------------------------------------
            this.handleTouchStart = (ev) => {
                if (this.tryStart(ev)) {
                    this.isTouchDragging = true;
                    let pev = this.createEventFromTouch(ev, true);
                    this.emitter.trigger('pointerdown', pev);
                    this.initScrollWatch(pev);
                    // unlike mouse, need to attach to target, not document
                    // https://stackoverflow.com/a/45760014
                    let targetEl = ev.target;
                    if (!this.shouldIgnoreMove) {
                        targetEl.addEventListener('touchmove', this.handleTouchMove);
                    }
                    targetEl.addEventListener('touchend', this.handleTouchEnd);
                    targetEl.addEventListener('touchcancel', this.handleTouchEnd); // treat it as a touch end
                    // attach a handler to get called when ANY scroll action happens on the page.
                    // this was impossible to do with normal on/off because 'scroll' doesn't bubble.
                    // http://stackoverflow.com/a/32954565/96342
                    window.addEventListener('scroll', this.handleTouchScroll, true);
                }
            };
            this.handleTouchMove = (ev) => {
                let pev = this.createEventFromTouch(ev);
                this.recordCoords(pev);
                this.emitter.trigger('pointermove', pev);
            };
            this.handleTouchEnd = (ev) => {
                if (this.isDragging) { // done to guard against touchend followed by touchcancel
                    let targetEl = ev.target;
                    targetEl.removeEventListener('touchmove', this.handleTouchMove);
                    targetEl.removeEventListener('touchend', this.handleTouchEnd);
                    targetEl.removeEventListener('touchcancel', this.handleTouchEnd);
                    window.removeEventListener('scroll', this.handleTouchScroll, true); // useCaptured=true
                    this.emitter.trigger('pointerup', this.createEventFromTouch(ev));
                    this.cleanup(); // call last so that pointerup has access to props
                    this.isTouchDragging = false;
                    startIgnoringMouse();
                }
            };
            this.handleTouchScroll = () => {
                this.wasTouchScroll = true;
            };
            this.handleScroll = (ev) => {
                if (!this.shouldIgnoreMove) {
                    let pageX = (window.scrollX - this.prevScrollX) + this.prevPageX;
                    let pageY = (window.scrollY - this.prevScrollY) + this.prevPageY;
                    this.emitter.trigger('pointermove', {
                        origEvent: ev,
                        isTouch: this.isTouchDragging,
                        subjectEl: this.subjectEl,
                        pageX,
                        pageY,
                        deltaX: pageX - this.origPageX,
                        deltaY: pageY - this.origPageY,
                    });
                }
            };
            this.containerEl = containerEl;
            this.emitter = new Emitter();
            containerEl.addEventListener('mousedown', this.handleMouseDown);
            containerEl.addEventListener('touchstart', this.handleTouchStart, {
                passive: true
            });
            listenerCreated();
        }
        destroy() {
            this.containerEl.removeEventListener('mousedown', this.handleMouseDown);
            this.containerEl.removeEventListener('touchstart', this.handleTouchStart, {
                passive: true
            });
            listenerDestroyed();
        }
        tryStart(ev) {
            let subjectEl = this.querySubjectEl(ev);
            let downEl = ev.target;
            if (subjectEl &&
                (!this.handleSelector || elementClosest(downEl, this.handleSelector))) {
                this.subjectEl = subjectEl;
                this.isDragging = true; // do this first so cancelTouchScroll will work
                this.wasTouchScroll = false;
                return true;
            }
            return false;
        }
        cleanup() {
            isWindowTouchMoveCancelled = false;
            this.isDragging = false;
            this.subjectEl = null;
            // keep wasTouchScroll around for later access
            this.destroyScrollWatch();
        }
        querySubjectEl(ev) {
            if (this.selector) {
                return elementClosest(ev.target, this.selector);
            }
            return this.containerEl;
        }
        shouldIgnoreMouse() {
            return ignoreMouseDepth || this.isTouchDragging;
        }
        // can be called by user of this class, to cancel touch-based scrolling for the current drag
        cancelTouchScroll() {
            if (this.isDragging) {
                isWindowTouchMoveCancelled = true;
            }
        }
        // Scrolling that simulates pointermoves
        // ----------------------------------------------------------------------------------------------------
        initScrollWatch(ev) {
            if (this.shouldWatchScroll) {
                this.recordCoords(ev);
                window.addEventListener('scroll', this.handleScroll, true); // useCapture=true
            }
        }
        recordCoords(ev) {
            if (this.shouldWatchScroll) {
                this.prevPageX = ev.pageX;
                this.prevPageY = ev.pageY;
                this.prevScrollX = window.scrollX;
                this.prevScrollY = window.scrollY;
            }
        }
        destroyScrollWatch() {
            if (this.shouldWatchScroll) {
                window.removeEventListener('scroll', this.handleScroll, true); // useCaptured=true
            }
        }
        // Event Normalization
        // ----------------------------------------------------------------------------------------------------
        createEventFromMouse(ev, isFirst) {
            let deltaX = 0;
            let deltaY = 0;
            // TODO: repeat code
            if (isFirst) {
                this.origPageX = ev.pageX;
                this.origPageY = ev.pageY;
            } else {
                deltaX = ev.pageX - this.origPageX;
                deltaY = ev.pageY - this.origPageY;
            }
            return {
                origEvent: ev,
                isTouch: false,
                subjectEl: this.subjectEl,
                pageX: ev.pageX,
                pageY: ev.pageY,
                deltaX,
                deltaY,
            };
        }
        createEventFromTouch(ev, isFirst) {
            let touches = ev.touches;
            let pageX;
            let pageY;
            let deltaX = 0;
            let deltaY = 0;
            // if touch coords available, prefer,
            // because FF would give bad ev.pageX ev.pageY
            if (touches && touches.length) {
                pageX = touches[0].pageX;
                pageY = touches[0].pageY;
            } else {
                pageX = ev.pageX;
                pageY = ev.pageY;
            }
            // TODO: repeat code
            if (isFirst) {
                this.origPageX = pageX;
                this.origPageY = pageY;
            } else {
                deltaX = pageX - this.origPageX;
                deltaY = pageY - this.origPageY;
            }
            return {
                origEvent: ev,
                isTouch: true,
                subjectEl: this.subjectEl,
                pageX,
                pageY,
                deltaX,
                deltaY,
            };
        }
    }
    // Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
    function isPrimaryMouseButton(ev) {
        return ev.button === 0 && !ev.ctrlKey;
    }
    // Ignoring fake mouse events generated by touch
    // ----------------------------------------------------------------------------------------------------
    function startIgnoringMouse() {
        ignoreMouseDepth += 1;
        setTimeout(() => {
            ignoreMouseDepth -= 1;
        }, config.touchMouseIgnoreWait);
    }
    // We want to attach touchmove as early as possible for Safari
    // ----------------------------------------------------------------------------------------------------
    function listenerCreated() {
        listenerCnt += 1;
        if (listenerCnt === 1) {
            window.addEventListener('touchmove', onWindowTouchMove, {
                passive: false
            });
        }
    }

    function listenerDestroyed() {
        listenerCnt -= 1;
        if (!listenerCnt) {
            window.removeEventListener('touchmove', onWindowTouchMove, {
                passive: false
            });
        }
    }

    function onWindowTouchMove(ev) {
        if (isWindowTouchMoveCancelled) {
            ev.preventDefault();
        }
    }

    /*
    An effect in which an element follows the movement of a pointer across the screen.
    The moving element is a clone of some other element.
    Must call start + handleMove + stop.
    */
    class ElementMirror {
        constructor() {
            this.isVisible = false; // must be explicitly enabled
            this.sourceEl = null;
            this.mirrorEl = null;
            this.sourceElRect = null; // screen coords relative to viewport
            // options that can be set directly by caller
            this.parentNode = document.body; // HIGHLY SUGGESTED to set this to sidestep ShadowDOM issues
            this.zIndex = 9999;
            this.revertDuration = 0;
        }
        start(sourceEl, pageX, pageY) {
            this.sourceEl = sourceEl;
            this.sourceElRect = this.sourceEl.getBoundingClientRect();
            this.origScreenX = pageX - window.scrollX;
            this.origScreenY = pageY - window.scrollY;
            this.deltaX = 0;
            this.deltaY = 0;
            this.updateElPosition();
        }
        handleMove(pageX, pageY) {
            this.deltaX = (pageX - window.scrollX) - this.origScreenX;
            this.deltaY = (pageY - window.scrollY) - this.origScreenY;
            this.updateElPosition();
        }
        // can be called before start
        setIsVisible(bool) {
            if (bool) {
                if (!this.isVisible) {
                    if (this.mirrorEl) {
                        this.mirrorEl.style.display = '';
                    }
                    this.isVisible = bool; // needs to happen before updateElPosition
                    this.updateElPosition(); // because was not updating the position while invisible
                }
            } else if (this.isVisible) {
                if (this.mirrorEl) {
                    this.mirrorEl.style.display = 'none';
                }
                this.isVisible = bool;
            }
        }
        // always async
        stop(needsRevertAnimation, callback) {
            let done = () => {
                this.cleanup();
                callback();
            };
            if (needsRevertAnimation &&
                this.mirrorEl &&
                this.isVisible &&
                this.revertDuration && // if 0, transition won't work
                (this.deltaX || this.deltaY) // if same coords, transition won't work
            ) {
                this.doRevertAnimation(done, this.revertDuration);
            } else {
                setTimeout(done, 0);
            }
        }
        doRevertAnimation(callback, revertDuration) {
            let mirrorEl = this.mirrorEl;
            let finalSourceElRect = this.sourceEl.getBoundingClientRect(); // because autoscrolling might have happened
            mirrorEl.style.transition =
                'top ' + revertDuration + 'ms,' +
                'left ' + revertDuration + 'ms';
            applyStyle(mirrorEl, {
                left: finalSourceElRect.left,
                top: finalSourceElRect.top,
            });
            whenTransitionDone(mirrorEl, () => {
                mirrorEl.style.transition = '';
                callback();
            });
        }
        cleanup() {
            if (this.mirrorEl) {
                removeElement(this.mirrorEl);
                this.mirrorEl = null;
            }
            this.sourceEl = null;
        }
        updateElPosition() {
            if (this.sourceEl && this.isVisible) {
                applyStyle(this.getMirrorEl(), {
                    left: this.sourceElRect.left + this.deltaX,
                    top: this.sourceElRect.top + this.deltaY,
                });
            }
        }
        getMirrorEl() {
            let sourceElRect = this.sourceElRect;
            let mirrorEl = this.mirrorEl;
            if (!mirrorEl) {
                mirrorEl = this.mirrorEl = this.sourceEl.cloneNode(true); // cloneChildren=true
                // we don't want long taps or any mouse interaction causing selection/menus.
                // would use preventSelection(), but that prevents selectstart, causing problems.
                mirrorEl.style.userSelect = 'none';
                mirrorEl.style.webkitUserSelect = 'none';
                mirrorEl.style.pointerEvents = 'none';
                mirrorEl.classList.add('fc-event-dragging');
                applyStyle(mirrorEl, {
                    position: 'fixed',
                    zIndex: this.zIndex,
                    visibility: '',
                    boxSizing: 'border-box',
                    width: sourceElRect.right - sourceElRect.left,
                    height: sourceElRect.bottom - sourceElRect.top,
                    right: 'auto',
                    bottom: 'auto',
                    margin: 0,
                });
                this.parentNode.appendChild(mirrorEl);
            }
            return mirrorEl;
        }
    }

    /*
    Is a cache for a given element's scroll information (all the info that ScrollController stores)
    in addition the "client rectangle" of the element.. the area within the scrollbars.

    The cache can be in one of two modes:
    - doesListening:false - ignores when the container is scrolled by someone else
    - doesListening:true - watch for scrolling and update the cache
    */
    class ScrollGeomCache extends ScrollController {
        constructor(scrollController, doesListening) {
            super();
            this.handleScroll = () => {
                this.scrollTop = this.scrollController.getScrollTop();
                this.scrollLeft = this.scrollController.getScrollLeft();
                this.handleScrollChange();
            };
            this.scrollController = scrollController;
            this.doesListening = doesListening;
            this.scrollTop = this.origScrollTop = scrollController.getScrollTop();
            this.scrollLeft = this.origScrollLeft = scrollController.getScrollLeft();
            this.scrollWidth = scrollController.getScrollWidth();
            this.scrollHeight = scrollController.getScrollHeight();
            this.clientWidth = scrollController.getClientWidth();
            this.clientHeight = scrollController.getClientHeight();
            this.clientRect = this.computeClientRect(); // do last in case it needs cached values
            if (this.doesListening) {
                this.getEventTarget().addEventListener('scroll', this.handleScroll);
            }
        }
        destroy() {
            if (this.doesListening) {
                this.getEventTarget().removeEventListener('scroll', this.handleScroll);
            }
        }
        getScrollTop() {
            return this.scrollTop;
        }
        getScrollLeft() {
            return this.scrollLeft;
        }
        setScrollTop(top) {
            this.scrollController.setScrollTop(top);
            if (!this.doesListening) {
                // we are not relying on the element to normalize out-of-bounds scroll values
                // so we need to sanitize ourselves
                this.scrollTop = Math.max(Math.min(top, this.getMaxScrollTop()), 0);
                this.handleScrollChange();
            }
        }
        setScrollLeft(top) {
            this.scrollController.setScrollLeft(top);
            if (!this.doesListening) {
                // we are not relying on the element to normalize out-of-bounds scroll values
                // so we need to sanitize ourselves
                this.scrollLeft = Math.max(Math.min(top, this.getMaxScrollLeft()), 0);
                this.handleScrollChange();
            }
        }
        getClientWidth() {
            return this.clientWidth;
        }
        getClientHeight() {
            return this.clientHeight;
        }
        getScrollWidth() {
            return this.scrollWidth;
        }
        getScrollHeight() {
            return this.scrollHeight;
        }
        handleScrollChange() {}
    }

    class ElementScrollGeomCache extends ScrollGeomCache {
        constructor(el, doesListening) {
            super(new ElementScrollController(el), doesListening);
        }
        getEventTarget() {
            return this.scrollController.el;
        }
        computeClientRect() {
            return computeInnerRect(this.scrollController.el);
        }
    }

    class WindowScrollGeomCache extends ScrollGeomCache {
        constructor(doesListening) {
            super(new WindowScrollController(), doesListening);
        }
        getEventTarget() {
            return window;
        }
        computeClientRect() {
            return {
                left: this.scrollLeft,
                right: this.scrollLeft + this.clientWidth,
                top: this.scrollTop,
                bottom: this.scrollTop + this.clientHeight,
            };
        }
        // the window is the only scroll object that changes it's rectangle relative
        // to the document's topleft as it scrolls
        handleScrollChange() {
            this.clientRect = this.computeClientRect();
        }
    }

    // If available we are using native "performance" API instead of "Date"
    // Read more about it on MDN:
    // https://developer.mozilla.org/en-US/docs/Web/API/Performance
    const getTime = typeof performance === 'function' ? performance.now : Date.now;
    /*
    For a pointer interaction, automatically scrolls certain scroll containers when the pointer
    approaches the edge.

    The caller must call start + handleMove + stop.
    */
    class AutoScroller {
        constructor() {
            // options that can be set by caller
            this.isEnabled = true;
            this.scrollQuery = [window, '.fc-scroller'];
            this.edgeThreshold = 50; // pixels
            this.maxVelocity = 300; // pixels per second
            // internal state
            this.pointerScreenX = null;
            this.pointerScreenY = null;
            this.isAnimating = false;
            this.scrollCaches = null;
            // protect against the initial pointerdown being too close to an edge and starting the scroll
            this.everMovedUp = false;
            this.everMovedDown = false;
            this.everMovedLeft = false;
            this.everMovedRight = false;
            this.animate = () => {
                if (this.isAnimating) { // wasn't cancelled between animation calls
                    let edge = this.computeBestEdge(this.pointerScreenX + window.scrollX, this.pointerScreenY + window.scrollY);
                    if (edge) {
                        let now = getTime();
                        this.handleSide(edge, (now - this.msSinceRequest) / 1000);
                        this.requestAnimation(now);
                    } else {
                        this.isAnimating = false; // will stop animation
                    }
                }
            };
        }
        start(pageX, pageY, scrollStartEl) {
            if (this.isEnabled) {
                this.scrollCaches = this.buildCaches(scrollStartEl);
                this.pointerScreenX = null;
                this.pointerScreenY = null;
                this.everMovedUp = false;
                this.everMovedDown = false;
                this.everMovedLeft = false;
                this.everMovedRight = false;
                this.handleMove(pageX, pageY);
            }
        }
        handleMove(pageX, pageY) {
            if (this.isEnabled) {
                let pointerScreenX = pageX - window.scrollX;
                let pointerScreenY = pageY - window.scrollY;
                let yDelta = this.pointerScreenY === null ? 0 : pointerScreenY - this.pointerScreenY;
                let xDelta = this.pointerScreenX === null ? 0 : pointerScreenX - this.pointerScreenX;
                if (yDelta < 0) {
                    this.everMovedUp = true;
                } else if (yDelta > 0) {
                    this.everMovedDown = true;
                }
                if (xDelta < 0) {
                    this.everMovedLeft = true;
                } else if (xDelta > 0) {
                    this.everMovedRight = true;
                }
                this.pointerScreenX = pointerScreenX;
                this.pointerScreenY = pointerScreenY;
                if (!this.isAnimating) {
                    this.isAnimating = true;
                    this.requestAnimation(getTime());
                }
            }
        }
        stop() {
            if (this.isEnabled) {
                this.isAnimating = false; // will stop animation
                for (let scrollCache of this.scrollCaches) {
                    scrollCache.destroy();
                }
                this.scrollCaches = null;
            }
        }
        requestAnimation(now) {
            this.msSinceRequest = now;
            requestAnimationFrame(this.animate);
        }
        handleSide(edge, seconds) {
            let {
                scrollCache
            } = edge;
            let {
                edgeThreshold
            } = this;
            let invDistance = edgeThreshold - edge.distance;
            let velocity = // the closer to the edge, the faster we scroll
                ((invDistance * invDistance) / (edgeThreshold * edgeThreshold)) * // quadratic
                this.maxVelocity * seconds;
            let sign = 1;
            switch (edge.name) {
                case 'left':
                    sign = -1;
                    // falls through
                case 'right':
                    scrollCache.setScrollLeft(scrollCache.getScrollLeft() + velocity * sign);
                    break;
                case 'top':
                    sign = -1;
                    // falls through
                case 'bottom':
                    scrollCache.setScrollTop(scrollCache.getScrollTop() + velocity * sign);
                    break;
            }
        }
        // left/top are relative to document topleft
        computeBestEdge(left, top) {
            let {
                edgeThreshold
            } = this;
            let bestSide = null;
            let scrollCaches = this.scrollCaches || [];
            for (let scrollCache of scrollCaches) {
                let rect = scrollCache.clientRect;
                let leftDist = left - rect.left;
                let rightDist = rect.right - left;
                let topDist = top - rect.top;
                let bottomDist = rect.bottom - top;
                // completely within the rect?
                if (leftDist >= 0 && rightDist >= 0 && topDist >= 0 && bottomDist >= 0) {
                    if (topDist <= edgeThreshold && this.everMovedUp && scrollCache.canScrollUp() &&
                        (!bestSide || bestSide.distance > topDist)) {
                        bestSide = {
                            scrollCache,
                            name: 'top',
                            distance: topDist
                        };
                    }
                    if (bottomDist <= edgeThreshold && this.everMovedDown && scrollCache.canScrollDown() &&
                        (!bestSide || bestSide.distance > bottomDist)) {
                        bestSide = {
                            scrollCache,
                            name: 'bottom',
                            distance: bottomDist
                        };
                    }
                    /*
                    TODO: fix broken RTL scrolling. canScrollLeft always returning false
                    https://github.com/fullcalendar/fullcalendar/issues/4837
                    */
                    if (leftDist <= edgeThreshold && this.everMovedLeft && scrollCache.canScrollLeft() &&
                        (!bestSide || bestSide.distance > leftDist)) {
                        bestSide = {
                            scrollCache,
                            name: 'left',
                            distance: leftDist
                        };
                    }
                    if (rightDist <= edgeThreshold && this.everMovedRight && scrollCache.canScrollRight() &&
                        (!bestSide || bestSide.distance > rightDist)) {
                        bestSide = {
                            scrollCache,
                            name: 'right',
                            distance: rightDist
                        };
                    }
                }
            }
            return bestSide;
        }
        buildCaches(scrollStartEl) {
            return this.queryScrollEls(scrollStartEl).map((el) => {
                if (el === window) {
                    return new WindowScrollGeomCache(false); // false = don't listen to user-generated scrolls
                }
                return new ElementScrollGeomCache(el, false); // false = don't listen to user-generated scrolls
            });
        }
        queryScrollEls(scrollStartEl) {
            let els = [];
            for (let query of this.scrollQuery) {
                if (typeof query === 'object') {
                    els.push(query);
                } else {
                    /*
                    TODO: in the future, always have auto-scroll happen on element where current Hit came from
                    Ticket: https://github.com/fullcalendar/fullcalendar/issues/4593
                    */
                    els.push(...Array.prototype.slice.call(scrollStartEl.getRootNode().querySelectorAll(query)));
                }
            }
            return els;
        }
    }

    /*
    Monitors dragging on an element. Has a number of high-level features:
    - minimum distance required before dragging
    - minimum wait time ("delay") before dragging
    - a mirror element that follows the pointer
    */
    class FeaturefulElementDragging extends ElementDragging {
        constructor(containerEl, selector) {
            super(containerEl);
            this.containerEl = containerEl;
            // options that can be directly set by caller
            // the caller can also set the PointerDragging's options as well
            this.delay = null;
            this.minDistance = 0;
            this.touchScrollAllowed = true; // prevents drag from starting and blocks scrolling during drag
            this.mirrorNeedsRevert = false;
            this.isInteracting = false; // is the user validly moving the pointer? lasts until pointerup
            this.isDragging = false; // is it INTENTFULLY dragging? lasts until after revert animation
            this.isDelayEnded = false;
            this.isDistanceSurpassed = false;
            this.delayTimeoutId = null;
            this.onPointerDown = (ev) => {
                if (!this.isDragging) { // so new drag doesn't happen while revert animation is going
                    this.isInteracting = true;
                    this.isDelayEnded = false;
                    this.isDistanceSurpassed = false;
                    preventSelection(document.body);
                    preventContextMenu(document.body);
                    // prevent links from being visited if there's an eventual drag.
                    // also prevents selection in older browsers (maybe?).
                    // not necessary for touch, besides, browser would complain about passiveness.
                    if (!ev.isTouch) {
                        ev.origEvent.preventDefault();
                    }
                    this.emitter.trigger('pointerdown', ev);
                    if (this.isInteracting && // not destroyed via pointerdown handler
                        !this.pointer.shouldIgnoreMove) {
                        // actions related to initiating dragstart+dragmove+dragend...
                        this.mirror.setIsVisible(false); // reset. caller must set-visible
                        this.mirror.start(ev.subjectEl, ev.pageX, ev.pageY); // must happen on first pointer down
                        this.startDelay(ev);
                        if (!this.minDistance) {
                            this.handleDistanceSurpassed(ev);
                        }
                    }
                }
            };
            this.onPointerMove = (ev) => {
                if (this.isInteracting) {
                    this.emitter.trigger('pointermove', ev);
                    if (!this.isDistanceSurpassed) {
                        let minDistance = this.minDistance;
                        let distanceSq; // current distance from the origin, squared
                        let {
                            deltaX,
                            deltaY
                        } = ev;
                        distanceSq = deltaX * deltaX + deltaY * deltaY;
                        if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
                            this.handleDistanceSurpassed(ev);
                        }
                    }
                    if (this.isDragging) {
                        // a real pointer move? (not one simulated by scrolling)
                        if (ev.origEvent.type !== 'scroll') {
                            this.mirror.handleMove(ev.pageX, ev.pageY);
                            this.autoScroller.handleMove(ev.pageX, ev.pageY);
                        }
                        this.emitter.trigger('dragmove', ev);
                    }
                }
            };
            this.onPointerUp = (ev) => {
                if (this.isInteracting) {
                    this.isInteracting = false;
                    allowSelection(document.body);
                    allowContextMenu(document.body);
                    this.emitter.trigger('pointerup', ev); // can potentially set mirrorNeedsRevert
                    if (this.isDragging) {
                        this.autoScroller.stop();
                        this.tryStopDrag(ev); // which will stop the mirror
                    }
                    if (this.delayTimeoutId) {
                        clearTimeout(this.delayTimeoutId);
                        this.delayTimeoutId = null;
                    }
                }
            };
            let pointer = this.pointer = new PointerDragging(containerEl);
            pointer.emitter.on('pointerdown', this.onPointerDown);
            pointer.emitter.on('pointermove', this.onPointerMove);
            pointer.emitter.on('pointerup', this.onPointerUp);
            if (selector) {
                pointer.selector = selector;
            }
            this.mirror = new ElementMirror();
            this.autoScroller = new AutoScroller();
        }
        destroy() {
            this.pointer.destroy();
            // HACK: simulate a pointer-up to end the current drag
            // TODO: fire 'dragend' directly and stop interaction. discourage use of pointerup event (b/c might not fire)
            this.onPointerUp({});
        }
        startDelay(ev) {
            if (typeof this.delay === 'number') {
                this.delayTimeoutId = setTimeout(() => {
                    this.delayTimeoutId = null;
                    this.handleDelayEnd(ev);
                }, this.delay); // not assignable to number!
            } else {
                this.handleDelayEnd(ev);
            }
        }
        handleDelayEnd(ev) {
            this.isDelayEnded = true;
            this.tryStartDrag(ev);
        }
        handleDistanceSurpassed(ev) {
            this.isDistanceSurpassed = true;
            this.tryStartDrag(ev);
        }
        tryStartDrag(ev) {
            if (this.isDelayEnded && this.isDistanceSurpassed) {
                if (!this.pointer.wasTouchScroll || this.touchScrollAllowed) {
                    this.isDragging = true;
                    this.mirrorNeedsRevert = false;
                    this.autoScroller.start(ev.pageX, ev.pageY, this.containerEl);
                    this.emitter.trigger('dragstart', ev);
                    if (this.touchScrollAllowed === false) {
                        this.pointer.cancelTouchScroll();
                    }
                }
            }
        }
        tryStopDrag(ev) {
            // .stop() is ALWAYS asynchronous, which we NEED because we want all pointerup events
            // that come from the document to fire beforehand. much more convenient this way.
            this.mirror.stop(this.mirrorNeedsRevert, this.stopDrag.bind(this, ev));
        }
        stopDrag(ev) {
            this.isDragging = false;
            this.emitter.trigger('dragend', ev);
        }
        // fill in the implementations...
        setIgnoreMove(bool) {
            this.pointer.shouldIgnoreMove = bool;
        }
        setMirrorIsVisible(bool) {
            this.mirror.setIsVisible(bool);
        }
        setMirrorNeedsRevert(bool) {
            this.mirrorNeedsRevert = bool;
        }
        setAutoScrollEnabled(bool) {
            this.autoScroller.isEnabled = bool;
        }
    }

    /*
    When this class is instantiated, it records the offset of an element (relative to the document topleft),
    and continues to monitor scrolling, updating the cached coordinates if it needs to.
    Does not access the DOM after instantiation, so highly performant.

    Also keeps track of all scrolling/overflow:hidden containers that are parents of the given element
    and an determine if a given point is inside the combined clipping rectangle.
    */
    class OffsetTracker {
        constructor(el) {
            this.el = el;
            this.origRect = computeRect(el);
            // will work fine for divs that have overflow:hidden
            this.scrollCaches = getClippingParents(el).map((scrollEl) => new ElementScrollGeomCache(scrollEl, true));
        }
        destroy() {
            for (let scrollCache of this.scrollCaches) {
                scrollCache.destroy();
            }
        }
        computeLeft() {
            let left = this.origRect.left;
            for (let scrollCache of this.scrollCaches) {
                left += scrollCache.origScrollLeft - scrollCache.getScrollLeft();
            }
            return left;
        }
        computeTop() {
            let top = this.origRect.top;
            for (let scrollCache of this.scrollCaches) {
                top += scrollCache.origScrollTop - scrollCache.getScrollTop();
            }
            return top;
        }
        isWithinClipping(pageX, pageY) {
            let point = {
                left: pageX,
                top: pageY
            };
            for (let scrollCache of this.scrollCaches) {
                if (!isIgnoredClipping(scrollCache.getEventTarget()) &&
                    !pointInsideRect(point, scrollCache.clientRect)) {
                    return false;
                }
            }
            return true;
        }
    }
    // certain clipping containers should never constrain interactions, like <html> and <body>
    // https://github.com/fullcalendar/fullcalendar/issues/3615
    function isIgnoredClipping(node) {
        let tagName = node.tagName;
        return tagName === 'HTML' || tagName === 'BODY';
    }

    /*
    Tracks movement over multiple droppable areas (aka "hits")
    that exist in one or more DateComponents.
    Relies on an existing draggable.

    emits:
    - pointerdown
    - dragstart
    - hitchange - fires initially, even if not over a hit
    - pointerup
    - (hitchange - again, to null, if ended over a hit)
    - dragend
    */
    class HitDragging {
        constructor(dragging, droppableStore) {
            // options that can be set by caller
            this.useSubjectCenter = false;
            this.requireInitial = true; // if doesn't start out on a hit, won't emit any events
            this.disablePointCheck = false;
            this.initialHit = null;
            this.movingHit = null;
            this.finalHit = null; // won't ever be populated if shouldIgnoreMove
            this.handlePointerDown = (ev) => {
                let {
                    dragging
                } = this;
                this.initialHit = null;
                this.movingHit = null;
                this.finalHit = null;
                this.prepareHits();
                this.processFirstCoord(ev);
                if (this.initialHit || !this.requireInitial) {
                    dragging.setIgnoreMove(false);
                    // TODO: fire this before computing processFirstCoord, so listeners can cancel. this gets fired by almost every handler :(
                    this.emitter.trigger('pointerdown', ev);
                } else {
                    dragging.setIgnoreMove(true);
                }
            };
            this.handleDragStart = (ev) => {
                this.emitter.trigger('dragstart', ev);
                this.handleMove(ev, true); // force = fire even if initially null
            };
            this.handleDragMove = (ev) => {
                this.emitter.trigger('dragmove', ev);
                this.handleMove(ev);
            };
            this.handlePointerUp = (ev) => {
                this.releaseHits();
                this.emitter.trigger('pointerup', ev);
            };
            this.handleDragEnd = (ev) => {
                if (this.movingHit) {
                    this.emitter.trigger('hitupdate', null, true, ev);
                }
                this.finalHit = this.movingHit;
                this.movingHit = null;
                this.emitter.trigger('dragend', ev);
            };
            this.droppableStore = droppableStore;
            dragging.emitter.on('pointerdown', this.handlePointerDown);
            dragging.emitter.on('dragstart', this.handleDragStart);
            dragging.emitter.on('dragmove', this.handleDragMove);
            dragging.emitter.on('pointerup', this.handlePointerUp);
            dragging.emitter.on('dragend', this.handleDragEnd);
            this.dragging = dragging;
            this.emitter = new Emitter();
        }
        // sets initialHit
        // sets coordAdjust
        processFirstCoord(ev) {
            let origPoint = {
                left: ev.pageX,
                top: ev.pageY
            };
            let adjustedPoint = origPoint;
            let subjectEl = ev.subjectEl;
            let subjectRect;
            if (subjectEl instanceof HTMLElement) { // i.e. not a Document/ShadowRoot
                subjectRect = computeRect(subjectEl);
                adjustedPoint = constrainPoint(adjustedPoint, subjectRect);
            }
            let initialHit = this.initialHit = this.queryHitForOffset(adjustedPoint.left, adjustedPoint.top);
            if (initialHit) {
                if (this.useSubjectCenter && subjectRect) {
                    let slicedSubjectRect = intersectRects(subjectRect, initialHit.rect);
                    if (slicedSubjectRect) {
                        adjustedPoint = getRectCenter(slicedSubjectRect);
                    }
                }
                this.coordAdjust = diffPoints(adjustedPoint, origPoint);
            } else {
                this.coordAdjust = {
                    left: 0,
                    top: 0
                };
            }
        }
        handleMove(ev, forceHandle) {
            let hit = this.queryHitForOffset(ev.pageX + this.coordAdjust.left, ev.pageY + this.coordAdjust.top);
            if (forceHandle || !isHitsEqual(this.movingHit, hit)) {
                this.movingHit = hit;
                this.emitter.trigger('hitupdate', hit, false, ev);
            }
        }
        prepareHits() {
            this.offsetTrackers = mapHash(this.droppableStore, (interactionSettings) => {
                interactionSettings.component.prepareHits();
                return new OffsetTracker(interactionSettings.el);
            });
        }
        releaseHits() {
            let {
                offsetTrackers
            } = this;
            for (let id in offsetTrackers) {
                offsetTrackers[id].destroy();
            }
            this.offsetTrackers = {};
        }
        queryHitForOffset(offsetLeft, offsetTop) {
            let {
                droppableStore,
                offsetTrackers
            } = this;
            let bestHit = null;
            for (let id in droppableStore) {
                let component = droppableStore[id].component;
                let offsetTracker = offsetTrackers[id];
                if (offsetTracker && // wasn't destroyed mid-drag
                    offsetTracker.isWithinClipping(offsetLeft, offsetTop)) {
                    let originLeft = offsetTracker.computeLeft();
                    let originTop = offsetTracker.computeTop();
                    let positionLeft = offsetLeft - originLeft;
                    let positionTop = offsetTop - originTop;
                    let {
                        origRect
                    } = offsetTracker;
                    let width = origRect.right - origRect.left;
                    let height = origRect.bottom - origRect.top;
                    if (
                        // must be within the element's bounds
                        positionLeft >= 0 && positionLeft < width &&
                        positionTop >= 0 && positionTop < height) {
                        let hit = component.queryHit(positionLeft, positionTop, width, height);
                        if (hit && (
                                // make sure the hit is within activeRange, meaning it's not a dead cell
                                rangeContainsRange(hit.dateProfile.activeRange, hit.dateSpan.range)) &&
                            // Ensure the component we are querying for the hit is accessibly my the pointer
                            // Prevents obscured calendars (ex: under a modal dialog) from accepting hit
                            // https://github.com/fullcalendar/fullcalendar/issues/5026
                            (this.disablePointCheck ||
                                offsetTracker.el.contains(offsetTracker.el.getRootNode().elementFromPoint(
                                    // add-back origins to get coordinate relative to top-left of window viewport
                                    positionLeft + originLeft - window.scrollX, positionTop + originTop - window.scrollY))) &&
                            (!bestHit || hit.layer > bestHit.layer)) {
                            hit.componentId = id;
                            hit.context = component.context;
                            // TODO: better way to re-orient rectangle
                            hit.rect.left += originLeft;
                            hit.rect.right += originLeft;
                            hit.rect.top += originTop;
                            hit.rect.bottom += originTop;
                            bestHit = hit;
                        }
                    }
                }
            }
            return bestHit;
        }
    }

    function isHitsEqual(hit0, hit1) {
        if (!hit0 && !hit1) {
            return true;
        }
        if (Boolean(hit0) !== Boolean(hit1)) {
            return false;
        }
        return isDateSpansEqual(hit0.dateSpan, hit1.dateSpan);
    }

    function buildDatePointApiWithContext(dateSpan, context) {
        let props = {};
        for (let transform of context.pluginHooks.datePointTransforms) {
            Object.assign(props, transform(dateSpan, context));
        }
        Object.assign(props, buildDatePointApi(dateSpan, context.dateEnv));
        return props;
    }

    function buildDatePointApi(span, dateEnv) {
        return {
            date: dateEnv.toDate(span.range.start),
            dateStr: dateEnv.formatIso(span.range.start, {
                omitTime: span.allDay
            }),
            allDay: span.allDay,
        };
    }

    /*
    Monitors when the user clicks on a specific date/time of a component.
    A pointerdown+pointerup on the same "hit" constitutes a click.
    */
    class DateClicking extends Interaction {
        constructor(settings) {
            super(settings);
            this.handlePointerDown = (pev) => {
                let {
                    dragging
                } = this;
                let downEl = pev.origEvent.target;
                // do this in pointerdown (not dragend) because DOM might be mutated by the time dragend is fired
                dragging.setIgnoreMove(!this.component.isValidDateDownEl(downEl));
            };
            // won't even fire if moving was ignored
            this.handleDragEnd = (ev) => {
                let {
                    component
                } = this;
                let {
                    pointer
                } = this.dragging;
                if (!pointer.wasTouchScroll) {
                    let {
                        initialHit,
                        finalHit
                    } = this.hitDragging;
                    if (initialHit && finalHit && isHitsEqual(initialHit, finalHit)) {
                        let {
                            context
                        } = component;
                        let arg = Object.assign(Object.assign({}, buildDatePointApiWithContext(initialHit.dateSpan, context)), {
                            dayEl: initialHit.dayEl,
                            jsEvent: ev.origEvent,
                            view: context.viewApi || context.calendarApi.view
                        });
                        context.emitter.trigger('dateClick', arg);
                    }
                }
            };
            // we DO want to watch pointer moves because otherwise finalHit won't get populated
            this.dragging = new FeaturefulElementDragging(settings.el);
            this.dragging.autoScroller.isEnabled = false;
            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
            hitDragging.emitter.on('dragend', this.handleDragEnd);
        }
        destroy() {
            this.dragging.destroy();
        }
    }

    /*
    Tracks when the user selects a portion of time of a component,
    constituted by a drag over date cells, with a possible delay at the beginning of the drag.
    */
    class DateSelecting extends Interaction {
        constructor(settings) {
            super(settings);
            this.dragSelection = null;
            this.handlePointerDown = (ev) => {
                let {
                    component,
                    dragging
                } = this;
                let {
                    options
                } = component.context;
                let canSelect = options.selectable &&
                    component.isValidDateDownEl(ev.origEvent.target);
                // don't bother to watch expensive moves if component won't do selection
                dragging.setIgnoreMove(!canSelect);
                // if touch, require user to hold down
                dragging.delay = ev.isTouch ? getComponentTouchDelay$1(component) : null;
            };
            this.handleDragStart = (ev) => {
                this.component.context.calendarApi.unselect(ev); // unselect previous selections
            };
            this.handleHitUpdate = (hit, isFinal) => {
                let {
                    context
                } = this.component;
                let dragSelection = null;
                let isInvalid = false;
                if (hit) {
                    let initialHit = this.hitDragging.initialHit;
                    let disallowed = hit.componentId === initialHit.componentId &&
                        this.isHitComboAllowed &&
                        !this.isHitComboAllowed(initialHit, hit);
                    if (!disallowed) {
                        dragSelection = joinHitsIntoSelection(initialHit, hit, context.pluginHooks.dateSelectionTransformers);
                    }
                    if (!dragSelection || !isDateSelectionValid(dragSelection, hit.dateProfile, context)) {
                        isInvalid = true;
                        dragSelection = null;
                    }
                }
                if (dragSelection) {
                    context.dispatch({
                        type: 'SELECT_DATES',
                        selection: dragSelection
                    });
                } else if (!isFinal) { // only unselect if moved away while dragging
                    context.dispatch({
                        type: 'UNSELECT_DATES'
                    });
                }
                if (!isInvalid) {
                    enableCursor();
                } else {
                    disableCursor();
                }
                if (!isFinal) {
                    this.dragSelection = dragSelection; // only clear if moved away from all hits while dragging
                }
            };
            this.handlePointerUp = (pev) => {
                if (this.dragSelection) {
                    // selection is already rendered, so just need to report selection
                    triggerDateSelect(this.dragSelection, pev, this.component.context);
                    this.dragSelection = null;
                }
            };
            let {
                component
            } = settings;
            let {
                options
            } = component.context;
            let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
            dragging.touchScrollAllowed = false;
            dragging.minDistance = options.selectMinDistance || 0;
            dragging.autoScroller.isEnabled = options.dragScroll;
            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
            hitDragging.emitter.on('dragstart', this.handleDragStart);
            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
            hitDragging.emitter.on('pointerup', this.handlePointerUp);
        }
        destroy() {
            this.dragging.destroy();
        }
    }

    function getComponentTouchDelay$1(component) {
        let {
            options
        } = component.context;
        let delay = options.selectLongPressDelay;
        if (delay == null) {
            delay = options.longPressDelay;
        }
        return delay;
    }

    function joinHitsIntoSelection(hit0, hit1, dateSelectionTransformers) {
        let dateSpan0 = hit0.dateSpan;
        let dateSpan1 = hit1.dateSpan;
        let ms = [
            dateSpan0.range.start,
            dateSpan0.range.end,
            dateSpan1.range.start,
            dateSpan1.range.end,
        ];
        ms.sort(compareNumbers);
        let props = {};
        for (let transformer of dateSelectionTransformers) {
            let res = transformer(hit0, hit1);
            if (res === false) {
                return null;
            }
            if (res) {
                Object.assign(props, res);
            }
        }
        props.range = {
            start: ms[0],
            end: ms[3]
        };
        props.allDay = dateSpan0.allDay;
        return props;
    }

    class EventDragging extends Interaction {
        constructor(settings) {
            super(settings);
            // internal state
            this.subjectEl = null;
            this.subjectSeg = null; // the seg being selected/dragged
            this.isDragging = false;
            this.eventRange = null;
            this.relevantEvents = null; // the events being dragged
            this.receivingContext = null;
            this.validMutation = null;
            this.mutatedRelevantEvents = null;
            this.handlePointerDown = (ev) => {
                let origTarget = ev.origEvent.target;
                let {
                    component,
                    dragging
                } = this;
                let {
                    mirror
                } = dragging;
                let {
                    options
                } = component.context;
                let initialContext = component.context;
                this.subjectEl = ev.subjectEl;
                let subjectSeg = this.subjectSeg = getElSeg(ev.subjectEl);
                let eventRange = this.eventRange = subjectSeg.eventRange;
                let eventInstanceId = eventRange.instance.instanceId;
                this.relevantEvents = getRelevantEvents(initialContext.getCurrentData().eventStore, eventInstanceId);
                dragging.minDistance = ev.isTouch ? 0 : options.eventDragMinDistance;
                dragging.delay =
                    // only do a touch delay if touch and this event hasn't been selected yet
                    (ev.isTouch && eventInstanceId !== component.props.eventSelection) ?
                    getComponentTouchDelay(component) :
                    null;
                if (options.fixedMirrorParent) {
                    mirror.parentNode = options.fixedMirrorParent;
                } else {
                    mirror.parentNode = elementClosest(origTarget, '.fc');
                }
                mirror.revertDuration = options.dragRevertDuration;
                let isValid = component.isValidSegDownEl(origTarget) &&
                    !elementClosest(origTarget, '.fc-event-resizer'); // NOT on a resizer
                dragging.setIgnoreMove(!isValid);
                // disable dragging for elements that are resizable (ie, selectable)
                // but are not draggable
                this.isDragging = isValid &&
                    ev.subjectEl.classList.contains('fc-event-draggable');
            };
            this.handleDragStart = (ev) => {
                let initialContext = this.component.context;
                let eventRange = this.eventRange;
                let eventInstanceId = eventRange.instance.instanceId;
                if (ev.isTouch) {
                    // need to select a different event?
                    if (eventInstanceId !== this.component.props.eventSelection) {
                        initialContext.dispatch({
                            type: 'SELECT_EVENT',
                            eventInstanceId
                        });
                    }
                } else {
                    // if now using mouse, but was previous touch interaction, clear selected event
                    initialContext.dispatch({
                        type: 'UNSELECT_EVENT'
                    });
                }
                if (this.isDragging) {
                    initialContext.calendarApi.unselect(ev); // unselect *date* selection
                    initialContext.emitter.trigger('eventDragStart', {
                        el: this.subjectEl,
                        event: new EventImpl(initialContext, eventRange.def, eventRange.instance),
                        jsEvent: ev.origEvent,
                        view: initialContext.viewApi,
                    });
                }
            };
            this.handleHitUpdate = (hit, isFinal) => {
                if (!this.isDragging) {
                    return;
                }
                let relevantEvents = this.relevantEvents;
                let initialHit = this.hitDragging.initialHit;
                let initialContext = this.component.context;
                // states based on new hit
                let receivingContext = null;
                let mutation = null;
                let mutatedRelevantEvents = null;
                let isInvalid = false;
                let interaction = {
                    affectedEvents: relevantEvents,
                    mutatedEvents: createEmptyEventStore(),
                    isEvent: true,
                };
                if (hit) {
                    receivingContext = hit.context;
                    let receivingOptions = receivingContext.options;
                    if (initialContext === receivingContext ||
                        (receivingOptions.editable && receivingOptions.droppable)) {
                        mutation = computeEventMutation(initialHit, hit, this.eventRange.instance.range.start, receivingContext.getCurrentData().pluginHooks.eventDragMutationMassagers);
                        if (mutation) {
                            mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, receivingContext.getCurrentData().eventUiBases, mutation, receivingContext);
                            interaction.mutatedEvents = mutatedRelevantEvents;
                            if (!isInteractionValid(interaction, hit.dateProfile, receivingContext)) {
                                isInvalid = true;
                                mutation = null;
                                mutatedRelevantEvents = null;
                                interaction.mutatedEvents = createEmptyEventStore();
                            }
                        }
                    } else {
                        receivingContext = null;
                    }
                }
                this.displayDrag(receivingContext, interaction);
                if (!isInvalid) {
                    enableCursor();
                } else {
                    disableCursor();
                }
                if (!isFinal) {
                    if (initialContext === receivingContext && // TODO: write test for this
                        isHitsEqual(initialHit, hit)) {
                        mutation = null;
                    }
                    this.dragging.setMirrorNeedsRevert(!mutation);
                    // render the mirror if no already-rendered mirror
                    // TODO: wish we could somehow wait for dispatch to guarantee render
                    this.dragging.setMirrorIsVisible(!hit || !this.subjectEl.getRootNode().querySelector('.fc-event-mirror'));
                    // assign states based on new hit
                    this.receivingContext = receivingContext;
                    this.validMutation = mutation;
                    this.mutatedRelevantEvents = mutatedRelevantEvents;
                }
            };
            this.handlePointerUp = () => {
                if (!this.isDragging) {
                    this.cleanup(); // because handleDragEnd won't fire
                }
            };
            this.handleDragEnd = (ev) => {
                if (this.isDragging) {
                    let initialContext = this.component.context;
                    let initialView = initialContext.viewApi;
                    let {
                        receivingContext,
                        validMutation
                    } = this;
                    let eventDef = this.eventRange.def;
                    let eventInstance = this.eventRange.instance;
                    let eventApi = new EventImpl(initialContext, eventDef, eventInstance);
                    let relevantEvents = this.relevantEvents;
                    let mutatedRelevantEvents = this.mutatedRelevantEvents;
                    let {
                        finalHit
                    } = this.hitDragging;
                    this.clearDrag(); // must happen after revert animation
                    initialContext.emitter.trigger('eventDragStop', {
                        el: this.subjectEl,
                        event: eventApi,
                        jsEvent: ev.origEvent,
                        view: initialView,
                    });
                    if (validMutation) {
                        // dropped within same calendar
                        if (receivingContext === initialContext) {
                            let updatedEventApi = new EventImpl(initialContext, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
                            initialContext.dispatch({
                                type: 'MERGE_EVENTS',
                                eventStore: mutatedRelevantEvents,
                            });
                            let eventChangeArg = {
                                oldEvent: eventApi,
                                event: updatedEventApi,
                                relatedEvents: buildEventApis(mutatedRelevantEvents, initialContext, eventInstance),
                                revert() {
                                    initialContext.dispatch({
                                        type: 'MERGE_EVENTS',
                                        eventStore: relevantEvents, // the pre-change data
                                    });
                                },
                            };
                            let transformed = {};
                            for (let transformer of initialContext.getCurrentData().pluginHooks.eventDropTransformers) {
                                Object.assign(transformed, transformer(validMutation, initialContext));
                            }
                            initialContext.emitter.trigger('eventDrop', Object.assign(Object.assign(Object.assign({}, eventChangeArg), transformed), {
                                el: ev.subjectEl,
                                delta: validMutation.datesDelta,
                                jsEvent: ev.origEvent,
                                view: initialView
                            }));
                            initialContext.emitter.trigger('eventChange', eventChangeArg);
                            // dropped in different calendar
                        } else if (receivingContext) {
                            let eventRemoveArg = {
                                event: eventApi,
                                relatedEvents: buildEventApis(relevantEvents, initialContext, eventInstance),
                                revert() {
                                    initialContext.dispatch({
                                        type: 'MERGE_EVENTS',
                                        eventStore: relevantEvents,
                                    });
                                },
                            };
                            initialContext.emitter.trigger('eventLeave', Object.assign(Object.assign({}, eventRemoveArg), {
                                draggedEl: ev.subjectEl,
                                view: initialView
                            }));
                            initialContext.dispatch({
                                type: 'REMOVE_EVENTS',
                                eventStore: relevantEvents,
                            });
                            initialContext.emitter.trigger('eventRemove', eventRemoveArg);
                            let addedEventDef = mutatedRelevantEvents.defs[eventDef.defId];
                            let addedEventInstance = mutatedRelevantEvents.instances[eventInstance.instanceId];
                            let addedEventApi = new EventImpl(receivingContext, addedEventDef, addedEventInstance);
                            receivingContext.dispatch({
                                type: 'MERGE_EVENTS',
                                eventStore: mutatedRelevantEvents,
                            });
                            let eventAddArg = {
                                event: addedEventApi,
                                relatedEvents: buildEventApis(mutatedRelevantEvents, receivingContext, addedEventInstance),
                                revert() {
                                    receivingContext.dispatch({
                                        type: 'REMOVE_EVENTS',
                                        eventStore: mutatedRelevantEvents,
                                    });
                                },
                            };
                            receivingContext.emitter.trigger('eventAdd', eventAddArg);
                            if (ev.isTouch) {
                                receivingContext.dispatch({
                                    type: 'SELECT_EVENT',
                                    eventInstanceId: eventInstance.instanceId,
                                });
                            }
                            receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), {
                                draggedEl: ev.subjectEl,
                                jsEvent: ev.origEvent,
                                view: finalHit.context.viewApi
                            }));
                            receivingContext.emitter.trigger('eventReceive', Object.assign(Object.assign({}, eventAddArg), {
                                draggedEl: ev.subjectEl,
                                view: finalHit.context.viewApi
                            }));
                        }
                    } else {
                        initialContext.emitter.trigger('_noEventDrop');
                    }
                }
                this.cleanup();
            };
            let {
                component
            } = this;
            let {
                options
            } = component.context;
            let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
            dragging.pointer.selector = EventDragging.SELECTOR;
            dragging.touchScrollAllowed = false;
            dragging.autoScroller.isEnabled = options.dragScroll;
            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsStore);
            hitDragging.useSubjectCenter = settings.useEventCenter;
            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
            hitDragging.emitter.on('dragstart', this.handleDragStart);
            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
            hitDragging.emitter.on('pointerup', this.handlePointerUp);
            hitDragging.emitter.on('dragend', this.handleDragEnd);
        }
        destroy() {
            this.dragging.destroy();
        }
        // render a drag state on the next receivingCalendar
        displayDrag(nextContext, state) {
            let initialContext = this.component.context;
            let prevContext = this.receivingContext;
            // does the previous calendar need to be cleared?
            if (prevContext && prevContext !== nextContext) {
                // does the initial calendar need to be cleared?
                // if so, don't clear all the way. we still need to to hide the affectedEvents
                if (prevContext === initialContext) {
                    prevContext.dispatch({
                        type: 'SET_EVENT_DRAG',
                        state: {
                            affectedEvents: state.affectedEvents,
                            mutatedEvents: createEmptyEventStore(),
                            isEvent: true,
                        },
                    });
                    // completely clear the old calendar if it wasn't the initial
                } else {
                    prevContext.dispatch({
                        type: 'UNSET_EVENT_DRAG'
                    });
                }
            }
            if (nextContext) {
                nextContext.dispatch({
                    type: 'SET_EVENT_DRAG',
                    state
                });
            }
        }
        clearDrag() {
            let initialCalendar = this.component.context;
            let {
                receivingContext
            } = this;
            if (receivingContext) {
                receivingContext.dispatch({
                    type: 'UNSET_EVENT_DRAG'
                });
            }
            // the initial calendar might have an dummy drag state from displayDrag
            if (initialCalendar !== receivingContext) {
                initialCalendar.dispatch({
                    type: 'UNSET_EVENT_DRAG'
                });
            }
        }
        cleanup() {
            this.subjectSeg = null;
            this.isDragging = false;
            this.eventRange = null;
            this.relevantEvents = null;
            this.receivingContext = null;
            this.validMutation = null;
            this.mutatedRelevantEvents = null;
        }
    }
    // TODO: test this in IE11
    // QUESTION: why do we need it on the resizable???
    EventDragging.SELECTOR = '.fc-event-draggable, .fc-event-resizable';

    function computeEventMutation(hit0, hit1, eventInstanceStart, massagers) {
        let dateSpan0 = hit0.dateSpan;
        let dateSpan1 = hit1.dateSpan;
        let date0 = dateSpan0.range.start;
        let date1 = dateSpan1.range.start;
        let standardProps = {};
        if (dateSpan0.allDay !== dateSpan1.allDay) {
            standardProps.allDay = dateSpan1.allDay;
            standardProps.hasEnd = hit1.context.options.allDayMaintainDuration;
            if (dateSpan1.allDay) {
                // means date1 is already start-of-day,
                // but date0 needs to be converted
                date0 = startOfDay(eventInstanceStart);
            } else {
                // Moving from allDate->timed
                // Doesn't matter where on the event the drag began, mutate the event's start-date to date1
                date0 = eventInstanceStart;
            }
        }
        let delta = diffDates(date0, date1, hit0.context.dateEnv, hit0.componentId === hit1.componentId ?
            hit0.largeUnit :
            null);
        if (delta.milliseconds) { // has hours/minutes/seconds
            standardProps.allDay = false;
        }
        let mutation = {
            datesDelta: delta,
            standardProps,
        };
        for (let massager of massagers) {
            massager(mutation, hit0, hit1);
        }
        return mutation;
    }

    function getComponentTouchDelay(component) {
        let {
            options
        } = component.context;
        let delay = options.eventLongPressDelay;
        if (delay == null) {
            delay = options.longPressDelay;
        }
        return delay;
    }

    class EventResizing extends Interaction {
        constructor(settings) {
            super(settings);
            // internal state
            this.draggingSegEl = null;
            this.draggingSeg = null; // TODO: rename to resizingSeg? subjectSeg?
            this.eventRange = null;
            this.relevantEvents = null;
            this.validMutation = null;
            this.mutatedRelevantEvents = null;
            this.handlePointerDown = (ev) => {
                let {
                    component
                } = this;
                let segEl = this.querySegEl(ev);
                let seg = getElSeg(segEl);
                let eventRange = this.eventRange = seg.eventRange;
                this.dragging.minDistance = component.context.options.eventDragMinDistance;
                // if touch, need to be working with a selected event
                this.dragging.setIgnoreMove(!this.component.isValidSegDownEl(ev.origEvent.target) ||
                    (ev.isTouch && this.component.props.eventSelection !== eventRange.instance.instanceId));
            };
            this.handleDragStart = (ev) => {
                let {
                    context
                } = this.component;
                let eventRange = this.eventRange;
                this.relevantEvents = getRelevantEvents(context.getCurrentData().eventStore, this.eventRange.instance.instanceId);
                let segEl = this.querySegEl(ev);
                this.draggingSegEl = segEl;
                this.draggingSeg = getElSeg(segEl);
                context.calendarApi.unselect();
                context.emitter.trigger('eventResizeStart', {
                    el: segEl,
                    event: new EventImpl(context, eventRange.def, eventRange.instance),
                    jsEvent: ev.origEvent,
                    view: context.viewApi,
                });
            };
            this.handleHitUpdate = (hit, isFinal, ev) => {
                let {
                    context
                } = this.component;
                let relevantEvents = this.relevantEvents;
                let initialHit = this.hitDragging.initialHit;
                let eventInstance = this.eventRange.instance;
                let mutation = null;
                let mutatedRelevantEvents = null;
                let isInvalid = false;
                let interaction = {
                    affectedEvents: relevantEvents,
                    mutatedEvents: createEmptyEventStore(),
                    isEvent: true,
                };
                if (hit) {
                    let disallowed = hit.componentId === initialHit.componentId &&
                        this.isHitComboAllowed &&
                        !this.isHitComboAllowed(initialHit, hit);
                    if (!disallowed) {
                        mutation = computeMutation(initialHit, hit, ev.subjectEl.classList.contains('fc-event-resizer-start'), eventInstance.range);
                    }
                }
                if (mutation) {
                    mutatedRelevantEvents = applyMutationToEventStore(relevantEvents, context.getCurrentData().eventUiBases, mutation, context);
                    interaction.mutatedEvents = mutatedRelevantEvents;
                    if (!isInteractionValid(interaction, hit.dateProfile, context)) {
                        isInvalid = true;
                        mutation = null;
                        mutatedRelevantEvents = null;
                        interaction.mutatedEvents = null;
                    }
                }
                if (mutatedRelevantEvents) {
                    context.dispatch({
                        type: 'SET_EVENT_RESIZE',
                        state: interaction,
                    });
                } else {
                    context.dispatch({
                        type: 'UNSET_EVENT_RESIZE'
                    });
                }
                if (!isInvalid) {
                    enableCursor();
                } else {
                    disableCursor();
                }
                if (!isFinal) {
                    if (mutation && isHitsEqual(initialHit, hit)) {
                        mutation = null;
                    }
                    this.validMutation = mutation;
                    this.mutatedRelevantEvents = mutatedRelevantEvents;
                }
            };
            this.handleDragEnd = (ev) => {
                let {
                    context
                } = this.component;
                let eventDef = this.eventRange.def;
                let eventInstance = this.eventRange.instance;
                let eventApi = new EventImpl(context, eventDef, eventInstance);
                let relevantEvents = this.relevantEvents;
                let mutatedRelevantEvents = this.mutatedRelevantEvents;
                context.emitter.trigger('eventResizeStop', {
                    el: this.draggingSegEl,
                    event: eventApi,
                    jsEvent: ev.origEvent,
                    view: context.viewApi,
                });
                if (this.validMutation) {
                    let updatedEventApi = new EventImpl(context, mutatedRelevantEvents.defs[eventDef.defId], eventInstance ? mutatedRelevantEvents.instances[eventInstance.instanceId] : null);
                    context.dispatch({
                        type: 'MERGE_EVENTS',
                        eventStore: mutatedRelevantEvents,
                    });
                    let eventChangeArg = {
                        oldEvent: eventApi,
                        event: updatedEventApi,
                        relatedEvents: buildEventApis(mutatedRelevantEvents, context, eventInstance),
                        revert() {
                            context.dispatch({
                                type: 'MERGE_EVENTS',
                                eventStore: relevantEvents, // the pre-change events
                            });
                        },
                    };
                    context.emitter.trigger('eventResize', Object.assign(Object.assign({}, eventChangeArg), {
                        el: this.draggingSegEl,
                        startDelta: this.validMutation.startDelta || createDuration(0),
                        endDelta: this.validMutation.endDelta || createDuration(0),
                        jsEvent: ev.origEvent,
                        view: context.viewApi
                    }));
                    context.emitter.trigger('eventChange', eventChangeArg);
                } else {
                    context.emitter.trigger('_noEventResize');
                }
                // reset all internal state
                this.draggingSeg = null;
                this.relevantEvents = null;
                this.validMutation = null;
                // okay to keep eventInstance around. useful to set it in handlePointerDown
            };
            let {
                component
            } = settings;
            let dragging = this.dragging = new FeaturefulElementDragging(settings.el);
            dragging.pointer.selector = '.fc-event-resizer';
            dragging.touchScrollAllowed = false;
            dragging.autoScroller.isEnabled = component.context.options.dragScroll;
            let hitDragging = this.hitDragging = new HitDragging(this.dragging, interactionSettingsToStore(settings));
            hitDragging.emitter.on('pointerdown', this.handlePointerDown);
            hitDragging.emitter.on('dragstart', this.handleDragStart);
            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
            hitDragging.emitter.on('dragend', this.handleDragEnd);
        }
        destroy() {
            this.dragging.destroy();
        }
        querySegEl(ev) {
            return elementClosest(ev.subjectEl, '.fc-event');
        }
    }

    function computeMutation(hit0, hit1, isFromStart, instanceRange) {
        let dateEnv = hit0.context.dateEnv;
        let date0 = hit0.dateSpan.range.start;
        let date1 = hit1.dateSpan.range.start;
        let delta = diffDates(date0, date1, dateEnv, hit0.largeUnit);
        if (isFromStart) {
            if (dateEnv.add(instanceRange.start, delta) < instanceRange.end) {
                return {
                    startDelta: delta
                };
            }
        } else if (dateEnv.add(instanceRange.end, delta) > instanceRange.start) {
            return {
                endDelta: delta
            };
        }
        return null;
    }

    class UnselectAuto {
        constructor(context) {
            this.context = context;
            this.isRecentPointerDateSelect = false; // wish we could use a selector to detect date selection, but uses hit system
            this.matchesCancel = false;
            this.matchesEvent = false;
            this.onSelect = (selectInfo) => {
                if (selectInfo.jsEvent) {
                    this.isRecentPointerDateSelect = true;
                }
            };
            this.onDocumentPointerDown = (pev) => {
                let unselectCancel = this.context.options.unselectCancel;
                let downEl = getEventTargetViaRoot(pev.origEvent);
                this.matchesCancel = !!elementClosest(downEl, unselectCancel);
                this.matchesEvent = !!elementClosest(downEl, EventDragging.SELECTOR); // interaction started on an event?
            };
            this.onDocumentPointerUp = (pev) => {
                let {
                    context
                } = this;
                let {
                    documentPointer
                } = this;
                let calendarState = context.getCurrentData();
                // touch-scrolling should never unfocus any type of selection
                if (!documentPointer.wasTouchScroll) {
                    if (calendarState.dateSelection && // an existing date selection?
                        !this.isRecentPointerDateSelect // a new pointer-initiated date selection since last onDocumentPointerUp?
                    ) {
                        let unselectAuto = context.options.unselectAuto;
                        if (unselectAuto && (!unselectAuto || !this.matchesCancel)) {
                            context.calendarApi.unselect(pev);
                        }
                    }
                    if (calendarState.eventSelection && // an existing event selected?
                        !this.matchesEvent // interaction DIDN'T start on an event
                    ) {
                        context.dispatch({
                            type: 'UNSELECT_EVENT'
                        });
                    }
                }
                this.isRecentPointerDateSelect = false;
            };
            let documentPointer = this.documentPointer = new PointerDragging(document);
            documentPointer.shouldIgnoreMove = true;
            documentPointer.shouldWatchScroll = false;
            documentPointer.emitter.on('pointerdown', this.onDocumentPointerDown);
            documentPointer.emitter.on('pointerup', this.onDocumentPointerUp);
            /*
            TODO: better way to know about whether there was a selection with the pointer
            */
            context.emitter.on('select', this.onSelect);
        }
        destroy() {
            this.context.emitter.off('select', this.onSelect);
            this.documentPointer.destroy();
        }
    }

    const OPTION_REFINERS$3 = {
        fixedMirrorParent: identity,
    };
    const LISTENER_REFINERS = {
        dateClick: identity,
        eventDragStart: identity,
        eventDragStop: identity,
        eventDrop: identity,
        eventResizeStart: identity,
        eventResizeStop: identity,
        eventResize: identity,
        drop: identity,
        eventReceive: identity,
        eventLeave: identity,
    };

    /*
    Given an already instantiated draggable object for one-or-more elements,
    Interprets any dragging as an attempt to drag an events that lives outside
    of a calendar onto a calendar.
    */
    class ExternalElementDragging {
        constructor(dragging, suppliedDragMeta) {
            this.receivingContext = null;
            this.droppableEvent = null; // will exist for all drags, even if create:false
            this.suppliedDragMeta = null;
            this.dragMeta = null;
            this.handleDragStart = (ev) => {
                this.dragMeta = this.buildDragMeta(ev.subjectEl);
            };
            this.handleHitUpdate = (hit, isFinal, ev) => {
                let {
                    dragging
                } = this.hitDragging;
                let receivingContext = null;
                let droppableEvent = null;
                let isInvalid = false;
                let interaction = {
                    affectedEvents: createEmptyEventStore(),
                    mutatedEvents: createEmptyEventStore(),
                    isEvent: this.dragMeta.create,
                };
                if (hit) {
                    receivingContext = hit.context;
                    if (this.canDropElOnCalendar(ev.subjectEl, receivingContext)) {
                        droppableEvent = computeEventForDateSpan(hit.dateSpan, this.dragMeta, receivingContext);
                        interaction.mutatedEvents = eventTupleToStore(droppableEvent);
                        isInvalid = !isInteractionValid(interaction, hit.dateProfile, receivingContext);
                        if (isInvalid) {
                            interaction.mutatedEvents = createEmptyEventStore();
                            droppableEvent = null;
                        }
                    }
                }
                this.displayDrag(receivingContext, interaction);
                // show mirror if no already-rendered mirror element OR if we are shutting down the mirror (?)
                // TODO: wish we could somehow wait for dispatch to guarantee render
                dragging.setMirrorIsVisible(isFinal || !droppableEvent || !document.querySelector('.fc-event-mirror'));
                if (!isInvalid) {
                    enableCursor();
                } else {
                    disableCursor();
                }
                if (!isFinal) {
                    dragging.setMirrorNeedsRevert(!droppableEvent);
                    this.receivingContext = receivingContext;
                    this.droppableEvent = droppableEvent;
                }
            };
            this.handleDragEnd = (pev) => {
                let {
                    receivingContext,
                    droppableEvent
                } = this;
                this.clearDrag();
                if (receivingContext && droppableEvent) {
                    let finalHit = this.hitDragging.finalHit;
                    let finalView = finalHit.context.viewApi;
                    let dragMeta = this.dragMeta;
                    receivingContext.emitter.trigger('drop', Object.assign(Object.assign({}, buildDatePointApiWithContext(finalHit.dateSpan, receivingContext)), {
                        draggedEl: pev.subjectEl,
                        jsEvent: pev.origEvent,
                        view: finalView
                    }));
                    if (dragMeta.create) {
                        let addingEvents = eventTupleToStore(droppableEvent);
                        receivingContext.dispatch({
                            type: 'MERGE_EVENTS',
                            eventStore: addingEvents,
                        });
                        if (pev.isTouch) {
                            receivingContext.dispatch({
                                type: 'SELECT_EVENT',
                                eventInstanceId: droppableEvent.instance.instanceId,
                            });
                        }
                        // signal that an external event landed
                        receivingContext.emitter.trigger('eventReceive', {
                            event: new EventImpl(receivingContext, droppableEvent.def, droppableEvent.instance),
                            relatedEvents: [],
                            revert() {
                                receivingContext.dispatch({
                                    type: 'REMOVE_EVENTS',
                                    eventStore: addingEvents,
                                });
                            },
                            draggedEl: pev.subjectEl,
                            view: finalView,
                        });
                    }
                }
                this.receivingContext = null;
                this.droppableEvent = null;
            };
            let hitDragging = this.hitDragging = new HitDragging(dragging, interactionSettingsStore);
            hitDragging.requireInitial = false; // will start outside of a component
            hitDragging.emitter.on('dragstart', this.handleDragStart);
            hitDragging.emitter.on('hitupdate', this.handleHitUpdate);
            hitDragging.emitter.on('dragend', this.handleDragEnd);
            this.suppliedDragMeta = suppliedDragMeta;
        }
        buildDragMeta(subjectEl) {
            if (typeof this.suppliedDragMeta === 'object') {
                return parseDragMeta(this.suppliedDragMeta);
            }
            if (typeof this.suppliedDragMeta === 'function') {
                return parseDragMeta(this.suppliedDragMeta(subjectEl));
            }
            return getDragMetaFromEl(subjectEl);
        }
        displayDrag(nextContext, state) {
            let prevContext = this.receivingContext;
            if (prevContext && prevContext !== nextContext) {
                prevContext.dispatch({
                    type: 'UNSET_EVENT_DRAG'
                });
            }
            if (nextContext) {
                nextContext.dispatch({
                    type: 'SET_EVENT_DRAG',
                    state
                });
            }
        }
        clearDrag() {
            if (this.receivingContext) {
                this.receivingContext.dispatch({
                    type: 'UNSET_EVENT_DRAG'
                });
            }
        }
        canDropElOnCalendar(el, receivingContext) {
            let dropAccept = receivingContext.options.dropAccept;
            if (typeof dropAccept === 'function') {
                return dropAccept.call(receivingContext.calendarApi, el);
            }
            if (typeof dropAccept === 'string' && dropAccept) {
                return Boolean(elementMatches(el, dropAccept));
            }
            return true;
        }
    }
    // Utils for computing event store from the DragMeta
    // ----------------------------------------------------------------------------------------------------
    function computeEventForDateSpan(dateSpan, dragMeta, context) {
        let defProps = Object.assign({}, dragMeta.leftoverProps);
        for (let transform of context.pluginHooks.externalDefTransforms) {
            Object.assign(defProps, transform(dateSpan, dragMeta));
        }
        let {
            refined,
            extra
        } = refineEventDef(defProps, context);
        let def = parseEventDef(refined, extra, dragMeta.sourceId, dateSpan.allDay, context.options.forceEventDuration || Boolean(dragMeta.duration), // hasEnd
            context);
        let start = dateSpan.range.start;
        // only rely on time info if drop zone is all-day,
        // otherwise, we already know the time
        if (dateSpan.allDay && dragMeta.startTime) {
            start = context.dateEnv.add(start, dragMeta.startTime);
        }
        let end = dragMeta.duration ?
            context.dateEnv.add(start, dragMeta.duration) :
            getDefaultEventEnd(dateSpan.allDay, start, context);
        let instance = createEventInstance(def.defId, {
            start,
            end
        });
        return {
            def,
            instance
        };
    }
    // Utils for extracting data from element
    // ----------------------------------------------------------------------------------------------------
    function getDragMetaFromEl(el) {
        let str = getEmbeddedElData(el, 'event');
        let obj = str ?
            JSON.parse(str) : {
                create: false
            }; // if no embedded data, assume no event creation
        return parseDragMeta(obj);
    }
    config.dataAttrPrefix = '';

    function getEmbeddedElData(el, name) {
        let prefix = config.dataAttrPrefix;
        let prefixedName = (prefix ? prefix + '-' : '') + name;
        return el.getAttribute('data-' + prefixedName) || '';
    }

    /*
    Makes an element (that is *external* to any calendar) draggable.
    Can pass in data that determines how an event will be created when dropped onto a calendar.
    Leverages FullCalendar's internal drag-n-drop functionality WITHOUT a third-party drag system.
    */
    class ExternalDraggable {
        constructor(el, settings = {}) {
            this.handlePointerDown = (ev) => {
                let {
                    dragging
                } = this;
                let {
                    minDistance,
                    longPressDelay
                } = this.settings;
                dragging.minDistance =
                    minDistance != null ?
                    minDistance :
                    (ev.isTouch ? 0 : BASE_OPTION_DEFAULTS.eventDragMinDistance);
                dragging.delay =
                    ev.isTouch ? // TODO: eventually read eventLongPressDelay instead vvv
                    (longPressDelay != null ? longPressDelay : BASE_OPTION_DEFAULTS.longPressDelay) :
                    0;
            };
            this.handleDragStart = (ev) => {
                if (ev.isTouch &&
                    this.dragging.delay &&
                    ev.subjectEl.classList.contains('fc-event')) {
                    this.dragging.mirror.getMirrorEl().classList.add('fc-event-selected');
                }
            };
            this.settings = settings;
            let dragging = this.dragging = new FeaturefulElementDragging(el);
            dragging.touchScrollAllowed = false;
            if (settings.itemSelector != null) {
                dragging.pointer.selector = settings.itemSelector;
            }
            if (settings.appendTo != null) {
                dragging.mirror.parentNode = settings.appendTo; // TODO: write tests
            }
            dragging.emitter.on('pointerdown', this.handlePointerDown);
            dragging.emitter.on('dragstart', this.handleDragStart);
            new ExternalElementDragging(dragging, settings.eventData); // eslint-disable-line no-new
        }
        destroy() {
            this.dragging.destroy();
        }
    }

    /*
    Detects when a *THIRD-PARTY* drag-n-drop system interacts with elements.
    The third-party system is responsible for drawing the visuals effects of the drag.
    This class simply monitors for pointer movements and fires events.
    It also has the ability to hide the moving element (the "mirror") during the drag.
    */
    class InferredElementDragging extends ElementDragging {
        constructor(containerEl) {
            super(containerEl);
            this.shouldIgnoreMove = false;
            this.mirrorSelector = '';
            this.currentMirrorEl = null;
            this.handlePointerDown = (ev) => {
                this.emitter.trigger('pointerdown', ev);
                if (!this.shouldIgnoreMove) {
                    // fire dragstart right away. does not support delay or min-distance
                    this.emitter.trigger('dragstart', ev);
                }
            };
            this.handlePointerMove = (ev) => {
                if (!this.shouldIgnoreMove) {
                    this.emitter.trigger('dragmove', ev);
                }
            };
            this.handlePointerUp = (ev) => {
                this.emitter.trigger('pointerup', ev);
                if (!this.shouldIgnoreMove) {
                    // fire dragend right away. does not support a revert animation
                    this.emitter.trigger('dragend', ev);
                }
            };
            let pointer = this.pointer = new PointerDragging(containerEl);
            pointer.emitter.on('pointerdown', this.handlePointerDown);
            pointer.emitter.on('pointermove', this.handlePointerMove);
            pointer.emitter.on('pointerup', this.handlePointerUp);
        }
        destroy() {
            this.pointer.destroy();
        }
        setIgnoreMove(bool) {
            this.shouldIgnoreMove = bool;
        }
        setMirrorIsVisible(bool) {
            if (bool) {
                // restore a previously hidden element.
                // use the reference in case the selector class has already been removed.
                if (this.currentMirrorEl) {
                    this.currentMirrorEl.style.visibility = '';
                    this.currentMirrorEl = null;
                }
            } else {
                let mirrorEl = this.mirrorSelector
                    // TODO: somehow query FullCalendars WITHIN shadow-roots
                    ?
                    document.querySelector(this.mirrorSelector) :
                    null;
                if (mirrorEl) {
                    this.currentMirrorEl = mirrorEl;
                    mirrorEl.style.visibility = 'hidden';
                }
            }
        }
    }

    /*
    Bridges third-party drag-n-drop systems with FullCalendar.
    Must be instantiated and destroyed by caller.
    */
    class ThirdPartyDraggable {
        constructor(containerOrSettings, settings) {
            let containerEl = document;
            if (
                // wish we could just test instanceof EventTarget, but doesn't work in IE11
                containerOrSettings === document ||
                containerOrSettings instanceof Element) {
                containerEl = containerOrSettings;
                settings = settings || {};
            } else {
                settings = (containerOrSettings || {});
            }
            let dragging = this.dragging = new InferredElementDragging(containerEl);
            if (typeof settings.itemSelector === 'string') {
                dragging.pointer.selector = settings.itemSelector;
            } else if (containerEl === document) {
                dragging.pointer.selector = '[data-event]';
            }
            if (typeof settings.mirrorSelector === 'string') {
                dragging.mirrorSelector = settings.mirrorSelector;
            }
            let externalDragging = new ExternalElementDragging(dragging, settings.eventData);
            // The hit-detection system requires that the dnd-mirror-element be pointer-events:none,
            // but this can't be guaranteed for third-party draggables, so disable
            externalDragging.hitDragging.disablePointCheck = true;
        }
        destroy() {
            this.dragging.destroy();
        }
    }

    var index$4 = createPlugin({
        name: '@fullcalendar/interaction',
        componentInteractions: [DateClicking, DateSelecting, EventDragging, EventResizing],
        calendarInteractions: [UnselectAuto],
        elementDraggingImpl: FeaturefulElementDragging,
        optionRefiners: OPTION_REFINERS$3,
        listenerRefiners: LISTENER_REFINERS,
    });

    /* An abstract class for the daygrid views, as well as month view. Renders one or more rows of day cells.
    ----------------------------------------------------------------------------------------------------------------------*/
    // It is a manager for a Table subcomponent, which does most of the heavy lifting.
    // It is responsible for managing width/height.
    class TableView extends DateComponent {
        constructor() {
            super(...arguments);
            this.headerElRef = d();
        }
        renderSimpleLayout(headerRowContent, bodyContent) {
            let {
                props,
                context
            } = this;
            let sections = [];
            let stickyHeaderDates = getStickyHeaderDates(context.options);
            if (headerRowContent) {
                sections.push({
                    type: 'header',
                    key: 'header',
                    isSticky: stickyHeaderDates,
                    chunk: {
                        elRef: this.headerElRef,
                        tableClassName: 'fc-col-header',
                        rowContent: headerRowContent,
                    },
                });
            }
            sections.push({
                type: 'body',
                key: 'body',
                liquid: true,
                chunk: {
                    content: bodyContent
                },
            });
            return (y(ViewContainer, {
                    elClasses: ['fc-daygrid'],
                    viewSpec: context.viewSpec
                },
                y(SimpleScrollGrid, {
                    liquid: !props.isHeightAuto && !props.forPrint,
                    collapsibleWidth: props.forPrint,
                    cols: [] /* TODO: make optional? */ ,
                    sections: sections
                })));
        }
        renderHScrollLayout(headerRowContent, bodyContent, colCnt, dayMinWidth) {
            let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
            if (!ScrollGrid) {
                throw new Error('No ScrollGrid implementation');
            }
            let {
                props,
                context
            } = this;
            let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
            let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
            let sections = [];
            if (headerRowContent) {
                sections.push({
                    type: 'header',
                    key: 'header',
                    isSticky: stickyHeaderDates,
                    chunks: [{
                        key: 'main',
                        elRef: this.headerElRef,
                        tableClassName: 'fc-col-header',
                        rowContent: headerRowContent,
                    }],
                });
            }
            sections.push({
                type: 'body',
                key: 'body',
                liquid: true,
                chunks: [{
                    key: 'main',
                    content: bodyContent,
                }],
            });
            if (stickyFooterScrollbar) {
                sections.push({
                    type: 'footer',
                    key: 'footer',
                    isSticky: true,
                    chunks: [{
                        key: 'main',
                        content: renderScrollShim,
                    }],
                });
            }
            return (y(ViewContainer, {
                    elClasses: ['fc-daygrid'],
                    viewSpec: context.viewSpec
                },
                y(ScrollGrid, {
                    liquid: !props.isHeightAuto && !props.forPrint,
                    forPrint: props.forPrint,
                    collapsibleWidth: props.forPrint,
                    colGroups: [{
                        cols: [{
                            span: colCnt,
                            minWidth: dayMinWidth
                        }]
                    }],
                    sections: sections
                })));
        }
    }

    function splitSegsByRow(segs, rowCnt) {
        let byRow = [];
        for (let i = 0; i < rowCnt; i += 1) {
            byRow[i] = [];
        }
        for (let seg of segs) {
            byRow[seg.row].push(seg);
        }
        return byRow;
    }

    function splitSegsByFirstCol(segs, colCnt) {
        let byCol = [];
        for (let i = 0; i < colCnt; i += 1) {
            byCol[i] = [];
        }
        for (let seg of segs) {
            byCol[seg.firstCol].push(seg);
        }
        return byCol;
    }

    function splitInteractionByRow(ui, rowCnt) {
        let byRow = [];
        if (!ui) {
            for (let i = 0; i < rowCnt; i += 1) {
                byRow[i] = null;
            }
        } else {
            for (let i = 0; i < rowCnt; i += 1) {
                byRow[i] = {
                    affectedInstances: ui.affectedInstances,
                    isEvent: ui.isEvent,
                    segs: [],
                };
            }
            for (let seg of ui.segs) {
                byRow[seg.row].segs.push(seg);
            }
        }
        return byRow;
    }

    const DEFAULT_TABLE_EVENT_TIME_FORMAT = createFormatter({
        hour: 'numeric',
        minute: '2-digit',
        omitZeroMinute: true,
        meridiem: 'narrow',
    });

    function hasListItemDisplay(seg) {
        let {
            display
        } = seg.eventRange.ui;
        return display === 'list-item' || (display === 'auto' &&
            !seg.eventRange.def.allDay &&
            seg.firstCol === seg.lastCol && // can't be multi-day
            seg.isStart && // "
            seg.isEnd // "
        );
    }

    class TableBlockEvent extends BaseComponent {
        render() {
            let {
                props
            } = this;
            return (y(StandardEvent, Object.assign({}, props, {
                elClasses: ['fc-daygrid-event', 'fc-daygrid-block-event', 'fc-h-event'],
                defaultTimeFormat: DEFAULT_TABLE_EVENT_TIME_FORMAT,
                defaultDisplayEventEnd: props.defaultDisplayEventEnd,
                disableResizing: !props.seg.eventRange.def.allDay
            })));
        }
    }

    class TableListItemEvent extends BaseComponent {
        render() {
            let {
                props,
                context
            } = this;
            let {
                options
            } = context;
            let {
                seg
            } = props;
            let timeFormat = options.eventTimeFormat || DEFAULT_TABLE_EVENT_TIME_FORMAT;
            let timeText = buildSegTimeText(seg, timeFormat, context, true, props.defaultDisplayEventEnd);
            return (y(EventContainer, Object.assign({}, props, {
                elTag: "a",
                elClasses: ['fc-daygrid-event', 'fc-daygrid-dot-event'],
                elAttrs: getSegAnchorAttrs(props.seg, context),
                defaultGenerator: renderInnerContent$2,
                timeText: timeText,
                isResizing: false,
                isDateSelecting: false
            })));
        }
    }

    function renderInnerContent$2(renderProps) {
        return (y(_, null,
            y("div", {
                className: "fc-daygrid-event-dot",
                style: {
                    borderColor: renderProps.borderColor || renderProps.backgroundColor
                }
            }),
            renderProps.timeText && (y("div", {
                className: "fc-event-time"
            }, renderProps.timeText)),
            y("div", {
                className: "fc-event-title"
            }, renderProps.event.title || y(_, null, "\u00A0"))));
    }

    class TableCellMoreLink extends BaseComponent {
        constructor() {
            super(...arguments);
            this.compileSegs = memoize(compileSegs);
        }
        render() {
            let {
                props
            } = this;
            let {
                allSegs,
                invisibleSegs
            } = this.compileSegs(props.singlePlacements);
            return (y(MoreLinkContainer, {
                elClasses: ['fc-daygrid-more-link'],
                dateProfile: props.dateProfile,
                todayRange: props.todayRange,
                allDayDate: props.allDayDate,
                moreCnt: props.moreCnt,
                allSegs: allSegs,
                hiddenSegs: invisibleSegs,
                alignmentElRef: props.alignmentElRef,
                alignGridTop: props.alignGridTop,
                extraDateSpan: props.extraDateSpan,
                popoverContent: () => {
                    let isForcedInvisible = (props.eventDrag ? props.eventDrag.affectedInstances : null) ||
                        (props.eventResize ? props.eventResize.affectedInstances : null) || {};
                    return (y(_, null, allSegs.map((seg) => {
                        let instanceId = seg.eventRange.instance.instanceId;
                        return (y("div", {
                            className: "fc-daygrid-event-harness",
                            key: instanceId,
                            style: {
                                visibility: isForcedInvisible[instanceId] ? 'hidden' : '',
                            }
                        }, hasListItemDisplay(seg) ? (y(TableListItemEvent, Object.assign({
                            seg: seg,
                            isDragging: false,
                            isSelected: instanceId === props.eventSelection,
                            defaultDisplayEventEnd: false
                        }, getSegMeta(seg, props.todayRange)))) : (y(TableBlockEvent, Object.assign({
                            seg: seg,
                            isDragging: false,
                            isResizing: false,
                            isDateSelecting: false,
                            isSelected: instanceId === props.eventSelection,
                            defaultDisplayEventEnd: false
                        }, getSegMeta(seg, props.todayRange))))));
                    })));
                }
            }));
        }
    }

    function compileSegs(singlePlacements) {
        let allSegs = [];
        let invisibleSegs = [];
        for (let placement of singlePlacements) {
            allSegs.push(placement.seg);
            if (!placement.isVisible) {
                invisibleSegs.push(placement.seg);
            }
        }
        return {
            allSegs,
            invisibleSegs
        };
    }

    const DEFAULT_WEEK_NUM_FORMAT$1 = createFormatter({
        week: 'narrow'
    });
    class TableCell extends DateComponent {
        constructor() {
            super(...arguments);
            this.rootElRef = d();
            this.state = {
                dayNumberId: getUniqueDomId(),
            };
            this.handleRootEl = (el) => {
                setRef(this.rootElRef, el);
                setRef(this.props.elRef, el);
            };
        }
        render() {
            let {
                context,
                props,
                state,
                rootElRef
            } = this;
            let {
                options,
                dateEnv
            } = context;
            let {
                date,
                dateProfile
            } = props;
            // TODO: memoize this?
            const isMonthStart = props.showDayNumber &&
                shouldDisplayMonthStart(date, dateProfile.currentRange, dateEnv);
            return (y(DayCellContainer, {
                elTag: "td",
                elRef: this.handleRootEl,
                elClasses: [
                    'fc-daygrid-day',
                    ...(props.extraClassNames || []),
                ],
                elAttrs: Object.assign(Object.assign(Object.assign({}, props.extraDataAttrs), (props.showDayNumber ? {
                    'aria-labelledby': state.dayNumberId
                } : {})), {
                    role: 'gridcell'
                }),
                defaultGenerator: renderTopInner,
                date: date,
                dateProfile: dateProfile,
                todayRange: props.todayRange,
                showDayNumber: props.showDayNumber,
                isMonthStart: isMonthStart,
                extraRenderProps: props.extraRenderProps
            }, (InnerContent, renderProps) => (y("div", {
                    ref: props.innerElRef,
                    className: "fc-daygrid-day-frame fc-scrollgrid-sync-inner",
                    style: {
                        minHeight: props.minHeight
                    }
                },
                props.showWeekNumber && (y(WeekNumberContainer, {
                    elTag: "a",
                    elClasses: ['fc-daygrid-week-number'],
                    elAttrs: buildNavLinkAttrs(context, date, 'week'),
                    date: date,
                    defaultFormat: DEFAULT_WEEK_NUM_FORMAT$1
                })),
                !renderProps.isDisabled &&
                (props.showDayNumber || hasCustomDayCellContent(options) || props.forceDayTop) ? (y("div", {
                        className: "fc-daygrid-day-top"
                    },
                    y(InnerContent, {
                        elTag: "a",
                        elClasses: [
                            'fc-daygrid-day-number',
                            isMonthStart && 'fc-daygrid-month-start',
                        ],
                        elAttrs: Object.assign(Object.assign({}, buildNavLinkAttrs(context, date)), {
                            id: state.dayNumberId
                        })
                    }))) : props.showDayNumber ? (
                    // for creating correct amount of space (see issue #7162)
                    y("div", {
                            className: "fc-daygrid-day-top",
                            style: {
                                visibility: 'hidden'
                            }
                        },
                        y("a", {
                            className: "fc-daygrid-day-number"
                        }, "\u00A0"))) : undefined,
                y("div", {
                        className: "fc-daygrid-day-events",
                        ref: props.fgContentElRef
                    },
                    props.fgContent,
                    y("div", {
                            className: "fc-daygrid-day-bottom",
                            style: {
                                marginTop: props.moreMarginTop
                            }
                        },
                        y(TableCellMoreLink, {
                            allDayDate: date,
                            singlePlacements: props.singlePlacements,
                            moreCnt: props.moreCnt,
                            alignmentElRef: rootElRef,
                            alignGridTop: !props.showDayNumber,
                            extraDateSpan: props.extraDateSpan,
                            dateProfile: props.dateProfile,
                            eventSelection: props.eventSelection,
                            eventDrag: props.eventDrag,
                            eventResize: props.eventResize,
                            todayRange: props.todayRange
                        }))),
                y("div", {
                    className: "fc-daygrid-day-bg"
                }, props.bgContent)))));
        }
    }

    function renderTopInner(props) {
        return props.dayNumberText || y(_, null, "\u00A0");
    }

    function shouldDisplayMonthStart(date, currentRange, dateEnv) {
        const {
            start: currentStart,
            end: currentEnd
        } = currentRange;
        const currentEndIncl = addMs(currentEnd, -1);
        const currentFirstYear = dateEnv.getYear(currentStart);
        const currentFirstMonth = dateEnv.getMonth(currentStart);
        const currentLastYear = dateEnv.getYear(currentEndIncl);
        const currentLastMonth = dateEnv.getMonth(currentEndIncl);
        // spans more than one month?
        return !(currentFirstYear === currentLastYear && currentFirstMonth === currentLastMonth) &&
            Boolean(
                // first date in current view?
                date.valueOf() === currentStart.valueOf() ||
                // a month-start that's within the current range?
                (dateEnv.getDay(date) === 1 && date.valueOf() < currentEnd.valueOf()));
    }

    function generateSegKey(seg) {
        return seg.eventRange.instance.instanceId + ':' + seg.firstCol;
    }

    function generateSegUid(seg) {
        return generateSegKey(seg) + ':' + seg.lastCol;
    }

    function computeFgSegPlacement(segs, // assumed already sorted
        dayMaxEvents, dayMaxEventRows, strictOrder, segHeights, maxContentHeight, cells) {
        let hierarchy = new DayGridSegHierarchy((segEntry) => {
            // TODO: more DRY with generateSegUid
            let segUid = segs[segEntry.index].eventRange.instance.instanceId +
                ':' + segEntry.span.start +
                ':' + (segEntry.span.end - 1);
            // if no thickness known, assume 1 (if 0, so small it always fits)
            return segHeights[segUid] || 1;
        });
        hierarchy.allowReslicing = true;
        hierarchy.strictOrder = strictOrder;
        if (dayMaxEvents === true || dayMaxEventRows === true) {
            hierarchy.maxCoord = maxContentHeight;
            hierarchy.hiddenConsumes = true;
        } else if (typeof dayMaxEvents === 'number') {
            hierarchy.maxStackCnt = dayMaxEvents;
        } else if (typeof dayMaxEventRows === 'number') {
            hierarchy.maxStackCnt = dayMaxEventRows;
            hierarchy.hiddenConsumes = true;
        }
        // create segInputs only for segs with known heights
        let segInputs = [];
        let unknownHeightSegs = [];
        for (let i = 0; i < segs.length; i += 1) {
            let seg = segs[i];
            let segUid = generateSegUid(seg);
            let eventHeight = segHeights[segUid];
            if (eventHeight != null) {
                segInputs.push({
                    index: i,
                    span: {
                        start: seg.firstCol,
                        end: seg.lastCol + 1,
                    },
                });
            } else {
                unknownHeightSegs.push(seg);
            }
        }
        let hiddenEntries = hierarchy.addSegs(segInputs);
        let segRects = hierarchy.toRects();
        let {
            singleColPlacements,
            multiColPlacements,
            leftoverMargins
        } = placeRects(segRects, segs, cells);
        let moreCnts = [];
        let moreMarginTops = [];
        // add segs with unknown heights
        for (let seg of unknownHeightSegs) {
            multiColPlacements[seg.firstCol].push({
                seg,
                isVisible: false,
                isAbsolute: true,
                absoluteTop: 0,
                marginTop: 0,
            });
            for (let col = seg.firstCol; col <= seg.lastCol; col += 1) {
                singleColPlacements[col].push({
                    seg: resliceSeg(seg, col, col + 1, cells),
                    isVisible: false,
                    isAbsolute: false,
                    absoluteTop: 0,
                    marginTop: 0,
                });
            }
        }
        // add the hidden entries
        for (let col = 0; col < cells.length; col += 1) {
            moreCnts.push(0);
        }
        for (let hiddenEntry of hiddenEntries) {
            let seg = segs[hiddenEntry.index];
            let hiddenSpan = hiddenEntry.span;
            multiColPlacements[hiddenSpan.start].push({
                seg: resliceSeg(seg, hiddenSpan.start, hiddenSpan.end, cells),
                isVisible: false,
                isAbsolute: true,
                absoluteTop: 0,
                marginTop: 0,
            });
            for (let col = hiddenSpan.start; col < hiddenSpan.end; col += 1) {
                moreCnts[col] += 1;
                singleColPlacements[col].push({
                    seg: resliceSeg(seg, col, col + 1, cells),
                    isVisible: false,
                    isAbsolute: false,
                    absoluteTop: 0,
                    marginTop: 0,
                });
            }
        }
        // deal with leftover margins
        for (let col = 0; col < cells.length; col += 1) {
            moreMarginTops.push(leftoverMargins[col]);
        }
        return {
            singleColPlacements,
            multiColPlacements,
            moreCnts,
            moreMarginTops
        };
    }
    // rects ordered by top coord, then left
    function placeRects(allRects, segs, cells) {
        let rectsByEachCol = groupRectsByEachCol(allRects, cells.length);
        let singleColPlacements = [];
        let multiColPlacements = [];
        let leftoverMargins = [];
        for (let col = 0; col < cells.length; col += 1) {
            let rects = rectsByEachCol[col];
            // compute all static segs in singlePlacements
            let singlePlacements = [];
            let currentHeight = 0;
            let currentMarginTop = 0;
            for (let rect of rects) {
                let seg = segs[rect.index];
                singlePlacements.push({
                    seg: resliceSeg(seg, col, col + 1, cells),
                    isVisible: true,
                    isAbsolute: false,
                    absoluteTop: rect.levelCoord,
                    marginTop: rect.levelCoord - currentHeight,
                });
                currentHeight = rect.levelCoord + rect.thickness;
            }
            // compute mixed static/absolute segs in multiPlacements
            let multiPlacements = [];
            currentHeight = 0;
            currentMarginTop = 0;
            for (let rect of rects) {
                let seg = segs[rect.index];
                let isAbsolute = rect.span.end - rect.span.start > 1; // multi-column?
                let isFirstCol = rect.span.start === col;
                currentMarginTop += rect.levelCoord - currentHeight; // amount of space since bottom of previous seg
                currentHeight = rect.levelCoord + rect.thickness; // height will now be bottom of current seg
                if (isAbsolute) {
                    currentMarginTop += rect.thickness;
                    if (isFirstCol) {
                        multiPlacements.push({
                            seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
                            isVisible: true,
                            isAbsolute: true,
                            absoluteTop: rect.levelCoord,
                            marginTop: 0,
                        });
                    }
                } else if (isFirstCol) {
                    multiPlacements.push({
                        seg: resliceSeg(seg, rect.span.start, rect.span.end, cells),
                        isVisible: true,
                        isAbsolute: false,
                        absoluteTop: rect.levelCoord,
                        marginTop: currentMarginTop, // claim the margin
                    });
                    currentMarginTop = 0;
                }
            }
            singleColPlacements.push(singlePlacements);
            multiColPlacements.push(multiPlacements);
            leftoverMargins.push(currentMarginTop);
        }
        return {
            singleColPlacements,
            multiColPlacements,
            leftoverMargins
        };
    }

    function groupRectsByEachCol(rects, colCnt) {
        let rectsByEachCol = [];
        for (let col = 0; col < colCnt; col += 1) {
            rectsByEachCol.push([]);
        }
        for (let rect of rects) {
            for (let col = rect.span.start; col < rect.span.end; col += 1) {
                rectsByEachCol[col].push(rect);
            }
        }
        return rectsByEachCol;
    }

    function resliceSeg(seg, spanStart, spanEnd, cells) {
        if (seg.firstCol === spanStart && seg.lastCol === spanEnd - 1) {
            return seg;
        }
        let eventRange = seg.eventRange;
        let origRange = eventRange.range;
        let slicedRange = intersectRanges(origRange, {
            start: cells[spanStart].date,
            end: addDays(cells[spanEnd - 1].date, 1),
        });
        return Object.assign(Object.assign({}, seg), {
            firstCol: spanStart,
            lastCol: spanEnd - 1,
            eventRange: {
                def: eventRange.def,
                ui: Object.assign(Object.assign({}, eventRange.ui), {
                    durationEditable: false
                }),
                instance: eventRange.instance,
                range: slicedRange,
            },
            isStart: seg.isStart && slicedRange.start.valueOf() === origRange.start.valueOf(),
            isEnd: seg.isEnd && slicedRange.end.valueOf() === origRange.end.valueOf()
        });
    }
    class DayGridSegHierarchy extends SegHierarchy {
        constructor() {
            super(...arguments);
            // config
            this.hiddenConsumes = false;
            // allows us to keep hidden entries in the hierarchy so they take up space
            this.forceHidden = {};
        }
        addSegs(segInputs) {
            const hiddenSegs = super.addSegs(segInputs);
            const {
                entriesByLevel
            } = this;
            const excludeHidden = (entry) => !this.forceHidden[buildEntryKey(entry)];
            // remove the forced-hidden segs
            for (let level = 0; level < entriesByLevel.length; level += 1) {
                entriesByLevel[level] = entriesByLevel[level].filter(excludeHidden);
            }
            return hiddenSegs;
        }
        handleInvalidInsertion(insertion, entry, hiddenEntries) {
            const {
                entriesByLevel,
                forceHidden
            } = this;
            const {
                touchingEntry,
                touchingLevel,
                touchingLateral
            } = insertion;
            // the entry that the new insertion is touching must be hidden
            if (this.hiddenConsumes && touchingEntry) {
                const touchingEntryId = buildEntryKey(touchingEntry);
                if (!forceHidden[touchingEntryId]) {
                    if (this.allowReslicing) {
                        // split up the touchingEntry, reinsert it
                        const hiddenEntry = Object.assign(Object.assign({}, touchingEntry), {
                            span: intersectSpans(touchingEntry.span, entry.span)
                        });
                        // reinsert the area that turned into a "more" link (so no other entries try to
                        // occupy the space) but mark it forced-hidden
                        const hiddenEntryId = buildEntryKey(hiddenEntry);
                        forceHidden[hiddenEntryId] = true;
                        entriesByLevel[touchingLevel][touchingLateral] = hiddenEntry;
                        hiddenEntries.push(hiddenEntry);
                        this.splitEntry(touchingEntry, entry, hiddenEntries);
                    } else {
                        forceHidden[touchingEntryId] = true;
                        hiddenEntries.push(touchingEntry);
                    }
                }
            }
            // will try to reslice...
            super.handleInvalidInsertion(insertion, entry, hiddenEntries);
        }
    }

    class TableRow extends DateComponent {
        constructor() {
            super(...arguments);
            this.cellElRefs = new RefMap(); // the <td>
            this.frameElRefs = new RefMap(); // the fc-daygrid-day-frame
            this.fgElRefs = new RefMap(); // the fc-daygrid-day-events
            this.segHarnessRefs = new RefMap(); // indexed by "instanceId:firstCol"
            this.rootElRef = d();
            this.state = {
                framePositions: null,
                maxContentHeight: null,
                segHeights: {},
            };
            this.handleResize = (isForced) => {
                if (isForced) {
                    this.updateSizing(true); // isExternal=true
                }
            };
        }
        render() {
            let {
                props,
                state,
                context
            } = this;
            let {
                options
            } = context;
            let colCnt = props.cells.length;
            let businessHoursByCol = splitSegsByFirstCol(props.businessHourSegs, colCnt);
            let bgEventSegsByCol = splitSegsByFirstCol(props.bgEventSegs, colCnt);
            let highlightSegsByCol = splitSegsByFirstCol(this.getHighlightSegs(), colCnt);
            let mirrorSegsByCol = splitSegsByFirstCol(this.getMirrorSegs(), colCnt);
            let {
                singleColPlacements,
                multiColPlacements,
                moreCnts,
                moreMarginTops
            } = computeFgSegPlacement(sortEventSegs(props.fgEventSegs, options.eventOrder), props.dayMaxEvents, props.dayMaxEventRows, options.eventOrderStrict, state.segHeights, state.maxContentHeight, props.cells);
            let isForcedInvisible = // TODO: messy way to compute this
                (props.eventDrag && props.eventDrag.affectedInstances) ||
                (props.eventResize && props.eventResize.affectedInstances) || {};
            return (y("tr", {
                    ref: this.rootElRef,
                    role: "row"
                },
                props.renderIntro && props.renderIntro(),
                props.cells.map((cell, col) => {
                    let normalFgNodes = this.renderFgSegs(col, props.forPrint ? singleColPlacements[col] : multiColPlacements[col], props.todayRange, isForcedInvisible);
                    let mirrorFgNodes = this.renderFgSegs(col, buildMirrorPlacements(mirrorSegsByCol[col], multiColPlacements), props.todayRange, {}, Boolean(props.eventDrag), Boolean(props.eventResize), false);
                    return (y(TableCell, {
                        key: cell.key,
                        elRef: this.cellElRefs.createRef(cell.key),
                        innerElRef: this.frameElRefs.createRef(cell.key) /* FF <td> problem, but okay to use for left/right. TODO: rename prop */ ,
                        dateProfile: props.dateProfile,
                        date: cell.date,
                        showDayNumber: props.showDayNumbers,
                        showWeekNumber: props.showWeekNumbers && col === 0,
                        forceDayTop: props.showWeekNumbers /* even displaying weeknum for row, not necessarily day */ ,
                        todayRange: props.todayRange,
                        eventSelection: props.eventSelection,
                        eventDrag: props.eventDrag,
                        eventResize: props.eventResize,
                        extraRenderProps: cell.extraRenderProps,
                        extraDataAttrs: cell.extraDataAttrs,
                        extraClassNames: cell.extraClassNames,
                        extraDateSpan: cell.extraDateSpan,
                        moreCnt: moreCnts[col],
                        moreMarginTop: moreMarginTops[col],
                        singlePlacements: singleColPlacements[col],
                        fgContentElRef: this.fgElRefs.createRef(cell.key),
                        fgContent: ( // Fragment scopes the keys
                            y(_, null,
                                y(_, null, normalFgNodes),
                                y(_, null, mirrorFgNodes))),
                        bgContent: ( // Fragment scopes the keys
                            y(_, null,
                                this.renderFillSegs(highlightSegsByCol[col], 'highlight'),
                                this.renderFillSegs(businessHoursByCol[col], 'non-business'),
                                this.renderFillSegs(bgEventSegsByCol[col], 'bg-event'))),
                        minHeight: props.cellMinHeight
                    }));
                })));
        }
        componentDidMount() {
            this.updateSizing(true);
            this.context.addResizeHandler(this.handleResize);
        }
        componentDidUpdate(prevProps, prevState) {
            let currentProps = this.props;
            this.updateSizing(!isPropsEqual(prevProps, currentProps));
        }
        componentWillUnmount() {
            this.context.removeResizeHandler(this.handleResize);
        }
        getHighlightSegs() {
            let {
                props
            } = this;
            if (props.eventDrag && props.eventDrag.segs.length) { // messy check
                return props.eventDrag.segs;
            }
            if (props.eventResize && props.eventResize.segs.length) { // messy check
                return props.eventResize.segs;
            }
            return props.dateSelectionSegs;
        }
        getMirrorSegs() {
            let {
                props
            } = this;
            if (props.eventResize && props.eventResize.segs.length) { // messy check
                return props.eventResize.segs;
            }
            return [];
        }
        renderFgSegs(col, segPlacements, todayRange, isForcedInvisible, isDragging, isResizing, isDateSelecting) {
            let {
                context
            } = this;
            let {
                eventSelection
            } = this.props;
            let {
                framePositions
            } = this.state;
            let defaultDisplayEventEnd = this.props.cells.length === 1; // colCnt === 1
            let isMirror = isDragging || isResizing || isDateSelecting;
            let nodes = [];
            if (framePositions) {
                for (let placement of segPlacements) {
                    let {
                        seg
                    } = placement;
                    let {
                        instanceId
                    } = seg.eventRange.instance;
                    let isVisible = placement.isVisible && !isForcedInvisible[instanceId];
                    let isAbsolute = placement.isAbsolute;
                    let left = '';
                    let right = '';
                    if (isAbsolute) {
                        if (context.isRtl) {
                            right = 0;
                            left = framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol];
                        } else {
                            left = 0;
                            right = framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol];
                        }
                    }
                    /*
                    known bug: events that are force to be list-item but span multiple days still take up space in later columns
                    todo: in print view, for multi-day events, don't display title within non-start/end segs
                    */
                    nodes.push(y("div", {
                        className: 'fc-daygrid-event-harness' + (isAbsolute ? ' fc-daygrid-event-harness-abs' : ''),
                        key: generateSegKey(seg),
                        ref: isMirror ? null : this.segHarnessRefs.createRef(generateSegUid(seg)),
                        style: {
                            visibility: isVisible ? '' : 'hidden',
                            marginTop: isAbsolute ? '' : placement.marginTop,
                            top: isAbsolute ? placement.absoluteTop : '',
                            left,
                            right,
                        }
                    }, hasListItemDisplay(seg) ? (y(TableListItemEvent, Object.assign({
                        seg: seg,
                        isDragging: isDragging,
                        isSelected: instanceId === eventSelection,
                        defaultDisplayEventEnd: defaultDisplayEventEnd
                    }, getSegMeta(seg, todayRange)))) : (y(TableBlockEvent, Object.assign({
                        seg: seg,
                        isDragging: isDragging,
                        isResizing: isResizing,
                        isDateSelecting: isDateSelecting,
                        isSelected: instanceId === eventSelection,
                        defaultDisplayEventEnd: defaultDisplayEventEnd
                    }, getSegMeta(seg, todayRange))))));
                }
            }
            return nodes;
        }
        renderFillSegs(segs, fillType) {
            let {
                isRtl
            } = this.context;
            let {
                todayRange
            } = this.props;
            let {
                framePositions
            } = this.state;
            let nodes = [];
            if (framePositions) {
                for (let seg of segs) {
                    let leftRightCss = isRtl ? {
                        right: 0,
                        left: framePositions.lefts[seg.lastCol] - framePositions.lefts[seg.firstCol],
                    } : {
                        left: 0,
                        right: framePositions.rights[seg.firstCol] - framePositions.rights[seg.lastCol],
                    };
                    nodes.push(y("div", {
                            key: buildEventRangeKey(seg.eventRange),
                            className: "fc-daygrid-bg-harness",
                            style: leftRightCss
                        }, fillType === 'bg-event' ?
                        y(BgEvent, Object.assign({
                            seg: seg
                        }, getSegMeta(seg, todayRange))) :
                        renderFill(fillType)));
                }
            }
            return y(_, {}, ...nodes);
        }
        updateSizing(isExternalSizingChange) {
            let {
                props,
                state,
                frameElRefs
            } = this;
            if (!props.forPrint &&
                props.clientWidth !== null // positioning ready?
            ) {
                if (isExternalSizingChange) {
                    let frameEls = props.cells.map((cell) => frameElRefs.currentMap[cell.key]);
                    if (frameEls.length) {
                        let originEl = this.rootElRef.current;
                        let newPositionCache = new PositionCache(originEl, frameEls, true, // isHorizontal
                            false);
                        if (!state.framePositions || !state.framePositions.similarTo(newPositionCache)) {
                            this.setState({
                                framePositions: new PositionCache(originEl, frameEls, true, // isHorizontal
                                    false),
                            });
                        }
                    }
                }
                const oldSegHeights = this.state.segHeights;
                const newSegHeights = this.querySegHeights();
                const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true;
                this.safeSetState({
                    // HACK to prevent oscillations of events being shown/hidden from max-event-rows
                    // Essentially, once you compute an element's height, never null-out.
                    // TODO: always display all events, as visibility:hidden?
                    segHeights: Object.assign(Object.assign({}, oldSegHeights), newSegHeights),
                    maxContentHeight: limitByContentHeight ? this.computeMaxContentHeight() : null,
                });
            }
        }
        querySegHeights() {
            let segElMap = this.segHarnessRefs.currentMap;
            let segHeights = {};
            // get the max height amongst instance segs
            for (let segUid in segElMap) {
                let height = Math.round(segElMap[segUid].getBoundingClientRect().height);
                segHeights[segUid] = Math.max(segHeights[segUid] || 0, height);
            }
            return segHeights;
        }
        computeMaxContentHeight() {
            let firstKey = this.props.cells[0].key;
            let cellEl = this.cellElRefs.currentMap[firstKey];
            let fcContainerEl = this.fgElRefs.currentMap[firstKey];
            return cellEl.getBoundingClientRect().bottom - fcContainerEl.getBoundingClientRect().top;
        }
        getCellEls() {
            let elMap = this.cellElRefs.currentMap;
            return this.props.cells.map((cell) => elMap[cell.key]);
        }
    }
    TableRow.addStateEquality({
        segHeights: isPropsEqual,
    });

    function buildMirrorPlacements(mirrorSegs, colPlacements) {
        if (!mirrorSegs.length) {
            return [];
        }
        let topsByInstanceId = buildAbsoluteTopHash(colPlacements); // TODO: cache this at first render?
        return mirrorSegs.map((seg) => ({
            seg,
            isVisible: true,
            isAbsolute: true,
            absoluteTop: topsByInstanceId[seg.eventRange.instance.instanceId],
            marginTop: 0,
        }));
    }

    function buildAbsoluteTopHash(colPlacements) {
        let topsByInstanceId = {};
        for (let placements of colPlacements) {
            for (let placement of placements) {
                topsByInstanceId[placement.seg.eventRange.instance.instanceId] = placement.absoluteTop;
            }
        }
        return topsByInstanceId;
    }

    class TableRows extends DateComponent {
        constructor() {
            super(...arguments);
            this.splitBusinessHourSegs = memoize(splitSegsByRow);
            this.splitBgEventSegs = memoize(splitAllDaySegsByRow);
            this.splitFgEventSegs = memoize(splitSegsByRow);
            this.splitDateSelectionSegs = memoize(splitSegsByRow);
            this.splitEventDrag = memoize(splitInteractionByRow);
            this.splitEventResize = memoize(splitInteractionByRow);
            this.rowRefs = new RefMap();
        }
        render() {
            let {
                props,
                context
            } = this;
            let rowCnt = props.cells.length;
            let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, rowCnt);
            let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, rowCnt);
            let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, rowCnt);
            let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, rowCnt);
            let eventDragByRow = this.splitEventDrag(props.eventDrag, rowCnt);
            let eventResizeByRow = this.splitEventResize(props.eventResize, rowCnt);
            // for DayGrid view with many rows, force a min-height on cells so doesn't appear squished
            // choose 7 because a month view will have max 6 rows
            let cellMinHeight = (rowCnt >= 7 && props.clientWidth) ?
                props.clientWidth / context.options.aspectRatio / 6 :
                null;
            return (y(NowTimer, {
                unit: "day"
            }, (nowDate, todayRange) => (y(_, null, props.cells.map((cells, row) => (y(TableRow, {
                ref: this.rowRefs.createRef(row),
                key: cells.length ?
                    cells[0].date.toISOString() /* best? or put key on cell? or use diff formatter? */ :
                    row // in case there are no cells (like when resource view is loading)
                    ,
                showDayNumbers: rowCnt > 1,
                showWeekNumbers: props.showWeekNumbers,
                todayRange: todayRange,
                dateProfile: props.dateProfile,
                cells: cells,
                renderIntro: props.renderRowIntro,
                businessHourSegs: businessHourSegsByRow[row],
                eventSelection: props.eventSelection,
                bgEventSegs: bgEventSegsByRow[row],
                fgEventSegs: fgEventSegsByRow[row],
                dateSelectionSegs: dateSelectionSegsByRow[row],
                eventDrag: eventDragByRow[row],
                eventResize: eventResizeByRow[row],
                dayMaxEvents: props.dayMaxEvents,
                dayMaxEventRows: props.dayMaxEventRows,
                clientWidth: props.clientWidth,
                clientHeight: props.clientHeight,
                cellMinHeight: cellMinHeight,
                forPrint: props.forPrint
            })))))));
        }
        componentDidMount() {
            this.registerInteractiveComponent();
        }
        componentDidUpdate() {
            // for if started with zero cells
            this.registerInteractiveComponent();
        }
        registerInteractiveComponent() {
            if (!this.rootEl) {
                // HACK: need a daygrid wrapper parent to do positioning
                // NOTE: a daygrid resource view w/o resources can have zero cells
                const firstCellEl = this.rowRefs.currentMap[0].getCellEls()[0];
                const rootEl = firstCellEl ? firstCellEl.closest('.fc-daygrid-body') : null;
                if (rootEl) {
                    this.rootEl = rootEl;
                    this.context.registerInteractiveComponent(this, {
                        el: rootEl,
                        isHitComboAllowed: this.props.isHitComboAllowed,
                    });
                }
            }
        }
        componentWillUnmount() {
            if (this.rootEl) {
                this.context.unregisterInteractiveComponent(this);
                this.rootEl = null;
            }
        }
        // Hit System
        // ----------------------------------------------------------------------------------------------------
        prepareHits() {
            this.rowPositions = new PositionCache(this.rootEl, this.rowRefs.collect().map((rowObj) => rowObj.getCellEls()[0]), // first cell el in each row. TODO: not optimal
                false, true);
            this.colPositions = new PositionCache(this.rootEl, this.rowRefs.currentMap[0].getCellEls(), // cell els in first row
                true, // horizontal
                false);
        }
        queryHit(positionLeft, positionTop) {
            let {
                colPositions,
                rowPositions
            } = this;
            let col = colPositions.leftToIndex(positionLeft);
            let row = rowPositions.topToIndex(positionTop);
            if (row != null && col != null) {
                let cell = this.props.cells[row][col];
                return {
                    dateProfile: this.props.dateProfile,
                    dateSpan: Object.assign({
                        range: this.getCellRange(row, col),
                        allDay: true
                    }, cell.extraDateSpan),
                    dayEl: this.getCellEl(row, col),
                    rect: {
                        left: colPositions.lefts[col],
                        right: colPositions.rights[col],
                        top: rowPositions.tops[row],
                        bottom: rowPositions.bottoms[row],
                    },
                    layer: 0,
                };
            }
            return null;
        }
        getCellEl(row, col) {
            return this.rowRefs.currentMap[row].getCellEls()[col]; // TODO: not optimal
        }
        getCellRange(row, col) {
            let start = this.props.cells[row][col].date;
            let end = addDays(start, 1);
            return {
                start,
                end
            };
        }
    }

    function splitAllDaySegsByRow(segs, rowCnt) {
        return splitSegsByRow(segs.filter(isSegAllDay), rowCnt);
    }

    function isSegAllDay(seg) {
        return seg.eventRange.def.allDay;
    }

    class Table extends DateComponent {
        constructor() {
            super(...arguments);
            this.elRef = d();
            this.needsScrollReset = false;
        }
        render() {
            let {
                props
            } = this;
            let {
                dayMaxEventRows,
                dayMaxEvents,
                expandRows
            } = props;
            let limitViaBalanced = dayMaxEvents === true || dayMaxEventRows === true;
            // if rows can't expand to fill fixed height, can't do balanced-height event limit
            // TODO: best place to normalize these options?
            if (limitViaBalanced && !expandRows) {
                limitViaBalanced = false;
                dayMaxEventRows = null;
                dayMaxEvents = null;
            }
            let classNames = [
                'fc-daygrid-body',
                limitViaBalanced ? 'fc-daygrid-body-balanced' : 'fc-daygrid-body-unbalanced',
                expandRows ? '' : 'fc-daygrid-body-natural', // will height of one row depend on the others?
            ];
            return (y("div", {
                    ref: this.elRef,
                    className: classNames.join(' '),
                    style: {
                        // these props are important to give this wrapper correct dimensions for interactions
                        // TODO: if we set it here, can we avoid giving to inner tables?
                        width: props.clientWidth,
                        minWidth: props.tableMinWidth,
                    }
                },
                y("table", {
                        role: "presentation",
                        className: "fc-scrollgrid-sync-table",
                        style: {
                            width: props.clientWidth,
                            minWidth: props.tableMinWidth,
                            height: expandRows ? props.clientHeight : '',
                        }
                    },
                    props.colGroupNode,
                    y("tbody", {
                            role: "presentation"
                        },
                        y(TableRows, {
                            dateProfile: props.dateProfile,
                            cells: props.cells,
                            renderRowIntro: props.renderRowIntro,
                            showWeekNumbers: props.showWeekNumbers,
                            clientWidth: props.clientWidth,
                            clientHeight: props.clientHeight,
                            businessHourSegs: props.businessHourSegs,
                            bgEventSegs: props.bgEventSegs,
                            fgEventSegs: props.fgEventSegs,
                            dateSelectionSegs: props.dateSelectionSegs,
                            eventSelection: props.eventSelection,
                            eventDrag: props.eventDrag,
                            eventResize: props.eventResize,
                            dayMaxEvents: dayMaxEvents,
                            dayMaxEventRows: dayMaxEventRows,
                            forPrint: props.forPrint,
                            isHitComboAllowed: props.isHitComboAllowed
                        })))));
        }
        componentDidMount() {
            this.requestScrollReset();
        }
        componentDidUpdate(prevProps) {
            if (prevProps.dateProfile !== this.props.dateProfile) {
                this.requestScrollReset();
            } else {
                this.flushScrollReset();
            }
        }
        requestScrollReset() {
            this.needsScrollReset = true;
            this.flushScrollReset();
        }
        flushScrollReset() {
            if (this.needsScrollReset &&
                this.props.clientWidth // sizes computed?
            ) {
                const subjectEl = getScrollSubjectEl(this.elRef.current, this.props.dateProfile);
                if (subjectEl) {
                    const originEl = subjectEl.closest('.fc-daygrid-body');
                    const scrollEl = originEl.closest('.fc-scroller');
                    const scrollTop = subjectEl.getBoundingClientRect().top -
                        originEl.getBoundingClientRect().top;
                    scrollEl.scrollTop = scrollTop ? (scrollTop + 1) : 0; // overcome border
                }
                this.needsScrollReset = false;
            }
        }
    }

    function getScrollSubjectEl(containerEl, dateProfile) {
        let el;
        if (dateProfile.currentRangeUnit.match(/year|month/)) {
            el = containerEl.querySelector(`[data-date="${formatIsoMonthStr(dateProfile.currentDate)}-01"]`);
            // even if view is month-based, first-of-month might be hidden...
        }
        if (!el) {
            el = containerEl.querySelector(`[data-date="${formatDayString(dateProfile.currentDate)}"]`);
            // could still be hidden if an interior-view hidden day
        }
        return el;
    }

    class DayTableSlicer extends Slicer {
        constructor() {
            super(...arguments);
            this.forceDayIfListItem = true;
        }
        sliceRange(dateRange, dayTableModel) {
            return dayTableModel.sliceRange(dateRange);
        }
    }

    class DayTable extends DateComponent {
        constructor() {
            super(...arguments);
            this.slicer = new DayTableSlicer();
            this.tableRef = d();
        }
        render() {
            let {
                props,
                context
            } = this;
            return (y(Table, Object.assign({
                ref: this.tableRef
            }, this.slicer.sliceProps(props, props.dateProfile, props.nextDayThreshold, context, props.dayTableModel), {
                dateProfile: props.dateProfile,
                cells: props.dayTableModel.cells,
                colGroupNode: props.colGroupNode,
                tableMinWidth: props.tableMinWidth,
                renderRowIntro: props.renderRowIntro,
                dayMaxEvents: props.dayMaxEvents,
                dayMaxEventRows: props.dayMaxEventRows,
                showWeekNumbers: props.showWeekNumbers,
                expandRows: props.expandRows,
                headerAlignElRef: props.headerAlignElRef,
                clientWidth: props.clientWidth,
                clientHeight: props.clientHeight,
                forPrint: props.forPrint
            })));
        }
    }

    class DayTableView extends TableView {
        constructor() {
            super(...arguments);
            this.buildDayTableModel = memoize(buildDayTableModel);
            this.headerRef = d();
            this.tableRef = d();
            // can't override any lifecycle methods from parent
        }
        render() {
            let {
                options,
                dateProfileGenerator
            } = this.context;
            let {
                props
            } = this;
            let dayTableModel = this.buildDayTableModel(props.dateProfile, dateProfileGenerator);
            let headerContent = options.dayHeaders && (y(DayHeader, {
                ref: this.headerRef,
                dateProfile: props.dateProfile,
                dates: dayTableModel.headerDates,
                datesRepDistinctDays: dayTableModel.rowCnt === 1
            }));
            let bodyContent = (contentArg) => (y(DayTable, {
                ref: this.tableRef,
                dateProfile: props.dateProfile,
                dayTableModel: dayTableModel,
                businessHours: props.businessHours,
                dateSelection: props.dateSelection,
                eventStore: props.eventStore,
                eventUiBases: props.eventUiBases,
                eventSelection: props.eventSelection,
                eventDrag: props.eventDrag,
                eventResize: props.eventResize,
                nextDayThreshold: options.nextDayThreshold,
                colGroupNode: contentArg.tableColGroupNode,
                tableMinWidth: contentArg.tableMinWidth,
                dayMaxEvents: options.dayMaxEvents,
                dayMaxEventRows: options.dayMaxEventRows,
                showWeekNumbers: options.weekNumbers,
                expandRows: !props.isHeightAuto,
                headerAlignElRef: this.headerElRef,
                clientWidth: contentArg.clientWidth,
                clientHeight: contentArg.clientHeight,
                forPrint: props.forPrint
            }));
            return options.dayMinWidth ?
                this.renderHScrollLayout(headerContent, bodyContent, dayTableModel.colCnt, options.dayMinWidth) :
                this.renderSimpleLayout(headerContent, bodyContent);
        }
    }

    function buildDayTableModel(dateProfile, dateProfileGenerator) {
        let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
        return new DayTableModel(daySeries, /year|month|week/.test(dateProfile.currentRangeUnit));
    }

    class TableDateProfileGenerator extends DateProfileGenerator {
        // Computes the date range that will be rendered
        buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay) {
            let renderRange = super.buildRenderRange(currentRange, currentRangeUnit, isRangeAllDay);
            let {
                props
            } = this;
            return buildDayTableRenderRange({
                currentRange: renderRange,
                snapToWeek: /^(year|month)$/.test(currentRangeUnit),
                fixedWeekCount: props.fixedWeekCount,
                dateEnv: props.dateEnv,
            });
        }
    }

    function buildDayTableRenderRange(props) {
        let {
            dateEnv,
            currentRange
        } = props;
        let {
            start,
            end
        } = currentRange;
        let endOfWeek;
        // year and month views should be aligned with weeks. this is already done for week
        if (props.snapToWeek) {
            start = dateEnv.startOfWeek(start);
            // make end-of-week if not already
            endOfWeek = dateEnv.startOfWeek(end);
            if (endOfWeek.valueOf() !== end.valueOf()) {
                end = addWeeks(endOfWeek, 1);
            }
        }
        // ensure 6 weeks
        if (props.fixedWeekCount) {
            // TODO: instead of these date-math gymnastics (for multimonth view),
            // compute dateprofiles of all months, then use start of first and end of last.
            let lastMonthRenderStart = dateEnv.startOfWeek(dateEnv.startOfMonth(addDays(currentRange.end, -1)));
            let rowCnt = Math.ceil( // could be partial weeks due to hiddenDays
                diffWeeks(lastMonthRenderStart, end));
            end = addWeeks(end, 6 - rowCnt);
        }
        return {
            start,
            end
        };
    }

    var css_248z$3 = ":root{--fc-daygrid-event-dot-width:8px}.fc-daygrid-day-events:after,.fc-daygrid-day-events:before,.fc-daygrid-day-frame:after,.fc-daygrid-day-frame:before,.fc-daygrid-event-harness:after,.fc-daygrid-event-harness:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-body{position:relative;z-index:1}.fc .fc-daygrid-day.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-daygrid-day-frame{min-height:100%;position:relative}.fc .fc-daygrid-day-top{display:flex;flex-direction:row-reverse}.fc .fc-day-other .fc-daygrid-day-top{opacity:.3}.fc .fc-daygrid-day-number{padding:4px;position:relative;z-index:4}.fc .fc-daygrid-month-start{font-size:1.1em;font-weight:700}.fc .fc-daygrid-day-events{margin-top:1px}.fc .fc-daygrid-body-balanced .fc-daygrid-day-events{left:0;position:absolute;right:0}.fc .fc-daygrid-body-unbalanced .fc-daygrid-day-events{min-height:2em;position:relative}.fc .fc-daygrid-body-natural .fc-daygrid-day-events{margin-bottom:1em}.fc .fc-daygrid-event-harness{position:relative}.fc .fc-daygrid-event-harness-abs{left:0;position:absolute;right:0;top:0}.fc .fc-daygrid-bg-harness{bottom:0;position:absolute;top:0}.fc .fc-daygrid-day-bg .fc-non-business{z-index:1}.fc .fc-daygrid-day-bg .fc-bg-event{z-index:2}.fc .fc-daygrid-day-bg .fc-highlight{z-index:3}.fc .fc-daygrid-event{margin-top:1px;z-index:6}.fc .fc-daygrid-event.fc-event-mirror{z-index:7}.fc .fc-daygrid-day-bottom{font-size:.85em;margin:0 2px}.fc .fc-daygrid-day-bottom:after,.fc .fc-daygrid-day-bottom:before{clear:both;content:\"\";display:table}.fc .fc-daygrid-more-link{border-radius:3px;cursor:pointer;line-height:1;margin-top:1px;max-width:100%;overflow:hidden;padding:2px;position:relative;white-space:nowrap;z-index:4}.fc .fc-daygrid-more-link:hover{background-color:rgba(0,0,0,.1)}.fc .fc-daygrid-week-number{background-color:var(--fc-neutral-bg-color);color:var(--fc-neutral-text-color);min-width:1.5em;padding:2px;position:absolute;text-align:center;top:0;z-index:5}.fc .fc-more-popover .fc-popover-body{min-width:220px;padding:10px}.fc-direction-ltr .fc-daygrid-event.fc-event-start,.fc-direction-rtl .fc-daygrid-event.fc-event-end{margin-left:2px}.fc-direction-ltr .fc-daygrid-event.fc-event-end,.fc-direction-rtl .fc-daygrid-event.fc-event-start{margin-right:2px}.fc-direction-ltr .fc-daygrid-more-link{float:left}.fc-direction-ltr .fc-daygrid-week-number{border-radius:0 0 3px 0;left:0}.fc-direction-rtl .fc-daygrid-more-link{float:right}.fc-direction-rtl .fc-daygrid-week-number{border-radius:0 0 0 3px;right:0}.fc-liquid-hack .fc-daygrid-day-frame{position:static}.fc-daygrid-event{border-radius:3px;font-size:var(--fc-small-font-size);position:relative;white-space:nowrap}.fc-daygrid-block-event .fc-event-time{font-weight:700}.fc-daygrid-block-event .fc-event-time,.fc-daygrid-block-event .fc-event-title{padding:1px}.fc-daygrid-dot-event{align-items:center;display:flex;padding:2px 0}.fc-daygrid-dot-event .fc-event-title{flex-grow:1;flex-shrink:1;font-weight:700;min-width:0;overflow:hidden}.fc-daygrid-dot-event.fc-event-mirror,.fc-daygrid-dot-event:hover{background:rgba(0,0,0,.1)}.fc-daygrid-dot-event.fc-event-selected:before{bottom:-10px;top:-10px}.fc-daygrid-event-dot{border:calc(var(--fc-daygrid-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-daygrid-event-dot-width)/2);box-sizing:content-box;height:0;margin:0 4px;width:0}.fc-direction-ltr .fc-daygrid-event .fc-event-time{margin-right:3px}.fc-direction-rtl .fc-daygrid-event .fc-event-time{margin-left:3px}";
    injectStyles(css_248z$3);

    var index$3 = createPlugin({
        name: '@fullcalendar/daygrid',
        initialView: 'dayGridMonth',
        views: {
            dayGrid: {
                component: DayTableView,
                dateProfileGeneratorClass: TableDateProfileGenerator,
            },
            dayGridDay: {
                type: 'dayGrid',
                duration: {
                    days: 1
                },
            },
            dayGridWeek: {
                type: 'dayGrid',
                duration: {
                    weeks: 1
                },
            },
            dayGridMonth: {
                type: 'dayGrid',
                duration: {
                    months: 1
                },
                fixedWeekCount: true,
            },
            dayGridYear: {
                type: 'dayGrid',
                duration: {
                    years: 1
                },
            },
        },
    });

    class AllDaySplitter extends Splitter {
        getKeyInfo() {
            return {
                allDay: {},
                timed: {},
            };
        }
        getKeysForDateSpan(dateSpan) {
            if (dateSpan.allDay) {
                return ['allDay'];
            }
            return ['timed'];
        }
        getKeysForEventDef(eventDef) {
            if (!eventDef.allDay) {
                return ['timed'];
            }
            if (hasBgRendering(eventDef)) {
                return ['timed', 'allDay'];
            }
            return ['allDay'];
        }
    }

    const DEFAULT_SLAT_LABEL_FORMAT = createFormatter({
        hour: 'numeric',
        minute: '2-digit',
        omitZeroMinute: true,
        meridiem: 'short',
    });

    function TimeColsAxisCell(props) {
        let classNames = [
            'fc-timegrid-slot',
            'fc-timegrid-slot-label',
            props.isLabeled ? 'fc-scrollgrid-shrink' : 'fc-timegrid-slot-minor',
        ];
        return (y(ViewContextType.Consumer, null, (context) => {
            if (!props.isLabeled) {
                return (y("td", {
                    className: classNames.join(' '),
                    "data-time": props.isoTimeStr
                }));
            }
            let {
                dateEnv,
                options,
                viewApi
            } = context;
            let labelFormat = // TODO: fully pre-parse
                options.slotLabelFormat == null ? DEFAULT_SLAT_LABEL_FORMAT :
                Array.isArray(options.slotLabelFormat) ? createFormatter(options.slotLabelFormat[0]) :
                createFormatter(options.slotLabelFormat);
            let renderProps = {
                level: 0,
                time: props.time,
                date: dateEnv.toDate(props.date),
                view: viewApi,
                text: dateEnv.format(props.date, labelFormat),
            };
            return (y(ContentContainer, {
                elTag: "td",
                elClasses: classNames,
                elAttrs: {
                    'data-time': props.isoTimeStr,
                },
                renderProps: renderProps,
                generatorName: "slotLabelContent",
                customGenerator: options.slotLabelContent,
                defaultGenerator: renderInnerContent$1,
                classNameGenerator: options.slotLabelClassNames,
                didMount: options.slotLabelDidMount,
                willUnmount: options.slotLabelWillUnmount
            }, (InnerContent) => (y("div", {
                    className: "fc-timegrid-slot-label-frame fc-scrollgrid-shrink-frame"
                },
                y(InnerContent, {
                    elTag: "div",
                    elClasses: [
                        'fc-timegrid-slot-label-cushion',
                        'fc-scrollgrid-shrink-cushion',
                    ]
                })))));
        }));
    }

    function renderInnerContent$1(props) {
        return props.text;
    }

    class TimeBodyAxis extends BaseComponent {
        render() {
            return this.props.slatMetas.map((slatMeta) => (y("tr", {
                    key: slatMeta.key
                },
                y(TimeColsAxisCell, Object.assign({}, slatMeta)))));
        }
    }

    const DEFAULT_WEEK_NUM_FORMAT = createFormatter({
        week: 'short'
    });
    const AUTO_ALL_DAY_MAX_EVENT_ROWS = 5;
    class TimeColsView extends DateComponent {
        constructor() {
            super(...arguments);
            this.allDaySplitter = new AllDaySplitter(); // for use by subclasses
            this.headerElRef = d();
            this.rootElRef = d();
            this.scrollerElRef = d();
            this.state = {
                slatCoords: null,
            };
            this.handleScrollTopRequest = (scrollTop) => {
                let scrollerEl = this.scrollerElRef.current;
                if (scrollerEl) { // TODO: not sure how this could ever be null. weirdness with the reducer
                    scrollerEl.scrollTop = scrollTop;
                }
            };
            /* Header Render Methods
            ------------------------------------------------------------------------------------------------------------------*/
            this.renderHeadAxis = (rowKey, frameHeight = '') => {
                let {
                    options
                } = this.context;
                let {
                    dateProfile
                } = this.props;
                let range = dateProfile.renderRange;
                let dayCnt = diffDays(range.start, range.end);
                // only do in day views (to avoid doing in week views that dont need it)
                let navLinkAttrs = (dayCnt === 1) ?
                    buildNavLinkAttrs(this.context, range.start, 'week') :
                    {};
                if (options.weekNumbers && rowKey === 'day') {
                    return (y(WeekNumberContainer, {
                        elTag: "th",
                        elClasses: [
                            'fc-timegrid-axis',
                            'fc-scrollgrid-shrink',
                        ],
                        elAttrs: {
                            'aria-hidden': true,
                        },
                        date: range.start,
                        defaultFormat: DEFAULT_WEEK_NUM_FORMAT
                    }, (InnerContent) => (y("div", {
                            className: [
                                'fc-timegrid-axis-frame',
                                'fc-scrollgrid-shrink-frame',
                                'fc-timegrid-axis-frame-liquid',
                            ].join(' '),
                            style: {
                                height: frameHeight
                            }
                        },
                        y(InnerContent, {
                            elTag: "a",
                            elClasses: [
                                'fc-timegrid-axis-cushion',
                                'fc-scrollgrid-shrink-cushion',
                                'fc-scrollgrid-sync-inner',
                            ],
                            elAttrs: navLinkAttrs
                        })))));
                }
                return (y("th", {
                        "aria-hidden": true,
                        className: "fc-timegrid-axis"
                    },
                    y("div", {
                        className: "fc-timegrid-axis-frame",
                        style: {
                            height: frameHeight
                        }
                    })));
            };
            /* Table Component Render Methods
            ------------------------------------------------------------------------------------------------------------------*/
            // only a one-way height sync. we don't send the axis inner-content height to the DayGrid,
            // but DayGrid still needs to have classNames on inner elements in order to measure.
            this.renderTableRowAxis = (rowHeight) => {
                let {
                    options,
                    viewApi
                } = this.context;
                let renderProps = {
                    text: options.allDayText,
                    view: viewApi,
                };
                return (
                    // TODO: make reusable hook. used in list view too
                    y(ContentContainer, {
                        elTag: "td",
                        elClasses: [
                            'fc-timegrid-axis',
                            'fc-scrollgrid-shrink',
                        ],
                        elAttrs: {
                            'aria-hidden': true,
                        },
                        renderProps: renderProps,
                        generatorName: "allDayContent",
                        customGenerator: options.allDayContent,
                        defaultGenerator: renderAllDayInner$1,
                        classNameGenerator: options.allDayClassNames,
                        didMount: options.allDayDidMount,
                        willUnmount: options.allDayWillUnmount
                    }, (InnerContent) => (y("div", {
                            className: [
                                'fc-timegrid-axis-frame',
                                'fc-scrollgrid-shrink-frame',
                                rowHeight == null ? ' fc-timegrid-axis-frame-liquid' : '',
                            ].join(' '),
                            style: {
                                height: rowHeight
                            }
                        },
                        y(InnerContent, {
                            elTag: "span",
                            elClasses: [
                                'fc-timegrid-axis-cushion',
                                'fc-scrollgrid-shrink-cushion',
                                'fc-scrollgrid-sync-inner',
                            ]
                        })))));
            };
            this.handleSlatCoords = (slatCoords) => {
                this.setState({
                    slatCoords
                });
            };
        }
        // rendering
        // ----------------------------------------------------------------------------------------------------
        renderSimpleLayout(headerRowContent, allDayContent, timeContent) {
            let {
                context,
                props
            } = this;
            let sections = [];
            let stickyHeaderDates = getStickyHeaderDates(context.options);
            if (headerRowContent) {
                sections.push({
                    type: 'header',
                    key: 'header',
                    isSticky: stickyHeaderDates,
                    chunk: {
                        elRef: this.headerElRef,
                        tableClassName: 'fc-col-header',
                        rowContent: headerRowContent,
                    },
                });
            }
            if (allDayContent) {
                sections.push({
                    type: 'body',
                    key: 'all-day',
                    chunk: {
                        content: allDayContent
                    },
                });
                sections.push({
                    type: 'body',
                    key: 'all-day-divider',
                    outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
                        y("tr", {
                                role: "presentation",
                                className: "fc-scrollgrid-section"
                            },
                            y("td", {
                                className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded')
                            }))),
                });
            }
            sections.push({
                type: 'body',
                key: 'body',
                liquid: true,
                expandRows: Boolean(context.options.expandRows),
                chunk: {
                    scrollerElRef: this.scrollerElRef,
                    content: timeContent,
                },
            });
            return (y(ViewContainer, {
                    elRef: this.rootElRef,
                    elClasses: ['fc-timegrid'],
                    viewSpec: context.viewSpec
                },
                y(SimpleScrollGrid, {
                    liquid: !props.isHeightAuto && !props.forPrint,
                    collapsibleWidth: props.forPrint,
                    cols: [{
                        width: 'shrink'
                    }],
                    sections: sections
                })));
        }
        renderHScrollLayout(headerRowContent, allDayContent, timeContent, colCnt, dayMinWidth, slatMetas, slatCoords) {
            let ScrollGrid = this.context.pluginHooks.scrollGridImpl;
            if (!ScrollGrid) {
                throw new Error('No ScrollGrid implementation');
            }
            let {
                context,
                props
            } = this;
            let stickyHeaderDates = !props.forPrint && getStickyHeaderDates(context.options);
            let stickyFooterScrollbar = !props.forPrint && getStickyFooterScrollbar(context.options);
            let sections = [];
            if (headerRowContent) {
                sections.push({
                    type: 'header',
                    key: 'header',
                    isSticky: stickyHeaderDates,
                    syncRowHeights: true,
                    chunks: [{
                            key: 'axis',
                            rowContent: (arg) => (y("tr", {
                                role: "presentation"
                            }, this.renderHeadAxis('day', arg.rowSyncHeights[0]))),
                        },
                        {
                            key: 'cols',
                            elRef: this.headerElRef,
                            tableClassName: 'fc-col-header',
                            rowContent: headerRowContent,
                        },
                    ],
                });
            }
            if (allDayContent) {
                sections.push({
                    type: 'body',
                    key: 'all-day',
                    syncRowHeights: true,
                    chunks: [{
                            key: 'axis',
                            rowContent: (contentArg) => (y("tr", {
                                role: "presentation"
                            }, this.renderTableRowAxis(contentArg.rowSyncHeights[0]))),
                        },
                        {
                            key: 'cols',
                            content: allDayContent,
                        },
                    ],
                });
                sections.push({
                    key: 'all-day-divider',
                    type: 'body',
                    outerContent: ( // TODO: rename to cellContent so don't need to define <tr>?
                        y("tr", {
                                role: "presentation",
                                className: "fc-scrollgrid-section"
                            },
                            y("td", {
                                colSpan: 2,
                                className: 'fc-timegrid-divider ' + context.theme.getClass('tableCellShaded')
                            }))),
                });
            }
            let isNowIndicator = context.options.nowIndicator;
            sections.push({
                type: 'body',
                key: 'body',
                liquid: true,
                expandRows: Boolean(context.options.expandRows),
                chunks: [{
                        key: 'axis',
                        content: (arg) => (
                            // TODO: make this now-indicator arrow more DRY with TimeColsContent
                            y("div", {
                                    className: "fc-timegrid-axis-chunk"
                                },
                                y("table", {
                                        "aria-hidden": true,
                                        style: {
                                            height: arg.expandRows ? arg.clientHeight : ''
                                        }
                                    },
                                    arg.tableColGroupNode,
                                    y("tbody", null,
                                        y(TimeBodyAxis, {
                                            slatMetas: slatMetas
                                        }))),
                                y("div", {
                                        className: "fc-timegrid-now-indicator-container"
                                    },
                                    y(NowTimer, {
                                        unit: isNowIndicator ? 'minute' : 'day' /* hacky */
                                    }, (nowDate) => {
                                        let nowIndicatorTop = isNowIndicator &&
                                            slatCoords &&
                                            slatCoords.safeComputeTop(nowDate); // might return void
                                        if (typeof nowIndicatorTop === 'number') {
                                            return (y(NowIndicatorContainer, {
                                                elClasses: ['fc-timegrid-now-indicator-arrow'],
                                                elStyle: {
                                                    top: nowIndicatorTop
                                                },
                                                isAxis: true,
                                                date: nowDate
                                            }));
                                        }
                                        return null;
                                    })))),
                    },
                    {
                        key: 'cols',
                        scrollerElRef: this.scrollerElRef,
                        content: timeContent,
                    },
                ],
            });
            if (stickyFooterScrollbar) {
                sections.push({
                    key: 'footer',
                    type: 'footer',
                    isSticky: true,
                    chunks: [{
                            key: 'axis',
                            content: renderScrollShim,
                        },
                        {
                            key: 'cols',
                            content: renderScrollShim,
                        },
                    ],
                });
            }
            return (y(ViewContainer, {
                    elRef: this.rootElRef,
                    elClasses: ['fc-timegrid'],
                    viewSpec: context.viewSpec
                },
                y(ScrollGrid, {
                    liquid: !props.isHeightAuto && !props.forPrint,
                    forPrint: props.forPrint,
                    collapsibleWidth: false,
                    colGroups: [{
                            width: 'shrink',
                            cols: [{
                                width: 'shrink'
                            }]
                        },
                        {
                            cols: [{
                                span: colCnt,
                                minWidth: dayMinWidth
                            }]
                        },
                    ],
                    sections: sections
                })));
        }
        /* Dimensions
        ------------------------------------------------------------------------------------------------------------------*/
        getAllDayMaxEventProps() {
            let {
                dayMaxEvents,
                dayMaxEventRows
            } = this.context.options;
            if (dayMaxEvents === true || dayMaxEventRows === true) { // is auto?
                dayMaxEvents = undefined;
                dayMaxEventRows = AUTO_ALL_DAY_MAX_EVENT_ROWS; // make sure "auto" goes to a real number
            }
            return {
                dayMaxEvents,
                dayMaxEventRows
            };
        }
    }

    function renderAllDayInner$1(renderProps) {
        return renderProps.text;
    }

    class TimeColsSlatsCoords {
        constructor(positions, dateProfile, slotDuration) {
            this.positions = positions;
            this.dateProfile = dateProfile;
            this.slotDuration = slotDuration;
        }
        safeComputeTop(date) {
            let {
                dateProfile
            } = this;
            if (rangeContainsMarker(dateProfile.currentRange, date)) {
                let startOfDayDate = startOfDay(date);
                let timeMs = date.valueOf() - startOfDayDate.valueOf();
                if (timeMs >= asRoughMs(dateProfile.slotMinTime) &&
                    timeMs < asRoughMs(dateProfile.slotMaxTime)) {
                    return this.computeTimeTop(createDuration(timeMs));
                }
            }
            return null;
        }
        // Computes the top coordinate, relative to the bounds of the grid, of the given date.
        // A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
        computeDateTop(when, startOfDayDate) {
            if (!startOfDayDate) {
                startOfDayDate = startOfDay(when);
            }
            return this.computeTimeTop(createDuration(when.valueOf() - startOfDayDate.valueOf()));
        }
        // Computes the top coordinate, relative to the bounds of the grid, of the given time (a Duration).
        // This is a makeshify way to compute the time-top. Assumes all slatMetas dates are uniform.
        // Eventually allow computation with arbirary slat dates.
        computeTimeTop(duration) {
            let {
                positions,
                dateProfile
            } = this;
            let len = positions.els.length;
            // floating-point value of # of slots covered
            let slatCoverage = (duration.milliseconds - asRoughMs(dateProfile.slotMinTime)) / asRoughMs(this.slotDuration);
            let slatIndex;
            let slatRemainder;
            // compute a floating-point number for how many slats should be progressed through.
            // from 0 to number of slats (inclusive)
            // constrained because slotMinTime/slotMaxTime might be customized.
            slatCoverage = Math.max(0, slatCoverage);
            slatCoverage = Math.min(len, slatCoverage);
            // an integer index of the furthest whole slat
            // from 0 to number slats (*exclusive*, so len-1)
            slatIndex = Math.floor(slatCoverage);
            slatIndex = Math.min(slatIndex, len - 1);
            // how much further through the slatIndex slat (from 0.0-1.0) must be covered in addition.
            // could be 1.0 if slatCoverage is covering *all* the slots
            slatRemainder = slatCoverage - slatIndex;
            return positions.tops[slatIndex] +
                positions.getHeight(slatIndex) * slatRemainder;
        }
    }

    class TimeColsSlatsBody extends BaseComponent {
        render() {
            let {
                props,
                context
            } = this;
            let {
                options
            } = context;
            let {
                slatElRefs
            } = props;
            return (y("tbody", null, props.slatMetas.map((slatMeta, i) => {
                let renderProps = {
                    time: slatMeta.time,
                    date: context.dateEnv.toDate(slatMeta.date),
                    view: context.viewApi,
                };
                return (y("tr", {
                        key: slatMeta.key,
                        ref: slatElRefs.createRef(slatMeta.key)
                    },
                    props.axis && (y(TimeColsAxisCell, Object.assign({}, slatMeta))),
                    y(ContentContainer, {
                        elTag: "td",
                        elClasses: [
                            'fc-timegrid-slot',
                            'fc-timegrid-slot-lane',
                            !slatMeta.isLabeled && 'fc-timegrid-slot-minor',
                        ],
                        elAttrs: {
                            'data-time': slatMeta.isoTimeStr,
                        },
                        renderProps: renderProps,
                        generatorName: "slotLaneContent",
                        customGenerator: options.slotLaneContent,
                        classNameGenerator: options.slotLaneClassNames,
                        didMount: options.slotLaneDidMount,
                        willUnmount: options.slotLaneWillUnmount
                    })));
            })));
        }
    }

    /*
    for the horizontal "slats" that run width-wise. Has a time axis on a side. Depends on RTL.
    */
    class TimeColsSlats extends BaseComponent {
        constructor() {
            super(...arguments);
            this.rootElRef = d();
            this.slatElRefs = new RefMap();
        }
        render() {
            let {
                props,
                context
            } = this;
            return (y("div", {
                    ref: this.rootElRef,
                    className: "fc-timegrid-slots"
                },
                y("table", {
                        "aria-hidden": true,
                        className: context.theme.getClass('table'),
                        style: {
                            minWidth: props.tableMinWidth,
                            width: props.clientWidth,
                            height: props.minHeight,
                        }
                    },
                    props.tableColGroupNode /* relies on there only being a single <col> for the axis */ ,
                    y(TimeColsSlatsBody, {
                        slatElRefs: this.slatElRefs,
                        axis: props.axis,
                        slatMetas: props.slatMetas
                    }))));
        }
        componentDidMount() {
            this.updateSizing();
        }
        componentDidUpdate() {
            this.updateSizing();
        }
        componentWillUnmount() {
            if (this.props.onCoords) {
                this.props.onCoords(null);
            }
        }
        updateSizing() {
            let {
                context,
                props
            } = this;
            if (props.onCoords &&
                props.clientWidth !== null // means sizing has stabilized
            ) {
                let rootEl = this.rootElRef.current;
                if (rootEl.offsetHeight) { // not hidden by css
                    props.onCoords(new TimeColsSlatsCoords(new PositionCache(this.rootElRef.current, collectSlatEls(this.slatElRefs.currentMap, props.slatMetas), false, true), this.props.dateProfile, context.options.slotDuration));
                }
            }
        }
    }

    function collectSlatEls(elMap, slatMetas) {
        return slatMetas.map((slatMeta) => elMap[slatMeta.key]);
    }

    function splitSegsByCol(segs, colCnt) {
        let segsByCol = [];
        let i;
        for (i = 0; i < colCnt; i += 1) {
            segsByCol.push([]);
        }
        if (segs) {
            for (i = 0; i < segs.length; i += 1) {
                segsByCol[segs[i].col].push(segs[i]);
            }
        }
        return segsByCol;
    }

    function splitInteractionByCol(ui, colCnt) {
        let byRow = [];
        if (!ui) {
            for (let i = 0; i < colCnt; i += 1) {
                byRow[i] = null;
            }
        } else {
            for (let i = 0; i < colCnt; i += 1) {
                byRow[i] = {
                    affectedInstances: ui.affectedInstances,
                    isEvent: ui.isEvent,
                    segs: [],
                };
            }
            for (let seg of ui.segs) {
                byRow[seg.col].segs.push(seg);
            }
        }
        return byRow;
    }

    class TimeColMoreLink extends BaseComponent {
        render() {
            let {
                props
            } = this;
            return (y(MoreLinkContainer, {
                elClasses: ['fc-timegrid-more-link'],
                elStyle: {
                    top: props.top,
                    bottom: props.bottom,
                },
                allDayDate: null,
                moreCnt: props.hiddenSegs.length,
                allSegs: props.hiddenSegs,
                hiddenSegs: props.hiddenSegs,
                extraDateSpan: props.extraDateSpan,
                dateProfile: props.dateProfile,
                todayRange: props.todayRange,
                popoverContent: () => renderPlainFgSegs(props.hiddenSegs, props),
                defaultGenerator: renderMoreLinkInner,
                forceTimed: true
            }, (InnerContent) => (y(InnerContent, {
                elTag: "div",
                elClasses: ['fc-timegrid-more-link-inner', 'fc-sticky']
            }))));
        }
    }

    function renderMoreLinkInner(props) {
        return props.shortText;
    }

    // segInputs assumed sorted
    function buildPositioning(segInputs, strictOrder, maxStackCnt) {
        let hierarchy = new SegHierarchy();
        if (strictOrder != null) {
            hierarchy.strictOrder = strictOrder;
        }
        if (maxStackCnt != null) {
            hierarchy.maxStackCnt = maxStackCnt;
        }
        let hiddenEntries = hierarchy.addSegs(segInputs);
        let hiddenGroups = groupIntersectingEntries(hiddenEntries);
        let web = buildWeb(hierarchy);
        web = stretchWeb(web, 1); // all levelCoords/thickness will have 0.0-1.0
        let segRects = webToRects(web);
        return {
            segRects,
            hiddenGroups
        };
    }

    function buildWeb(hierarchy) {
        const {
            entriesByLevel
        } = hierarchy;
        const buildNode = cacheable((level, lateral) => level + ':' + lateral, (level, lateral) => {
            let siblingRange = findNextLevelSegs(hierarchy, level, lateral);
            let nextLevelRes = buildNodes(siblingRange, buildNode);
            let entry = entriesByLevel[level][lateral];
            return [
                Object.assign(Object.assign({}, entry), {
                    nextLevelNodes: nextLevelRes[0]
                }),
                entry.thickness + nextLevelRes[1], // the pressure builds
            ];
        });
        return buildNodes(entriesByLevel.length ?
            {
                level: 0,
                lateralStart: 0,
                lateralEnd: entriesByLevel[0].length
            } :
            null, buildNode)[0];
    }

    function buildNodes(siblingRange, buildNode) {
        if (!siblingRange) {
            return [
                [], 0
            ];
        }
        let {
            level,
            lateralStart,
            lateralEnd
        } = siblingRange;
        let lateral = lateralStart;
        let pairs = [];
        while (lateral < lateralEnd) {
            pairs.push(buildNode(level, lateral));
            lateral += 1;
        }
        pairs.sort(cmpDescPressures);
        return [
            pairs.map(extractNode),
            pairs[0][1], // first item's pressure
        ];
    }

    function cmpDescPressures(a, b) {
        return b[1] - a[1];
    }

    function extractNode(a) {
        return a[0];
    }

    function findNextLevelSegs(hierarchy, subjectLevel, subjectLateral) {
        let {
            levelCoords,
            entriesByLevel
        } = hierarchy;
        let subjectEntry = entriesByLevel[subjectLevel][subjectLateral];
        let afterSubject = levelCoords[subjectLevel] + subjectEntry.thickness;
        let levelCnt = levelCoords.length;
        let level = subjectLevel;
        // skip past levels that are too high up
        for (; level < levelCnt && levelCoords[level] < afterSubject; level += 1)
        ; // do nothing
        for (; level < levelCnt; level += 1) {
            let entries = entriesByLevel[level];
            let entry;
            let searchIndex = binarySearch(entries, subjectEntry.span.start, getEntrySpanEnd);
            let lateralStart = searchIndex[0] + searchIndex[1]; // if exact match (which doesn't collide), go to next one
            let lateralEnd = lateralStart;
            while ( // loop through entries that horizontally intersect
                (entry = entries[lateralEnd]) && // but not past the whole seg list
                entry.span.start < subjectEntry.span.end) {
                lateralEnd += 1;
            }
            if (lateralStart < lateralEnd) {
                return {
                    level,
                    lateralStart,
                    lateralEnd
                };
            }
        }
        return null;
    }

    function stretchWeb(topLevelNodes, totalThickness) {
        const stretchNode = cacheable((node, startCoord, prevThickness) => buildEntryKey(node), (node, startCoord, prevThickness) => {
            let {
                nextLevelNodes,
                thickness
            } = node;
            let allThickness = thickness + prevThickness;
            let thicknessFraction = thickness / allThickness;
            let endCoord;
            let newChildren = [];
            if (!nextLevelNodes.length) {
                endCoord = totalThickness;
            } else {
                for (let childNode of nextLevelNodes) {
                    if (endCoord === undefined) {
                        let res = stretchNode(childNode, startCoord, allThickness);
                        endCoord = res[0];
                        newChildren.push(res[1]);
                    } else {
                        let res = stretchNode(childNode, endCoord, 0);
                        newChildren.push(res[1]);
                    }
                }
            }
            let newThickness = (endCoord - startCoord) * thicknessFraction;
            return [endCoord - newThickness, Object.assign(Object.assign({}, node), {
                thickness: newThickness,
                nextLevelNodes: newChildren
            })];
        });
        return topLevelNodes.map((node) => stretchNode(node, 0, 0)[1]);
    }
    // not sorted in any particular order
    function webToRects(topLevelNodes) {
        let rects = [];
        const processNode = cacheable((node, levelCoord, stackDepth) => buildEntryKey(node), (node, levelCoord, stackDepth) => {
            let rect = Object.assign(Object.assign({}, node), {
                levelCoord,
                stackDepth,
                stackForward: 0
            });
            rects.push(rect);
            return (rect.stackForward = processNodes(node.nextLevelNodes, levelCoord + node.thickness, stackDepth + 1) + 1);
        });

        function processNodes(nodes, levelCoord, stackDepth) {
            let stackForward = 0;
            for (let node of nodes) {
                stackForward = Math.max(processNode(node, levelCoord, stackDepth), stackForward);
            }
            return stackForward;
        }
        processNodes(topLevelNodes, 0, 0);
        return rects; // TODO: sort rects by levelCoord to be consistent with toRects?
    }
    // TODO: move to general util
    function cacheable(keyFunc, workFunc) {
        const cache = {};
        return (...args) => {
            let key = keyFunc(...args);
            return (key in cache) ?
                cache[key] :
                (cache[key] = workFunc(...args));
        };
    }

    function computeSegVCoords(segs, colDate, slatCoords = null, eventMinHeight = 0) {
        let vcoords = [];
        if (slatCoords) {
            for (let i = 0; i < segs.length; i += 1) {
                let seg = segs[i];
                let spanStart = slatCoords.computeDateTop(seg.start, colDate);
                let spanEnd = Math.max(spanStart + (eventMinHeight || 0), // :(
                    slatCoords.computeDateTop(seg.end, colDate));
                vcoords.push({
                    start: Math.round(spanStart),
                    end: Math.round(spanEnd), //
                });
            }
        }
        return vcoords;
    }

    function computeFgSegPlacements(segs, segVCoords, // might not have for every seg
        eventOrderStrict, eventMaxStack) {
        let segInputs = [];
        let dumbSegs = []; // segs without coords
        for (let i = 0; i < segs.length; i += 1) {
            let vcoords = segVCoords[i];
            if (vcoords) {
                segInputs.push({
                    index: i,
                    thickness: 1,
                    span: vcoords,
                });
            } else {
                dumbSegs.push(segs[i]);
            }
        }
        let {
            segRects,
            hiddenGroups
        } = buildPositioning(segInputs, eventOrderStrict, eventMaxStack);
        let segPlacements = [];
        for (let segRect of segRects) {
            segPlacements.push({
                seg: segs[segRect.index],
                rect: segRect,
            });
        }
        for (let dumbSeg of dumbSegs) {
            segPlacements.push({
                seg: dumbSeg,
                rect: null
            });
        }
        return {
            segPlacements,
            hiddenGroups
        };
    }

    const DEFAULT_TIME_FORMAT$1 = createFormatter({
        hour: 'numeric',
        minute: '2-digit',
        meridiem: false,
    });
    class TimeColEvent extends BaseComponent {
        render() {
            return (y(StandardEvent, Object.assign({}, this.props, {
                elClasses: [
                    'fc-timegrid-event',
                    'fc-v-event',
                    this.props.isShort && 'fc-timegrid-event-short',
                ],
                defaultTimeFormat: DEFAULT_TIME_FORMAT$1
            })));
        }
    }

    class TimeCol extends BaseComponent {
        constructor() {
            super(...arguments);
            this.sortEventSegs = memoize(sortEventSegs);
        }
        // TODO: memoize event-placement?
        render() {
            let {
                props,
                context
            } = this;
            let {
                options
            } = context;
            let isSelectMirror = options.selectMirror;
            let mirrorSegs = // yuck
                (props.eventDrag && props.eventDrag.segs) ||
                (props.eventResize && props.eventResize.segs) ||
                (isSelectMirror && props.dateSelectionSegs) || [];
            let interactionAffectedInstances = // TODO: messy way to compute this
                (props.eventDrag && props.eventDrag.affectedInstances) ||
                (props.eventResize && props.eventResize.affectedInstances) || {};
            let sortedFgSegs = this.sortEventSegs(props.fgEventSegs, options.eventOrder);
            return (y(DayCellContainer, {
                elTag: "td",
                elRef: props.elRef,
                elClasses: [
                    'fc-timegrid-col',
                    ...(props.extraClassNames || []),
                ],
                elAttrs: Object.assign({
                    role: 'gridcell'
                }, props.extraDataAttrs),
                date: props.date,
                dateProfile: props.dateProfile,
                todayRange: props.todayRange,
                extraRenderProps: props.extraRenderProps
            }, (InnerContent) => (y("div", {
                    className: "fc-timegrid-col-frame"
                },
                y("div", {
                        className: "fc-timegrid-col-bg"
                    },
                    this.renderFillSegs(props.businessHourSegs, 'non-business'),
                    this.renderFillSegs(props.bgEventSegs, 'bg-event'),
                    this.renderFillSegs(props.dateSelectionSegs, 'highlight')),
                y("div", {
                    className: "fc-timegrid-col-events"
                }, this.renderFgSegs(sortedFgSegs, interactionAffectedInstances, false, false, false)),
                y("div", {
                    className: "fc-timegrid-col-events"
                }, this.renderFgSegs(mirrorSegs, {}, Boolean(props.eventDrag), Boolean(props.eventResize), Boolean(isSelectMirror), 'mirror')),
                y("div", {
                    className: "fc-timegrid-now-indicator-container"
                }, this.renderNowIndicator(props.nowIndicatorSegs)),
                hasCustomDayCellContent(options) && (y(InnerContent, {
                    elTag: "div",
                    elClasses: ['fc-timegrid-col-misc']
                }))))));
        }
        renderFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {
            let {
                props
            } = this;
            if (props.forPrint) {
                return renderPlainFgSegs(sortedFgSegs, props);
            }
            return this.renderPositionedFgSegs(sortedFgSegs, segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey);
        }
        renderPositionedFgSegs(segs, // if not mirror, needs to be sorted
            segIsInvisible, isDragging, isResizing, isDateSelecting, forcedKey) {
            let {
                eventMaxStack,
                eventShortHeight,
                eventOrderStrict,
                eventMinHeight
            } = this.context.options;
            let {
                date,
                slatCoords,
                eventSelection,
                todayRange,
                nowDate
            } = this.props;
            let isMirror = isDragging || isResizing || isDateSelecting;
            let segVCoords = computeSegVCoords(segs, date, slatCoords, eventMinHeight);
            let {
                segPlacements,
                hiddenGroups
            } = computeFgSegPlacements(segs, segVCoords, eventOrderStrict, eventMaxStack);
            return (y(_, null,
                this.renderHiddenGroups(hiddenGroups, segs),
                segPlacements.map((segPlacement) => {
                    let {
                        seg,
                        rect
                    } = segPlacement;
                    let instanceId = seg.eventRange.instance.instanceId;
                    let isVisible = isMirror || Boolean(!segIsInvisible[instanceId] && rect);
                    let vStyle = computeSegVStyle(rect && rect.span);
                    let hStyle = (!isMirror && rect) ? this.computeSegHStyle(rect) : {
                        left: 0,
                        right: 0
                    };
                    let isInset = Boolean(rect) && rect.stackForward > 0;
                    let isShort = Boolean(rect) && (rect.span.end - rect.span.start) < eventShortHeight; // look at other places for this problem
                    return (y("div", {
                            className: 'fc-timegrid-event-harness' +
                                (isInset ? ' fc-timegrid-event-harness-inset' : ''),
                            key: forcedKey || instanceId,
                            style: Object.assign(Object.assign({
                                visibility: isVisible ? '' : 'hidden'
                            }, vStyle), hStyle)
                        },
                        y(TimeColEvent, Object.assign({
                            seg: seg,
                            isDragging: isDragging,
                            isResizing: isResizing,
                            isDateSelecting: isDateSelecting,
                            isSelected: instanceId === eventSelection,
                            isShort: isShort
                        }, getSegMeta(seg, todayRange, nowDate)))));
                })));
        }
        // will already have eventMinHeight applied because segInputs already had it
        renderHiddenGroups(hiddenGroups, segs) {
            let {
                extraDateSpan,
                dateProfile,
                todayRange,
                nowDate,
                eventSelection,
                eventDrag,
                eventResize
            } = this.props;
            return (y(_, null, hiddenGroups.map((hiddenGroup) => {
                let positionCss = computeSegVStyle(hiddenGroup.span);
                let hiddenSegs = compileSegsFromEntries(hiddenGroup.entries, segs);
                return (y(TimeColMoreLink, {
                    key: buildIsoString(computeEarliestSegStart(hiddenSegs)),
                    hiddenSegs: hiddenSegs,
                    top: positionCss.top,
                    bottom: positionCss.bottom,
                    extraDateSpan: extraDateSpan,
                    dateProfile: dateProfile,
                    todayRange: todayRange,
                    nowDate: nowDate,
                    eventSelection: eventSelection,
                    eventDrag: eventDrag,
                    eventResize: eventResize
                }));
            })));
        }
        renderFillSegs(segs, fillType) {
            let {
                props,
                context
            } = this;
            let segVCoords = computeSegVCoords(segs, props.date, props.slatCoords, context.options.eventMinHeight); // don't assume all populated
            let children = segVCoords.map((vcoords, i) => {
                let seg = segs[i];
                return (y("div", {
                        key: buildEventRangeKey(seg.eventRange),
                        className: "fc-timegrid-bg-harness",
                        style: computeSegVStyle(vcoords)
                    }, fillType === 'bg-event' ?
                    y(BgEvent, Object.assign({
                        seg: seg
                    }, getSegMeta(seg, props.todayRange, props.nowDate))) :
                    renderFill(fillType)));
            });
            return y(_, null, children);
        }
        renderNowIndicator(segs) {
            let {
                slatCoords,
                date
            } = this.props;
            if (!slatCoords) {
                return null;
            }
            return segs.map((seg, i) => (y(NowIndicatorContainer
                // key doesn't matter. will only ever be one
                , {
                    // key doesn't matter. will only ever be one
                    key: i,
                    elClasses: ['fc-timegrid-now-indicator-line'],
                    elStyle: {
                        top: slatCoords.computeDateTop(seg.start, date),
                    },
                    isAxis: false,
                    date: date
                })));
        }
        computeSegHStyle(segHCoords) {
            let {
                isRtl,
                options
            } = this.context;
            let shouldOverlap = options.slotEventOverlap;
            let nearCoord = segHCoords.levelCoord; // the left side if LTR. the right side if RTL. floating-point
            let farCoord = segHCoords.levelCoord + segHCoords.thickness; // the right side if LTR. the left side if RTL. floating-point
            let left; // amount of space from left edge, a fraction of the total width
            let right; // amount of space from right edge, a fraction of the total width
            if (shouldOverlap) {
                // double the width, but don't go beyond the maximum forward coordinate (1.0)
                farCoord = Math.min(1, nearCoord + (farCoord - nearCoord) * 2);
            }
            if (isRtl) {
                left = 1 - farCoord;
                right = nearCoord;
            } else {
                left = nearCoord;
                right = 1 - farCoord;
            }
            let props = {
                zIndex: segHCoords.stackDepth + 1,
                left: left * 100 + '%',
                right: right * 100 + '%',
            };
            if (shouldOverlap && !segHCoords.stackForward) {
                // add padding to the edge so that forward stacked events don't cover the resizer's icon
                props[isRtl ? 'marginLeft' : 'marginRight'] = 10 * 2; // 10 is a guesstimate of the icon's width
            }
            return props;
        }
    }

    function renderPlainFgSegs(sortedFgSegs, {
        todayRange,
        nowDate,
        eventSelection,
        eventDrag,
        eventResize
    }) {
        let hiddenInstances = (eventDrag ? eventDrag.affectedInstances : null) ||
            (eventResize ? eventResize.affectedInstances : null) || {};
        return (y(_, null, sortedFgSegs.map((seg) => {
            let instanceId = seg.eventRange.instance.instanceId;
            return (y("div", {
                    key: instanceId,
                    style: {
                        visibility: hiddenInstances[instanceId] ? 'hidden' : ''
                    }
                },
                y(TimeColEvent, Object.assign({
                    seg: seg,
                    isDragging: false,
                    isResizing: false,
                    isDateSelecting: false,
                    isSelected: instanceId === eventSelection,
                    isShort: false
                }, getSegMeta(seg, todayRange, nowDate)))));
        })));
    }

    function computeSegVStyle(segVCoords) {
        if (!segVCoords) {
            return {
                top: '',
                bottom: ''
            };
        }
        return {
            top: segVCoords.start,
            bottom: -segVCoords.end,
        };
    }

    function compileSegsFromEntries(segEntries, allSegs) {
        return segEntries.map((segEntry) => allSegs[segEntry.index]);
    }

    class TimeColsContent extends BaseComponent {
        constructor() {
            super(...arguments);
            this.splitFgEventSegs = memoize(splitSegsByCol);
            this.splitBgEventSegs = memoize(splitSegsByCol);
            this.splitBusinessHourSegs = memoize(splitSegsByCol);
            this.splitNowIndicatorSegs = memoize(splitSegsByCol);
            this.splitDateSelectionSegs = memoize(splitSegsByCol);
            this.splitEventDrag = memoize(splitInteractionByCol);
            this.splitEventResize = memoize(splitInteractionByCol);
            this.rootElRef = d();
            this.cellElRefs = new RefMap();
        }
        render() {
            let {
                props,
                context
            } = this;
            let nowIndicatorTop = context.options.nowIndicator &&
                props.slatCoords &&
                props.slatCoords.safeComputeTop(props.nowDate); // might return void
            let colCnt = props.cells.length;
            let fgEventSegsByRow = this.splitFgEventSegs(props.fgEventSegs, colCnt);
            let bgEventSegsByRow = this.splitBgEventSegs(props.bgEventSegs, colCnt);
            let businessHourSegsByRow = this.splitBusinessHourSegs(props.businessHourSegs, colCnt);
            let nowIndicatorSegsByRow = this.splitNowIndicatorSegs(props.nowIndicatorSegs, colCnt);
            let dateSelectionSegsByRow = this.splitDateSelectionSegs(props.dateSelectionSegs, colCnt);
            let eventDragByRow = this.splitEventDrag(props.eventDrag, colCnt);
            let eventResizeByRow = this.splitEventResize(props.eventResize, colCnt);
            return (y("div", {
                    className: "fc-timegrid-cols",
                    ref: this.rootElRef
                },
                y("table", {
                        role: "presentation",
                        style: {
                            minWidth: props.tableMinWidth,
                            width: props.clientWidth,
                        }
                    },
                    props.tableColGroupNode,
                    y("tbody", {
                            role: "presentation"
                        },
                        y("tr", {
                                role: "row"
                            },
                            props.axis && (y("td", {
                                    "aria-hidden": true,
                                    className: "fc-timegrid-col fc-timegrid-axis"
                                },
                                y("div", {
                                        className: "fc-timegrid-col-frame"
                                    },
                                    y("div", {
                                        className: "fc-timegrid-now-indicator-container"
                                    }, typeof nowIndicatorTop === 'number' && (y(NowIndicatorContainer, {
                                        elClasses: ['fc-timegrid-now-indicator-arrow'],
                                        elStyle: {
                                            top: nowIndicatorTop
                                        },
                                        isAxis: true,
                                        date: props.nowDate
                                    })))))),
                            props.cells.map((cell, i) => (y(TimeCol, {
                                key: cell.key,
                                elRef: this.cellElRefs.createRef(cell.key),
                                dateProfile: props.dateProfile,
                                date: cell.date,
                                nowDate: props.nowDate,
                                todayRange: props.todayRange,
                                extraRenderProps: cell.extraRenderProps,
                                extraDataAttrs: cell.extraDataAttrs,
                                extraClassNames: cell.extraClassNames,
                                extraDateSpan: cell.extraDateSpan,
                                fgEventSegs: fgEventSegsByRow[i],
                                bgEventSegs: bgEventSegsByRow[i],
                                businessHourSegs: businessHourSegsByRow[i],
                                nowIndicatorSegs: nowIndicatorSegsByRow[i],
                                dateSelectionSegs: dateSelectionSegsByRow[i],
                                eventDrag: eventDragByRow[i],
                                eventResize: eventResizeByRow[i],
                                slatCoords: props.slatCoords,
                                eventSelection: props.eventSelection,
                                forPrint: props.forPrint
                            }))))))));
        }
        componentDidMount() {
            this.updateCoords();
        }
        componentDidUpdate() {
            this.updateCoords();
        }
        updateCoords() {
            let {
                props
            } = this;
            if (props.onColCoords &&
                props.clientWidth !== null // means sizing has stabilized
            ) {
                props.onColCoords(new PositionCache(this.rootElRef.current, collectCellEls(this.cellElRefs.currentMap, props.cells), true, // horizontal
                    false));
            }
        }
    }

    function collectCellEls(elMap, cells) {
        return cells.map((cell) => elMap[cell.key]);
    }

    /* A component that renders one or more columns of vertical time slots
    ----------------------------------------------------------------------------------------------------------------------*/
    class TimeCols extends DateComponent {
        constructor() {
            super(...arguments);
            this.processSlotOptions = memoize(processSlotOptions);
            this.state = {
                slatCoords: null,
            };
            this.handleRootEl = (el) => {
                if (el) {
                    this.context.registerInteractiveComponent(this, {
                        el,
                        isHitComboAllowed: this.props.isHitComboAllowed,
                    });
                } else {
                    this.context.unregisterInteractiveComponent(this);
                }
            };
            this.handleScrollRequest = (request) => {
                let {
                    onScrollTopRequest
                } = this.props;
                let {
                    slatCoords
                } = this.state;
                if (onScrollTopRequest && slatCoords) {
                    if (request.time) {
                        let top = slatCoords.computeTimeTop(request.time);
                        top = Math.ceil(top); // zoom can give weird floating-point values. rather scroll a little bit further
                        if (top) {
                            top += 1; // to overcome top border that slots beyond the first have. looks better
                        }
                        onScrollTopRequest(top);
                    }
                    return true;
                }
                return false;
            };
            this.handleColCoords = (colCoords) => {
                this.colCoords = colCoords;
            };
            this.handleSlatCoords = (slatCoords) => {
                this.setState({
                    slatCoords
                });
                if (this.props.onSlatCoords) {
                    this.props.onSlatCoords(slatCoords);
                }
            };
        }
        render() {
            let {
                props,
                state
            } = this;
            return (y("div", {
                    className: "fc-timegrid-body",
                    ref: this.handleRootEl,
                    style: {
                        // these props are important to give this wrapper correct dimensions for interactions
                        // TODO: if we set it here, can we avoid giving to inner tables?
                        width: props.clientWidth,
                        minWidth: props.tableMinWidth,
                    }
                },
                y(TimeColsSlats, {
                    axis: props.axis,
                    dateProfile: props.dateProfile,
                    slatMetas: props.slatMetas,
                    clientWidth: props.clientWidth,
                    minHeight: props.expandRows ? props.clientHeight : '',
                    tableMinWidth: props.tableMinWidth,
                    tableColGroupNode: props.axis ? props.tableColGroupNode : null /* axis depends on the colgroup's shrinking */ ,
                    onCoords: this.handleSlatCoords
                }),
                y(TimeColsContent, {
                    cells: props.cells,
                    axis: props.axis,
                    dateProfile: props.dateProfile,
                    businessHourSegs: props.businessHourSegs,
                    bgEventSegs: props.bgEventSegs,
                    fgEventSegs: props.fgEventSegs,
                    dateSelectionSegs: props.dateSelectionSegs,
                    eventSelection: props.eventSelection,
                    eventDrag: props.eventDrag,
                    eventResize: props.eventResize,
                    todayRange: props.todayRange,
                    nowDate: props.nowDate,
                    nowIndicatorSegs: props.nowIndicatorSegs,
                    clientWidth: props.clientWidth,
                    tableMinWidth: props.tableMinWidth,
                    tableColGroupNode: props.tableColGroupNode,
                    slatCoords: state.slatCoords,
                    onColCoords: this.handleColCoords,
                    forPrint: props.forPrint
                })));
        }
        componentDidMount() {
            this.scrollResponder = this.context.createScrollResponder(this.handleScrollRequest);
        }
        componentDidUpdate(prevProps) {
            this.scrollResponder.update(prevProps.dateProfile !== this.props.dateProfile);
        }
        componentWillUnmount() {
            this.scrollResponder.detach();
        }
        queryHit(positionLeft, positionTop) {
            let {
                dateEnv,
                options
            } = this.context;
            let {
                colCoords
            } = this;
            let {
                dateProfile
            } = this.props;
            let {
                slatCoords
            } = this.state;
            let {
                snapDuration,
                snapsPerSlot
            } = this.processSlotOptions(this.props.slotDuration, options.snapDuration);
            let colIndex = colCoords.leftToIndex(positionLeft);
            let slatIndex = slatCoords.positions.topToIndex(positionTop);
            if (colIndex != null && slatIndex != null) {
                let cell = this.props.cells[colIndex];
                let slatTop = slatCoords.positions.tops[slatIndex];
                let slatHeight = slatCoords.positions.getHeight(slatIndex);
                let partial = (positionTop - slatTop) / slatHeight; // floating point number between 0 and 1
                let localSnapIndex = Math.floor(partial * snapsPerSlot); // the snap # relative to start of slat
                let snapIndex = slatIndex * snapsPerSlot + localSnapIndex;
                let dayDate = this.props.cells[colIndex].date;
                let time = addDurations(dateProfile.slotMinTime, multiplyDuration(snapDuration, snapIndex));
                let start = dateEnv.add(dayDate, time);
                let end = dateEnv.add(start, snapDuration);
                return {
                    dateProfile,
                    dateSpan: Object.assign({
                        range: {
                            start,
                            end
                        },
                        allDay: false
                    }, cell.extraDateSpan),
                    dayEl: colCoords.els[colIndex],
                    rect: {
                        left: colCoords.lefts[colIndex],
                        right: colCoords.rights[colIndex],
                        top: slatTop,
                        bottom: slatTop + slatHeight,
                    },
                    layer: 0,
                };
            }
            return null;
        }
    }

    function processSlotOptions(slotDuration, snapDurationOverride) {
        let snapDuration = snapDurationOverride || slotDuration;
        let snapsPerSlot = wholeDivideDurations(slotDuration, snapDuration);
        if (snapsPerSlot === null) {
            snapDuration = slotDuration;
            snapsPerSlot = 1;
            // TODO: say warning?
        }
        return {
            snapDuration,
            snapsPerSlot
        };
    }

    class DayTimeColsSlicer extends Slicer {
        sliceRange(range, dayRanges) {
            let segs = [];
            for (let col = 0; col < dayRanges.length; col += 1) {
                let segRange = intersectRanges(range, dayRanges[col]);
                if (segRange) {
                    segs.push({
                        start: segRange.start,
                        end: segRange.end,
                        isStart: segRange.start.valueOf() === range.start.valueOf(),
                        isEnd: segRange.end.valueOf() === range.end.valueOf(),
                        col,
                    });
                }
            }
            return segs;
        }
    }

    class DayTimeCols extends DateComponent {
        constructor() {
            super(...arguments);
            this.buildDayRanges = memoize(buildDayRanges);
            this.slicer = new DayTimeColsSlicer();
            this.timeColsRef = d();
        }
        render() {
            let {
                props,
                context
            } = this;
            let {
                dateProfile,
                dayTableModel
            } = props;
            let {
                nowIndicator,
                nextDayThreshold
            } = context.options;
            let dayRanges = this.buildDayRanges(dayTableModel, dateProfile, context.dateEnv);
            // give it the first row of cells
            // TODO: would move this further down hierarchy, but sliceNowDate needs it
            return (y(NowTimer, {
                unit: nowIndicator ? 'minute' : 'day'
            }, (nowDate, todayRange) => (y(TimeCols, Object.assign({
                ref: this.timeColsRef
            }, this.slicer.sliceProps(props, dateProfile, null, context, dayRanges), {
                forPrint: props.forPrint,
                axis: props.axis,
                dateProfile: dateProfile,
                slatMetas: props.slatMetas,
                slotDuration: props.slotDuration,
                cells: dayTableModel.cells[0],
                tableColGroupNode: props.tableColGroupNode,
                tableMinWidth: props.tableMinWidth,
                clientWidth: props.clientWidth,
                clientHeight: props.clientHeight,
                expandRows: props.expandRows,
                nowDate: nowDate,
                nowIndicatorSegs: nowIndicator && this.slicer.sliceNowDate(nowDate, dateProfile, nextDayThreshold, context, dayRanges),
                todayRange: todayRange,
                onScrollTopRequest: props.onScrollTopRequest,
                onSlatCoords: props.onSlatCoords
            })))));
        }
    }

    function buildDayRanges(dayTableModel, dateProfile, dateEnv) {
        let ranges = [];
        for (let date of dayTableModel.headerDates) {
            ranges.push({
                start: dateEnv.add(date, dateProfile.slotMinTime),
                end: dateEnv.add(date, dateProfile.slotMaxTime),
            });
        }
        return ranges;
    }

    // potential nice values for the slot-duration and interval-duration
    // from largest to smallest
    const STOCK_SUB_DURATIONS = [{
            hours: 1
        },
        {
            minutes: 30
        },
        {
            minutes: 15
        },
        {
            seconds: 30
        },
        {
            seconds: 15
        },
    ];

    function buildSlatMetas(slotMinTime, slotMaxTime, explicitLabelInterval, slotDuration, dateEnv) {
        let dayStart = new Date(0);
        let slatTime = slotMinTime;
        let slatIterator = createDuration(0);
        let labelInterval = explicitLabelInterval || computeLabelInterval(slotDuration);
        let metas = [];
        while (asRoughMs(slatTime) < asRoughMs(slotMaxTime)) {
            let date = dateEnv.add(dayStart, slatTime);
            let isLabeled = wholeDivideDurations(slatIterator, labelInterval) !== null;
            metas.push({
                date,
                time: slatTime,
                key: date.toISOString(),
                isoTimeStr: formatIsoTimeString(date),
                isLabeled,
            });
            slatTime = addDurations(slatTime, slotDuration);
            slatIterator = addDurations(slatIterator, slotDuration);
        }
        return metas;
    }
    // Computes an automatic value for slotLabelInterval
    function computeLabelInterval(slotDuration) {
        let i;
        let labelInterval;
        let slotsPerLabel;
        // find the smallest stock label interval that results in more than one slots-per-label
        for (i = STOCK_SUB_DURATIONS.length - 1; i >= 0; i -= 1) {
            labelInterval = createDuration(STOCK_SUB_DURATIONS[i]);
            slotsPerLabel = wholeDivideDurations(labelInterval, slotDuration);
            if (slotsPerLabel !== null && slotsPerLabel > 1) {
                return labelInterval;
            }
        }
        return slotDuration; // fall back
    }

    class DayTimeColsView extends TimeColsView {
        constructor() {
            super(...arguments);
            this.buildTimeColsModel = memoize(buildTimeColsModel);
            this.buildSlatMetas = memoize(buildSlatMetas);
        }
        render() {
            let {
                options,
                dateEnv,
                dateProfileGenerator
            } = this.context;
            let {
                props
            } = this;
            let {
                dateProfile
            } = props;
            let dayTableModel = this.buildTimeColsModel(dateProfile, dateProfileGenerator);
            let splitProps = this.allDaySplitter.splitProps(props);
            let slatMetas = this.buildSlatMetas(dateProfile.slotMinTime, dateProfile.slotMaxTime, options.slotLabelInterval, options.slotDuration, dateEnv);
            let {
                dayMinWidth
            } = options;
            let hasAttachedAxis = !dayMinWidth;
            let hasDetachedAxis = dayMinWidth;
            let headerContent = options.dayHeaders && (y(DayHeader, {
                dates: dayTableModel.headerDates,
                dateProfile: dateProfile,
                datesRepDistinctDays: true,
                renderIntro: hasAttachedAxis ? this.renderHeadAxis : null
            }));
            let allDayContent = (options.allDaySlot !== false) && ((contentArg) => (y(DayTable, Object.assign({}, splitProps.allDay, {
                dateProfile: dateProfile,
                dayTableModel: dayTableModel,
                nextDayThreshold: options.nextDayThreshold,
                tableMinWidth: contentArg.tableMinWidth,
                colGroupNode: contentArg.tableColGroupNode,
                renderRowIntro: hasAttachedAxis ? this.renderTableRowAxis : null,
                showWeekNumbers: false,
                expandRows: false,
                headerAlignElRef: this.headerElRef,
                clientWidth: contentArg.clientWidth,
                clientHeight: contentArg.clientHeight,
                forPrint: props.forPrint
            }, this.getAllDayMaxEventProps()))));
            let timeGridContent = (contentArg) => (y(DayTimeCols, Object.assign({}, splitProps.timed, {
                dayTableModel: dayTableModel,
                dateProfile: dateProfile,
                axis: hasAttachedAxis,
                slotDuration: options.slotDuration,
                slatMetas: slatMetas,
                forPrint: props.forPrint,
                tableColGroupNode: contentArg.tableColGroupNode,
                tableMinWidth: contentArg.tableMinWidth,
                clientWidth: contentArg.clientWidth,
                clientHeight: contentArg.clientHeight,
                onSlatCoords: this.handleSlatCoords,
                expandRows: contentArg.expandRows,
                onScrollTopRequest: this.handleScrollTopRequest
            })));
            return hasDetachedAxis ?
                this.renderHScrollLayout(headerContent, allDayContent, timeGridContent, dayTableModel.colCnt, dayMinWidth, slatMetas, this.state.slatCoords) :
                this.renderSimpleLayout(headerContent, allDayContent, timeGridContent);
        }
    }

    function buildTimeColsModel(dateProfile, dateProfileGenerator) {
        let daySeries = new DaySeriesModel(dateProfile.renderRange, dateProfileGenerator);
        return new DayTableModel(daySeries, false);
    }

    var css_248z$2 = ".fc-v-event{background-color:var(--fc-event-bg-color);border:1px solid var(--fc-event-border-color);display:block}.fc-v-event .fc-event-main{color:var(--fc-event-text-color);height:100%}.fc-v-event .fc-event-main-frame{display:flex;flex-direction:column;height:100%}.fc-v-event .fc-event-time{flex-grow:0;flex-shrink:0;max-height:100%;overflow:hidden}.fc-v-event .fc-event-title-container{flex-grow:1;flex-shrink:1;min-height:0}.fc-v-event .fc-event-title{bottom:0;max-height:100%;overflow:hidden;top:0}.fc-v-event:not(.fc-event-start){border-top-left-radius:0;border-top-right-radius:0;border-top-width:0}.fc-v-event:not(.fc-event-end){border-bottom-left-radius:0;border-bottom-right-radius:0;border-bottom-width:0}.fc-v-event.fc-event-selected:before{left:-10px;right:-10px}.fc-v-event .fc-event-resizer-start{cursor:n-resize}.fc-v-event .fc-event-resizer-end{cursor:s-resize}.fc-v-event:not(.fc-event-selected) .fc-event-resizer{height:var(--fc-event-resizer-thickness);left:0;right:0}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-start{top:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event:not(.fc-event-selected) .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-thickness)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer{left:50%;margin-left:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-start{top:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc-v-event.fc-event-selected .fc-event-resizer-end{bottom:calc(var(--fc-event-resizer-dot-total-width)/-2)}.fc .fc-timegrid .fc-daygrid-body{z-index:2}.fc .fc-timegrid-divider{padding:0 0 2px}.fc .fc-timegrid-body{min-height:100%;position:relative;z-index:1}.fc .fc-timegrid-axis-chunk{position:relative}.fc .fc-timegrid-axis-chunk>table,.fc .fc-timegrid-slots{position:relative;z-index:1}.fc .fc-timegrid-slot{border-bottom:0;height:1.5em}.fc .fc-timegrid-slot:empty:before{content:\"\\00a0\"}.fc .fc-timegrid-slot-minor{border-top-style:dotted}.fc .fc-timegrid-slot-label-cushion{display:inline-block;white-space:nowrap}.fc .fc-timegrid-slot-label{vertical-align:middle}.fc .fc-timegrid-axis-cushion,.fc .fc-timegrid-slot-label-cushion{padding:0 4px}.fc .fc-timegrid-axis-frame-liquid{height:100%}.fc .fc-timegrid-axis-frame{align-items:center;display:flex;justify-content:flex-end;overflow:hidden}.fc .fc-timegrid-axis-cushion{flex-shrink:0;max-width:60px}.fc-direction-ltr .fc-timegrid-slot-label-frame{text-align:right}.fc-direction-rtl .fc-timegrid-slot-label-frame{text-align:left}.fc-liquid-hack .fc-timegrid-axis-frame-liquid{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col.fc-day-today{background-color:var(--fc-today-bg-color)}.fc .fc-timegrid-col-frame{min-height:100%;position:relative}.fc-media-screen.fc-liquid-hack .fc-timegrid-col-frame{bottom:0;height:auto;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols{bottom:0;left:0;position:absolute;right:0;top:0}.fc-media-screen .fc-timegrid-cols>table{height:100%}.fc-media-screen .fc-timegrid-col-bg,.fc-media-screen .fc-timegrid-col-events,.fc-media-screen .fc-timegrid-now-indicator-container{left:0;position:absolute;right:0;top:0}.fc .fc-timegrid-col-bg{z-index:2}.fc .fc-timegrid-col-bg .fc-non-business{z-index:1}.fc .fc-timegrid-col-bg .fc-bg-event{z-index:2}.fc .fc-timegrid-col-bg .fc-highlight{z-index:3}.fc .fc-timegrid-bg-harness{left:0;position:absolute;right:0}.fc .fc-timegrid-col-events{z-index:3}.fc .fc-timegrid-now-indicator-container{bottom:0;overflow:hidden}.fc-direction-ltr .fc-timegrid-col-events{margin:0 2.5% 0 2px}.fc-direction-rtl .fc-timegrid-col-events{margin:0 2px 0 2.5%}.fc-timegrid-event-harness{position:absolute}.fc-timegrid-event-harness>.fc-timegrid-event{bottom:0;left:0;position:absolute;right:0;top:0}.fc-timegrid-event-harness-inset .fc-timegrid-event,.fc-timegrid-event.fc-event-mirror,.fc-timegrid-more-link{box-shadow:0 0 0 1px var(--fc-page-bg-color)}.fc-timegrid-event,.fc-timegrid-more-link{border-radius:3px;font-size:var(--fc-small-font-size)}.fc-timegrid-event{margin-bottom:1px}.fc-timegrid-event .fc-event-main{padding:1px 1px 0}.fc-timegrid-event .fc-event-time{font-size:var(--fc-small-font-size);margin-bottom:1px;white-space:nowrap}.fc-timegrid-event-short .fc-event-main-frame{flex-direction:row;overflow:hidden}.fc-timegrid-event-short .fc-event-time:after{content:\"\\00a0-\\00a0\"}.fc-timegrid-event-short .fc-event-title{font-size:var(--fc-small-font-size)}.fc-timegrid-more-link{background:var(--fc-more-link-bg-color);color:var(--fc-more-link-text-color);cursor:pointer;margin-bottom:1px;position:absolute;z-index:9999}.fc-timegrid-more-link-inner{padding:3px 2px;top:0}.fc-direction-ltr .fc-timegrid-more-link{right:0}.fc-direction-rtl .fc-timegrid-more-link{left:0}.fc .fc-timegrid-now-indicator-arrow,.fc .fc-timegrid-now-indicator-line{pointer-events:none}.fc .fc-timegrid-now-indicator-line{border-color:var(--fc-now-indicator-color);border-style:solid;border-width:1px 0 0;left:0;position:absolute;right:0;z-index:4}.fc .fc-timegrid-now-indicator-arrow{border-color:var(--fc-now-indicator-color);border-style:solid;margin-top:-5px;position:absolute;z-index:4}.fc-direction-ltr .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 0 5px 6px;left:0}.fc-direction-rtl .fc-timegrid-now-indicator-arrow{border-bottom-color:transparent;border-top-color:transparent;border-width:5px 6px 5px 0;right:0}";
    injectStyles(css_248z$2);

    const OPTION_REFINERS$2 = {
        allDaySlot: Boolean,
    };

    var index$2 = createPlugin({
        name: '@fullcalendar/timegrid',
        initialView: 'timeGridWeek',
        optionRefiners: OPTION_REFINERS$2,
        views: {
            timeGrid: {
                component: DayTimeColsView,
                usesMinMaxTime: true,
                allDaySlot: true,
                slotDuration: '00:30:00',
                slotEventOverlap: true, // a bad name. confused with overlap/constraint system
            },
            timeGridDay: {
                type: 'timeGrid',
                duration: {
                    days: 1
                },
            },
            timeGridWeek: {
                type: 'timeGrid',
                duration: {
                    weeks: 1
                },
            },
        },
    });

    class ListViewHeaderRow extends BaseComponent {
        constructor() {
            super(...arguments);
            this.state = {
                textId: getUniqueDomId(),
            };
        }
        render() {
            let {
                theme,
                dateEnv,
                options,
                viewApi
            } = this.context;
            let {
                cellId,
                dayDate,
                todayRange
            } = this.props;
            let {
                textId
            } = this.state;
            let dayMeta = getDateMeta(dayDate, todayRange);
            // will ever be falsy?
            let text = options.listDayFormat ? dateEnv.format(dayDate, options.listDayFormat) : '';
            // will ever be falsy? also, BAD NAME "alt"
            let sideText = options.listDaySideFormat ? dateEnv.format(dayDate, options.listDaySideFormat) : '';
            let renderProps = Object.assign({
                date: dateEnv.toDate(dayDate),
                view: viewApi,
                textId,
                text,
                sideText,
                navLinkAttrs: buildNavLinkAttrs(this.context, dayDate),
                sideNavLinkAttrs: buildNavLinkAttrs(this.context, dayDate, 'day', false)
            }, dayMeta);
            // TODO: make a reusable HOC for dayHeader (used in daygrid/timegrid too)
            return (y(ContentContainer, {
                elTag: "tr",
                elClasses: [
                    'fc-list-day',
                    ...getDayClassNames(dayMeta, theme),
                ],
                elAttrs: {
                    'data-date': formatDayString(dayDate),
                },
                renderProps: renderProps,
                generatorName: "dayHeaderContent",
                customGenerator: options.dayHeaderContent,
                defaultGenerator: renderInnerContent,
                classNameGenerator: options.dayHeaderClassNames,
                didMount: options.dayHeaderDidMount,
                willUnmount: options.dayHeaderWillUnmount
            }, (InnerContent) => ( // TODO: force-hide top border based on :first-child
                y("th", {
                        scope: "colgroup",
                        colSpan: 3,
                        id: cellId,
                        "aria-labelledby": textId
                    },
                    y(InnerContent, {
                        elTag: "div",
                        elClasses: [
                            'fc-list-day-cushion',
                            theme.getClass('tableCellShaded'),
                        ]
                    })))));
        }
    }

    function renderInnerContent(props) {
        return (y(_, null,
            props.text && (y("a", Object.assign({
                id: props.textId,
                className: "fc-list-day-text"
            }, props.navLinkAttrs), props.text)),
            props.sideText && ( /* not keyboard tabbable */ y("a", Object.assign({
                "aria-hidden": true,
                className: "fc-list-day-side-text"
            }, props.sideNavLinkAttrs), props.sideText))));
    }

    const DEFAULT_TIME_FORMAT = createFormatter({
        hour: 'numeric',
        minute: '2-digit',
        meridiem: 'short',
    });
    class ListViewEventRow extends BaseComponent {
        render() {
            let {
                props,
                context
            } = this;
            let {
                options
            } = context;
            let {
                seg,
                timeHeaderId,
                eventHeaderId,
                dateHeaderId
            } = props;
            let timeFormat = options.eventTimeFormat || DEFAULT_TIME_FORMAT;
            return (y(EventContainer, Object.assign({}, props, {
                elTag: "tr",
                elClasses: [
                    'fc-list-event',
                    seg.eventRange.def.url && 'fc-event-forced-url',
                ],
                defaultGenerator: () => renderEventInnerContent(seg, context) /* weird */ ,
                seg: seg,
                timeText: "",
                disableDragging: true,
                disableResizing: true
            }), (InnerContent, eventContentArg) => (y(_, null,
                buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId),
                y("td", {
                        "aria-hidden": true,
                        className: "fc-list-event-graphic"
                    },
                    y("span", {
                        className: "fc-list-event-dot",
                        style: {
                            borderColor: eventContentArg.borderColor || eventContentArg.backgroundColor,
                        }
                    })),
                y(InnerContent, {
                    elTag: "td",
                    elClasses: ['fc-list-event-title'],
                    elAttrs: {
                        headers: `${eventHeaderId} ${dateHeaderId}`
                    }
                })))));
        }
    }

    function renderEventInnerContent(seg, context) {
        let interactiveAttrs = getSegAnchorAttrs(seg, context);
        return (y("a", Object.assign({}, interactiveAttrs), seg.eventRange.def.title));
    }

    function buildTimeContent(seg, timeFormat, context, timeHeaderId, dateHeaderId) {
        let {
            options
        } = context;
        if (options.displayEventTime !== false) {
            let eventDef = seg.eventRange.def;
            let eventInstance = seg.eventRange.instance;
            let doAllDay = false;
            let timeText;
            if (eventDef.allDay) {
                doAllDay = true;
            } else if (isMultiDayRange(seg.eventRange.range)) { // TODO: use (!isStart || !isEnd) instead?
                if (seg.isStart) {
                    timeText = buildSegTimeText(seg, timeFormat, context, null, null, eventInstance.range.start, seg.end);
                } else if (seg.isEnd) {
                    timeText = buildSegTimeText(seg, timeFormat, context, null, null, seg.start, eventInstance.range.end);
                } else {
                    doAllDay = true;
                }
            } else {
                timeText = buildSegTimeText(seg, timeFormat, context);
            }
            if (doAllDay) {
                let renderProps = {
                    text: context.options.allDayText,
                    view: context.viewApi,
                };
                return (y(ContentContainer, {
                    elTag: "td",
                    elClasses: ['fc-list-event-time'],
                    elAttrs: {
                        headers: `${timeHeaderId} ${dateHeaderId}`,
                    },
                    renderProps: renderProps,
                    generatorName: "allDayContent",
                    customGenerator: options.allDayContent,
                    defaultGenerator: renderAllDayInner,
                    classNameGenerator: options.allDayClassNames,
                    didMount: options.allDayDidMount,
                    willUnmount: options.allDayWillUnmount
                }));
            }
            return (y("td", {
                className: "fc-list-event-time"
            }, timeText));
        }
        return null;
    }

    function renderAllDayInner(renderProps) {
        return renderProps.text;
    }

    /*
    Responsible for the scroller, and forwarding event-related actions into the "grid".
    */
    class ListView extends DateComponent {
        constructor() {
            super(...arguments);
            this.computeDateVars = memoize(computeDateVars);
            this.eventStoreToSegs = memoize(this._eventStoreToSegs);
            this.state = {
                timeHeaderId: getUniqueDomId(),
                eventHeaderId: getUniqueDomId(),
                dateHeaderIdRoot: getUniqueDomId(),
            };
            this.setRootEl = (rootEl) => {
                if (rootEl) {
                    this.context.registerInteractiveComponent(this, {
                        el: rootEl,
                    });
                } else {
                    this.context.unregisterInteractiveComponent(this);
                }
            };
        }
        render() {
            let {
                props,
                context
            } = this;
            let {
                dayDates,
                dayRanges
            } = this.computeDateVars(props.dateProfile);
            let eventSegs = this.eventStoreToSegs(props.eventStore, props.eventUiBases, dayRanges);
            return (y(ViewContainer, {
                    elRef: this.setRootEl,
                    elClasses: [
                        'fc-list',
                        context.theme.getClass('table'),
                        context.options.stickyHeaderDates !== false ?
                        'fc-list-sticky' :
                        '',
                    ],
                    viewSpec: context.viewSpec
                },
                y(Scroller, {
                        liquid: !props.isHeightAuto,
                        overflowX: props.isHeightAuto ? 'visible' : 'hidden',
                        overflowY: props.isHeightAuto ? 'visible' : 'auto'
                    }, eventSegs.length > 0 ?
                    this.renderSegList(eventSegs, dayDates) :
                    this.renderEmptyMessage())));
        }
        renderEmptyMessage() {
            let {
                options,
                viewApi
            } = this.context;
            let renderProps = {
                text: options.noEventsText,
                view: viewApi,
            };
            return (y(ContentContainer, {
                elTag: "div",
                elClasses: ['fc-list-empty'],
                renderProps: renderProps,
                generatorName: "noEventsContent",
                customGenerator: options.noEventsContent,
                defaultGenerator: renderNoEventsInner,
                classNameGenerator: options.noEventsClassNames,
                didMount: options.noEventsDidMount,
                willUnmount: options.noEventsWillUnmount
            }, (InnerContent) => (y(InnerContent, {
                elTag: "div",
                elClasses: ['fc-list-empty-cushion']
            }))));
        }
        renderSegList(allSegs, dayDates) {
            let {
                theme,
                options
            } = this.context;
            let {
                timeHeaderId,
                eventHeaderId,
                dateHeaderIdRoot
            } = this.state;
            let segsByDay = groupSegsByDay(allSegs); // sparse array
            return (y(NowTimer, {
                unit: "day"
            }, (nowDate, todayRange) => {
                let innerNodes = [];
                for (let dayIndex = 0; dayIndex < segsByDay.length; dayIndex += 1) {
                    let daySegs = segsByDay[dayIndex];
                    if (daySegs) { // sparse array, so might be undefined
                        let dayStr = formatDayString(dayDates[dayIndex]);
                        let dateHeaderId = dateHeaderIdRoot + '-' + dayStr;
                        // append a day header
                        innerNodes.push(y(ListViewHeaderRow, {
                            key: dayStr,
                            cellId: dateHeaderId,
                            dayDate: dayDates[dayIndex],
                            todayRange: todayRange
                        }));
                        daySegs = sortEventSegs(daySegs, options.eventOrder);
                        for (let seg of daySegs) {
                            innerNodes.push(y(ListViewEventRow, Object.assign({
                                key: dayStr + ':' + seg.eventRange.instance.instanceId /* are multiple segs for an instanceId */ ,
                                seg: seg,
                                isDragging: false,
                                isResizing: false,
                                isDateSelecting: false,
                                isSelected: false,
                                timeHeaderId: timeHeaderId,
                                eventHeaderId: eventHeaderId,
                                dateHeaderId: dateHeaderId
                            }, getSegMeta(seg, todayRange, nowDate))));
                        }
                    }
                }
                return (y("table", {
                        className: 'fc-list-table ' + theme.getClass('table')
                    },
                    y("thead", null,
                        y("tr", null,
                            y("th", {
                                scope: "col",
                                id: timeHeaderId
                            }, options.timeHint),
                            y("th", {
                                scope: "col",
                                "aria-hidden": true
                            }),
                            y("th", {
                                scope: "col",
                                id: eventHeaderId
                            }, options.eventHint))),
                    y("tbody", null, innerNodes)));
            }));
        }
        _eventStoreToSegs(eventStore, eventUiBases, dayRanges) {
            return this.eventRangesToSegs(sliceEventStore(eventStore, eventUiBases, this.props.dateProfile.activeRange, this.context.options.nextDayThreshold).fg, dayRanges);
        }
        eventRangesToSegs(eventRanges, dayRanges) {
            let segs = [];
            for (let eventRange of eventRanges) {
                segs.push(...this.eventRangeToSegs(eventRange, dayRanges));
            }
            return segs;
        }
        eventRangeToSegs(eventRange, dayRanges) {
            let {
                dateEnv
            } = this.context;
            let {
                nextDayThreshold
            } = this.context.options;
            let range = eventRange.range;
            let allDay = eventRange.def.allDay;
            let dayIndex;
            let segRange;
            let seg;
            let segs = [];
            for (dayIndex = 0; dayIndex < dayRanges.length; dayIndex += 1) {
                segRange = intersectRanges(range, dayRanges[dayIndex]);
                if (segRange) {
                    seg = {
                        component: this,
                        eventRange,
                        start: segRange.start,
                        end: segRange.end,
                        isStart: eventRange.isStart && segRange.start.valueOf() === range.start.valueOf(),
                        isEnd: eventRange.isEnd && segRange.end.valueOf() === range.end.valueOf(),
                        dayIndex,
                    };
                    segs.push(seg);
                    // detect when range won't go fully into the next day,
                    // and mutate the latest seg to the be the end.
                    if (!seg.isEnd && !allDay &&
                        dayIndex + 1 < dayRanges.length &&
                        range.end <
                        dateEnv.add(dayRanges[dayIndex + 1].start, nextDayThreshold)) {
                        seg.end = range.end;
                        seg.isEnd = true;
                        break;
                    }
                }
            }
            return segs;
        }
    }

    function renderNoEventsInner(renderProps) {
        return renderProps.text;
    }

    function computeDateVars(dateProfile) {
        let dayStart = startOfDay(dateProfile.renderRange.start);
        let viewEnd = dateProfile.renderRange.end;
        let dayDates = [];
        let dayRanges = [];
        while (dayStart < viewEnd) {
            dayDates.push(dayStart);
            dayRanges.push({
                start: dayStart,
                end: addDays(dayStart, 1),
            });
            dayStart = addDays(dayStart, 1);
        }
        return {
            dayDates,
            dayRanges
        };
    }
    // Returns a sparse array of arrays, segs grouped by their dayIndex
    function groupSegsByDay(segs) {
        let segsByDay = []; // sparse array
        let i;
        let seg;
        for (i = 0; i < segs.length; i += 1) {
            seg = segs[i];
            (segsByDay[seg.dayIndex] || (segsByDay[seg.dayIndex] = []))
            .push(seg);
        }
        return segsByDay;
    }

    var css_248z$1 = ":root{--fc-list-event-dot-width:10px;--fc-list-event-hover-bg-color:#f5f5f5}.fc-theme-standard .fc-list{border:1px solid var(--fc-border-color)}.fc .fc-list-empty{align-items:center;background-color:var(--fc-neutral-bg-color);display:flex;height:100%;justify-content:center}.fc .fc-list-empty-cushion{margin:5em 0}.fc .fc-list-table{border-style:hidden;width:100%}.fc .fc-list-table tr>*{border-left:0;border-right:0}.fc .fc-list-sticky .fc-list-day>*{background:var(--fc-page-bg-color);position:sticky;top:0}.fc .fc-list-table thead{left:-10000px;position:absolute}.fc .fc-list-table tbody>tr:first-child th{border-top:0}.fc .fc-list-table th{padding:0}.fc .fc-list-day-cushion,.fc .fc-list-table td{padding:8px 14px}.fc .fc-list-day-cushion:after{clear:both;content:\"\";display:table}.fc-theme-standard .fc-list-day-cushion{background-color:var(--fc-neutral-bg-color)}.fc-direction-ltr .fc-list-day-text,.fc-direction-rtl .fc-list-day-side-text{float:left}.fc-direction-ltr .fc-list-day-side-text,.fc-direction-rtl .fc-list-day-text{float:right}.fc-direction-ltr .fc-list-table .fc-list-event-graphic{padding-right:0}.fc-direction-rtl .fc-list-table .fc-list-event-graphic{padding-left:0}.fc .fc-list-event.fc-event-forced-url{cursor:pointer}.fc .fc-list-event:hover td{background-color:var(--fc-list-event-hover-bg-color)}.fc .fc-list-event-graphic,.fc .fc-list-event-time{white-space:nowrap;width:1px}.fc .fc-list-event-dot{border:calc(var(--fc-list-event-dot-width)/2) solid var(--fc-event-border-color);border-radius:calc(var(--fc-list-event-dot-width)/2);box-sizing:content-box;display:inline-block;height:0;width:0}.fc .fc-list-event-title a{color:inherit;text-decoration:none}.fc .fc-list-event.fc-event-forced-url:hover a{text-decoration:underline}";
    injectStyles(css_248z$1);

    const OPTION_REFINERS$1 = {
        listDayFormat: createFalsableFormatter,
        listDaySideFormat: createFalsableFormatter,
        noEventsClassNames: identity,
        noEventsContent: identity,
        noEventsDidMount: identity,
        noEventsWillUnmount: identity,
        // noEventsText is defined in base options
    };

    function createFalsableFormatter(input) {
        return input === false ? null : createFormatter(input);
    }

    var index$1 = createPlugin({
        name: '@fullcalendar/list',
        optionRefiners: OPTION_REFINERS$1,
        views: {
            list: {
                component: ListView,
                buttonTextKey: 'list',
                listDayFormat: {
                    month: 'long',
                    day: 'numeric',
                    year: 'numeric'
                }, // like "January 1, 2016"
            },
            listDay: {
                type: 'list',
                duration: {
                    days: 1
                },
                listDayFormat: {
                    weekday: 'long'
                }, // day-of-week is all we need. full date is probably in headerToolbar
            },
            listWeek: {
                type: 'list',
                duration: {
                    weeks: 1
                },
                listDayFormat: {
                    weekday: 'long'
                },
                listDaySideFormat: {
                    month: 'long',
                    day: 'numeric',
                    year: 'numeric'
                },
            },
            listMonth: {
                type: 'list',
                duration: {
                    month: 1
                },
                listDaySideFormat: {
                    weekday: 'long'
                }, // day-of-week is nice-to-have
            },
            listYear: {
                type: 'list',
                duration: {
                    year: 1
                },
                listDaySideFormat: {
                    weekday: 'long'
                }, // day-of-week is nice-to-have
            },
        },
    });

    class SingleMonth extends DateComponent {
        constructor() {
            super(...arguments);
            this.buildDayTableModel = memoize(buildDayTableModel);
            this.slicer = new DayTableSlicer();
            this.state = {
                labelId: getUniqueDomId(),
            };
        }
        render() {
            const {
                props,
                state,
                context
            } = this;
            const {
                dateProfile,
                forPrint
            } = props;
            const {
                options
            } = context;
            const dayTableModel = this.buildDayTableModel(dateProfile, context.dateProfileGenerator);
            const slicedProps = this.slicer.sliceProps(props, dateProfile, options.nextDayThreshold, context, dayTableModel);
            // ensure single-month has aspect ratio
            const tableHeight = props.tableWidth != null ? props.tableWidth / options.aspectRatio : null;
            const rowCnt = dayTableModel.cells.length;
            const rowHeight = tableHeight != null ? tableHeight / rowCnt : null;
            return (y("div", {
                    ref: props.elRef,
                    "data-date": props.isoDateStr,
                    className: "fc-multimonth-month",
                    style: {
                        width: props.width
                    },
                    role: "grid",
                    "aria-labelledby": state.labelId
                },
                y("div", {
                        className: "fc-multimonth-header",
                        style: {
                            marginBottom: rowHeight
                        },
                        role: "presentation"
                    },
                    y("div", {
                        className: "fc-multimonth-title",
                        id: state.labelId
                    }, context.dateEnv.format(props.dateProfile.currentRange.start, props.titleFormat)),
                    y("table", {
                            className: [
                                'fc-multimonth-header-table',
                                context.theme.getClass('table'),
                            ].join(' '),
                            role: "presentation"
                        },
                        y("thead", {
                                role: "rowgroup"
                            },
                            y(DayHeader, {
                                dateProfile: props.dateProfile,
                                dates: dayTableModel.headerDates,
                                datesRepDistinctDays: false
                            })))),
                y("div", {
                        className: [
                            'fc-multimonth-daygrid',
                            'fc-daygrid',
                            'fc-daygrid-body',
                            !forPrint && 'fc-daygrid-body-balanced',
                            forPrint && 'fc-daygrid-body-unbalanced',
                            forPrint && 'fc-daygrid-body-natural',
                        ].join(' '),
                        style: {
                            marginTop: -rowHeight
                        }
                    },
                    y("table", {
                            className: [
                                'fc-multimonth-daygrid-table',
                                context.theme.getClass('table'),
                            ].join(' '),
                            style: {
                                height: forPrint ? '' : tableHeight
                            },
                            role: "presentation"
                        },
                        y("tbody", {
                                role: "rowgroup"
                            },
                            y(TableRows, Object.assign({}, slicedProps, {
                                dateProfile: dateProfile,
                                cells: dayTableModel.cells,
                                eventSelection: props.eventSelection,
                                dayMaxEvents: !forPrint,
                                dayMaxEventRows: !forPrint,
                                showWeekNumbers: options.weekNumbers,
                                clientWidth: props.clientWidth,
                                clientHeight: props.clientHeight,
                                forPrint: forPrint
                            })))))));
        }
    }

    class MultiMonthView extends DateComponent {
        constructor() {
            super(...arguments);
            this.splitDateProfileByMonth = memoize(splitDateProfileByMonth);
            this.buildMonthFormat = memoize(buildMonthFormat);
            this.scrollElRef = d();
            this.firstMonthElRef = d();
            this.needsScrollReset = false;
            this.handleSizing = (isForced) => {
                if (isForced) {
                    this.updateSize();
                }
            };
        }
        render() {
            const {
                context,
                props,
                state
            } = this;
            const {
                options
            } = context;
            const {
                clientWidth,
                clientHeight
            } = state;
            const monthHPadding = state.monthHPadding || 0;
            const colCount = Math.min(clientWidth != null ?
                Math.floor(clientWidth / (options.multiMonthMinWidth + monthHPadding)) :
                1, options.multiMonthMaxColumns) || 1;
            const monthWidthPct = (100 / colCount) + '%';
            const monthTableWidth = clientWidth == null ? null :
                (clientWidth / colCount) - monthHPadding;
            const isLegitSingleCol = clientWidth != null && colCount === 1;
            const monthDateProfiles = this.splitDateProfileByMonth(context.dateProfileGenerator, props.dateProfile, context.dateEnv, isLegitSingleCol ? false : options.fixedWeekCount, options.showNonCurrentDates);
            const monthTitleFormat = this.buildMonthFormat(options.multiMonthTitleFormat, monthDateProfiles);
            const rootClassNames = [
                'fc-multimonth',
                isLegitSingleCol ?
                'fc-multimonth-singlecol' :
                'fc-multimonth-multicol',
                (monthTableWidth != null && monthTableWidth < 400) ?
                'fc-multimonth-compact' :
                '',
                props.isHeightAuto ?
                '' :
                'fc-scroller', // for AutoScroller
            ];
            return (y(ViewContainer, {
                elRef: this.scrollElRef,
                elClasses: rootClassNames,
                viewSpec: context.viewSpec
            }, monthDateProfiles.map((monthDateProfile, i) => {
                const monthStr = formatIsoMonthStr(monthDateProfile.currentRange.start);
                return (y(SingleMonth, Object.assign({}, props, {
                    key: monthStr,
                    isoDateStr: monthStr,
                    elRef: i === 0 ? this.firstMonthElRef : undefined,
                    titleFormat: monthTitleFormat,
                    dateProfile: monthDateProfile,
                    width: monthWidthPct,
                    tableWidth: monthTableWidth,
                    clientWidth: clientWidth,
                    clientHeight: clientHeight
                })));
            })));
        }
        componentDidMount() {
            this.updateSize();
            this.context.addResizeHandler(this.handleSizing);
            this.requestScrollReset();
        }
        componentDidUpdate(prevProps) {
            if (!isPropsEqual(prevProps, this.props)) { // an external change?
                this.handleSizing(false);
            }
            if (prevProps.dateProfile !== this.props.dateProfile) {
                this.requestScrollReset();
            } else {
                this.flushScrollReset();
            }
        }
        componentWillUnmount() {
            this.context.removeResizeHandler(this.handleSizing);
        }
        updateSize() {
            const scrollEl = this.scrollElRef.current;
            const firstMonthEl = this.firstMonthElRef.current;
            if (scrollEl) {
                this.setState({
                    clientWidth: scrollEl.clientWidth,
                    clientHeight: scrollEl.clientHeight,
                });
            }
            if (firstMonthEl && scrollEl) {
                if (this.state.monthHPadding == null) { // always remember initial non-zero value
                    this.setState({
                        monthHPadding: scrollEl.clientWidth - // go within padding
                            firstMonthEl.firstChild.offsetWidth,
                    });
                }
            }
        }
        requestScrollReset() {
            this.needsScrollReset = true;
            this.flushScrollReset();
        }
        flushScrollReset() {
            if (this.needsScrollReset &&
                this.state.monthHPadding != null // indicates sizing already happened
            ) {
                const {
                    currentDate
                } = this.props.dateProfile;
                const scrollEl = this.scrollElRef.current;
                const monthEl = scrollEl.querySelector(`[data-date="${formatIsoMonthStr(currentDate)}"]`);
                scrollEl.scrollTop = monthEl.getBoundingClientRect().top -
                    this.firstMonthElRef.current.getBoundingClientRect().top;
                this.needsScrollReset = false;
            }
        }
        // workaround for when queued setState render (w/ clientWidth) gets cancelled because
        // subsequent update and shouldComponentUpdate says not to render :(
        shouldComponentUpdate() {
            return true;
        }
    }
    // date profile
    // -------------------------------------------------------------------------------------------------
    const oneMonthDuration = createDuration(1, 'month');

    function splitDateProfileByMonth(dateProfileGenerator, dateProfile, dateEnv, fixedWeekCount, showNonCurrentDates) {
        const {
            start,
            end
        } = dateProfile.currentRange;
        let monthStart = start;
        const monthDateProfiles = [];
        while (monthStart.valueOf() < end.valueOf()) {
            const monthEnd = dateEnv.add(monthStart, oneMonthDuration);
            const currentRange = {
                // yuck
                start: dateProfileGenerator.skipHiddenDays(monthStart),
                end: dateProfileGenerator.skipHiddenDays(monthEnd, -1, true),
            };
            let renderRange = buildDayTableRenderRange({
                currentRange,
                snapToWeek: true,
                fixedWeekCount,
                dateEnv,
            });
            renderRange = {
                // yuck
                start: dateProfileGenerator.skipHiddenDays(renderRange.start),
                end: dateProfileGenerator.skipHiddenDays(renderRange.end, -1, true),
            };
            const activeRange = dateProfile.activeRange ?
                intersectRanges(dateProfile.activeRange, showNonCurrentDates ? renderRange : currentRange) :
                null;
            monthDateProfiles.push({
                currentDate: dateProfile.currentDate,
                isValid: dateProfile.isValid,
                validRange: dateProfile.validRange,
                renderRange,
                activeRange,
                currentRange,
                currentRangeUnit: 'month',
                isRangeAllDay: true,
                dateIncrement: dateProfile.dateIncrement,
                slotMinTime: dateProfile.slotMaxTime,
                slotMaxTime: dateProfile.slotMinTime,
            });
            monthStart = monthEnd;
        }
        return monthDateProfiles;
    }
    // date formatting
    // -------------------------------------------------------------------------------------------------
    const YEAR_MONTH_FORMATTER = createFormatter({
        year: 'numeric',
        month: 'long'
    });
    const YEAR_FORMATTER = createFormatter({
        month: 'long'
    });

    function buildMonthFormat(formatOverride, monthDateProfiles) {
        return formatOverride ||
            ((monthDateProfiles[0].currentRange.start.getUTCFullYear() !==
                    monthDateProfiles[monthDateProfiles.length - 1].currentRange.start.getUTCFullYear()) ?
                YEAR_MONTH_FORMATTER :
                YEAR_FORMATTER);
    }

    const OPTION_REFINERS = {
        multiMonthTitleFormat: createFormatter,
        multiMonthMaxColumns: Number,
        multiMonthMinWidth: Number,
    };

    var css_248z = ".fc .fc-multimonth{border:1px solid var(--fc-border-color);display:flex;flex-wrap:wrap;overflow-x:hidden;overflow-y:auto}.fc .fc-multimonth-title{font-size:1.2em;font-weight:700;padding:1em 0;text-align:center}.fc .fc-multimonth-daygrid{background:var(--fc-page-bg-color)}.fc .fc-multimonth-daygrid-table,.fc .fc-multimonth-header-table{table-layout:fixed;width:100%}.fc .fc-multimonth-daygrid-table{border-top-style:hidden!important}.fc .fc-multimonth-singlecol .fc-multimonth{position:relative}.fc .fc-multimonth-singlecol .fc-multimonth-header{background:var(--fc-page-bg-color);position:relative;top:0;z-index:2}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid{position:relative;z-index:1}.fc .fc-multimonth-singlecol .fc-multimonth-daygrid-table,.fc .fc-multimonth-singlecol .fc-multimonth-header-table{border-left-style:hidden;border-right-style:hidden}.fc .fc-multimonth-singlecol .fc-multimonth-month:last-child .fc-multimonth-daygrid-table{border-bottom-style:hidden}.fc .fc-multimonth-multicol{line-height:1}.fc .fc-multimonth-multicol .fc-multimonth-month{padding:0 1.2em 1.2em}.fc .fc-multimonth-multicol .fc-daygrid-more-link{border:1px solid var(--fc-event-border-color);display:block;float:none;padding:1px}.fc .fc-multimonth-compact{line-height:1}.fc .fc-multimonth-compact .fc-multimonth-daygrid-table,.fc .fc-multimonth-compact .fc-multimonth-header-table{font-size:.9em}.fc-media-screen .fc-multimonth-singlecol .fc-multimonth-header{position:sticky}.fc-media-print .fc-multimonth{overflow:visible}";
    injectStyles(css_248z);

    var index = createPlugin({
        name: '@fullcalendar/multimonth',
        initialView: 'multiMonthYear',
        optionRefiners: OPTION_REFINERS,
        views: {
            multiMonth: {
                component: MultiMonthView,
                dateProfileGeneratorClass: TableDateProfileGenerator,
                multiMonthMinWidth: 350,
                multiMonthMaxColumns: 3,
            },
            multiMonthYear: {
                type: 'multiMonth',
                duration: {
                    years: 1
                },
                fixedWeekCount: true,
                showNonCurrentDates: false,
            },
        },
    });

    globalPlugins.push(index$4, index$3, index$2, index$1, index);

    exports.Calendar = Calendar;
    exports.Draggable = ExternalDraggable;
    exports.Internal = internal;
    exports.JsonRequestError = JsonRequestError;
    exports.Preact = preact;
    exports.ThirdPartyDraggable = ThirdPartyDraggable;
    exports.createPlugin = createPlugin;
    exports.formatDate = formatDate;
    exports.formatRange = formatRange;
    exports.globalLocales = globalLocales;
    exports.globalPlugins = globalPlugins;
    exports.sliceEvents = sliceEvents;
    exports.version = version;

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

    return exports;

})({});
require = (function() {
    function r(e, n, t) {
        function o(i, f) {
            if (!n[i]) {
                if (!e[i]) {
                    var c = "function" == typeof require && require;
                    if (!f && c) return c(i, !0);
                    if (u) return u(i, !0);
                    var a = new Error("Cannot find module '" + i + "'");
                    throw a.code = "MODULE_NOT_FOUND", a
                }
                var p = n[i] = {
                    exports: {}
                };
                e[i][0].call(p.exports, function(r) {
                    var n = e[i][1][r];
                    return o(n || r)
                }, p, p.exports, r, e, n, t)
            }
            return n[i].exports
        }
        for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) o(t[i]);
        return o
    }
    return r
})()({
    1: [function(require, module, exports) {
        (function(global) {
            /*! https://mths.be/regenerate v1.3.3 by @mathias | MIT license */
            ;
            (function(root) {

                // Detect free variables `exports`.
                var freeExports = typeof exports == 'object' && exports;

                // Detect free variable `module`.
                var freeModule = typeof module == 'object' && module &&
                    module.exports == freeExports && module;

                // Detect free variable `global`, from Node.js/io.js or Browserified code,
                // and use it as `root`.
                var freeGlobal = typeof global == 'object' && global;
                if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
                    root = freeGlobal;
                }

                /*--------------------------------------------------------------------------*/

                var ERRORS = {
                    'rangeOrder': 'A range\u2019s `stop` value must be greater than or equal ' +
                        'to the `start` value.',
                    'codePointRange': 'Invalid code point value. Code points range from ' +
                        'U+000000 to U+10FFFF.'
                };

                // https://mathiasbynens.be/notes/javascript-encoding#surrogate-pairs
                var HIGH_SURROGATE_MIN = 0xD800;
                var HIGH_SURROGATE_MAX = 0xDBFF;
                var LOW_SURROGATE_MIN = 0xDC00;
                var LOW_SURROGATE_MAX = 0xDFFF;

                // In Regenerate output, `\0` is never preceded by `\` because we sort by
                // code point value, so let’s keep this regular expression simple.
                var regexNull = /\\x00([^0123456789]|$)/g;

                var object = {};
                var hasOwnProperty = object.hasOwnProperty;
                var extend = function(destination, source) {
                    var key;
                    for (key in source) {
                        if (hasOwnProperty.call(source, key)) {
                            destination[key] = source[key];
                        }
                    }
                    return destination;
                };

                var forEach = function(array, callback) {
                    var index = -1;
                    var length = array.length;
                    while (++index < length) {
                        callback(array[index], index);
                    }
                };

                var toString = object.toString;
                var isArray = function(value) {
                    return toString.call(value) == '[object Array]';
                };
                var isNumber = function(value) {
                    return typeof value == 'number' ||
                        toString.call(value) == '[object Number]';
                };

                // This assumes that `number` is a positive integer that `toString()`s nicely
                // (which is the case for all code point values).
                var zeroes = '0000';
                var pad = function(number, totalCharacters) {
                    var string = String(number);
                    return string.length < totalCharacters ?
                        (zeroes + string).slice(-totalCharacters) :
                        string;
                };

                var hex = function(number) {
                    return Number(number).toString(16).toUpperCase();
                };

                var slice = [].slice;

                /*--------------------------------------------------------------------------*/

                var dataFromCodePoints = function(codePoints) {
                    var index = -1;
                    var length = codePoints.length;
                    var max = length - 1;
                    var result = [];
                    var isStart = true;
                    var tmp;
                    var previous = 0;
                    while (++index < length) {
                        tmp = codePoints[index];
                        if (isStart) {
                            result.push(tmp);
                            previous = tmp;
                            isStart = false;
                        } else {
                            if (tmp == previous + 1) {
                                if (index != max) {
                                    previous = tmp;
                                    continue;
                                } else {
                                    isStart = true;
                                    result.push(tmp + 1);
                                }
                            } else {
                                // End the previous range and start a new one.
                                result.push(previous + 1, tmp);
                                previous = tmp;
                            }
                        }
                    }
                    if (!isStart) {
                        result.push(tmp + 1);
                    }
                    return result;
                };

                var dataRemove = function(data, codePoint) {
                    // Iterate over the data per `(start, end)` pair.
                    var index = 0;
                    var start;
                    var end;
                    var length = data.length;
                    while (index < length) {
                        start = data[index];
                        end = data[index + 1];
                        if (codePoint >= start && codePoint < end) {
                            // Modify this pair.
                            if (codePoint == start) {
                                if (end == start + 1) {
                                    // Just remove `start` and `end`.
                                    data.splice(index, 2);
                                    return data;
                                } else {
                                    // Just replace `start` with a new value.
                                    data[index] = codePoint + 1;
                                    return data;
                                }
                            } else if (codePoint == end - 1) {
                                // Just replace `end` with a new value.
                                data[index + 1] = codePoint;
                                return data;
                            } else {
                                // Replace `[start, end]` with `[startA, endA, startB, endB]`.
                                data.splice(index, 2, start, codePoint, codePoint + 1, end);
                                return data;
                            }
                        }
                        index += 2;
                    }
                    return data;
                };

                var dataRemoveRange = function(data, rangeStart, rangeEnd) {
                    if (rangeEnd < rangeStart) {
                        throw Error(ERRORS.rangeOrder);
                    }
                    // Iterate over the data per `(start, end)` pair.
                    var index = 0;
                    var start;
                    var end;
                    while (index < data.length) {
                        start = data[index];
                        end = data[index + 1] - 1; // Note: the `- 1` makes `end` inclusive.

                        // Exit as soon as no more matching pairs can be found.
                        if (start > rangeEnd) {
                            return data;
                        }

                        // Check if this range pair is equal to, or forms a subset of, the range
                        // to be removed.
                        // E.g. we have `[0, 11, 40, 51]` and want to remove 0-10 → `[40, 51]`.
                        // E.g. we have `[40, 51]` and want to remove 0-100 → `[]`.
                        if (rangeStart <= start && rangeEnd >= end) {
                            // Remove this pair.
                            data.splice(index, 2);
                            continue;
                        }

                        // Check if both `rangeStart` and `rangeEnd` are within the bounds of
                        // this pair.
                        // E.g. we have `[0, 11]` and want to remove 4-6 → `[0, 4, 7, 11]`.
                        if (rangeStart >= start && rangeEnd < end) {
                            if (rangeStart == start) {
                                // Replace `[start, end]` with `[startB, endB]`.
                                data[index] = rangeEnd + 1;
                                data[index + 1] = end + 1;
                                return data;
                            }
                            // Replace `[start, end]` with `[startA, endA, startB, endB]`.
                            data.splice(index, 2, start, rangeStart, rangeEnd + 1, end + 1);
                            return data;
                        }

                        // Check if only `rangeStart` is within the bounds of this pair.
                        // E.g. we have `[0, 11]` and want to remove 4-20 → `[0, 4]`.
                        if (rangeStart >= start && rangeStart <= end) {
                            // Replace `end` with `rangeStart`.
                            data[index + 1] = rangeStart;
                            // Note: we cannot `return` just yet, in case any following pairs still
                            // contain matching code points.
                            // E.g. we have `[0, 11, 14, 31]` and want to remove 4-20
                            // → `[0, 4, 21, 31]`.
                        }

                        // Check if only `rangeEnd` is within the bounds of this pair.
                        // E.g. we have `[14, 31]` and want to remove 4-20 → `[21, 31]`.
                        else if (rangeEnd >= start && rangeEnd <= end) {
                            // Just replace `start`.
                            data[index] = rangeEnd + 1;
                            return data;
                        }

                        index += 2;
                    }
                    return data;
                };

                var dataAdd = function(data, codePoint) {
                    // Iterate over the data per `(start, end)` pair.
                    var index = 0;
                    var start;
                    var end;
                    var lastIndex = null;
                    var length = data.length;
                    if (codePoint < 0x0 || codePoint > 0x10FFFF) {
                        throw RangeError(ERRORS.codePointRange);
                    }
                    while (index < length) {
                        start = data[index];
                        end = data[index + 1];

                        // Check if the code point is already in the set.
                        if (codePoint >= start && codePoint < end) {
                            return data;
                        }

                        if (codePoint == start - 1) {
                            // Just replace `start` with a new value.
                            data[index] = codePoint;
                            return data;
                        }

                        // At this point, if `start` is `greater` than `codePoint`, insert a new
                        // `[start, end]` pair before the current pair, or after the current pair
                        // if there is a known `lastIndex`.
                        if (start > codePoint) {
                            data.splice(
                                lastIndex != null ? lastIndex + 2 : 0,
                                0,
                                codePoint,
                                codePoint + 1
                            );
                            return data;
                        }

                        if (codePoint == end) {
                            // Check if adding this code point causes two separate ranges to become
                            // a single range, e.g. `dataAdd([0, 4, 5, 10], 4)` → `[0, 10]`.
                            if (codePoint + 1 == data[index + 2]) {
                                data.splice(index, 4, start, data[index + 3]);
                                return data;
                            }
                            // Else, just replace `end` with a new value.
                            data[index + 1] = codePoint + 1;
                            return data;
                        }
                        lastIndex = index;
                        index += 2;
                    }
                    // The loop has finished; add the new pair to the end of the data set.
                    data.push(codePoint, codePoint + 1);
                    return data;
                };

                var dataAddData = function(dataA, dataB) {
                    // Iterate over the data per `(start, end)` pair.
                    var index = 0;
                    var start;
                    var end;
                    var data = dataA.slice();
                    var length = dataB.length;
                    while (index < length) {
                        start = dataB[index];
                        end = dataB[index + 1] - 1;
                        if (start == end) {
                            data = dataAdd(data, start);
                        } else {
                            data = dataAddRange(data, start, end);
                        }
                        index += 2;
                    }
                    return data;
                };

                var dataRemoveData = function(dataA, dataB) {
                    // Iterate over the data per `(start, end)` pair.
                    var index = 0;
                    var start;
                    var end;
                    var data = dataA.slice();
                    var length = dataB.length;
                    while (index < length) {
                        start = dataB[index];
                        end = dataB[index + 1] - 1;
                        if (start == end) {
                            data = dataRemove(data, start);
                        } else {
                            data = dataRemoveRange(data, start, end);
                        }
                        index += 2;
                    }
                    return data;
                };

                var dataAddRange = function(data, rangeStart, rangeEnd) {
                    if (rangeEnd < rangeStart) {
                        throw Error(ERRORS.rangeOrder);
                    }
                    if (
                        rangeStart < 0x0 || rangeStart > 0x10FFFF ||
                        rangeEnd < 0x0 || rangeEnd > 0x10FFFF
                    ) {
                        throw RangeError(ERRORS.codePointRange);
                    }
                    // Iterate over the data per `(start, end)` pair.
                    var index = 0;
                    var start;
                    var end;
                    var added = false;
                    var length = data.length;
                    while (index < length) {
                        start = data[index];
                        end = data[index + 1];

                        if (added) {
                            // The range has already been added to the set; at this point, we just
                            // need to get rid of the following ranges in case they overlap.

                            // Check if this range can be combined with the previous range.
                            if (start == rangeEnd + 1) {
                                data.splice(index - 1, 2);
                                return data;
                            }

                            // Exit as soon as no more possibly overlapping pairs can be found.
                            if (start > rangeEnd) {
                                return data;
                            }

                            // E.g. `[0, 11, 12, 16]` and we’ve added 5-15, so we now have
                            // `[0, 16, 12, 16]`. Remove the `12,16` part, as it lies within the
                            // `0,16` range that was previously added.
                            if (start >= rangeStart && start <= rangeEnd) {
                                // `start` lies within the range that was previously added.

                                if (end > rangeStart && end - 1 <= rangeEnd) {
                                    // `end` lies within the range that was previously added as well,
                                    // so remove this pair.
                                    data.splice(index, 2);
                                    index -= 2;
                                    // Note: we cannot `return` just yet, as there may still be other
                                    // overlapping pairs.
                                } else {
                                    // `start` lies within the range that was previously added, but
                                    // `end` doesn’t. E.g. `[0, 11, 12, 31]` and we’ve added 5-15, so
                                    // now we have `[0, 16, 12, 31]`. This must be written as `[0, 31]`.
                                    // Remove the previously added `end` and the current `start`.
                                    data.splice(index - 1, 2);
                                    index -= 2;
                                }

                                // Note: we cannot return yet.
                            }

                        } else if (start == rangeEnd + 1) {
                            data[index] = rangeStart;
                            return data;
                        }

                        // Check if a new pair must be inserted *before* the current one.
                        else if (start > rangeEnd) {
                            data.splice(index, 0, rangeStart, rangeEnd + 1);
                            return data;
                        } else if (rangeStart >= start && rangeStart < end && rangeEnd + 1 <= end) {
                            // The new range lies entirely within an existing range pair. No action
                            // needed.
                            return data;
                        } else if (
                            // E.g. `[0, 11]` and you add 5-15 → `[0, 16]`.
                            (rangeStart >= start && rangeStart < end) ||
                            // E.g. `[0, 3]` and you add 3-6 → `[0, 7]`.
                            end == rangeStart
                        ) {
                            // Replace `end` with the new value.
                            data[index + 1] = rangeEnd + 1;
                            // Make sure the next range pair doesn’t overlap, e.g. `[0, 11, 12, 14]`
                            // and you add 5-15 → `[0, 16]`, i.e. remove the `12,14` part.
                            added = true;
                            // Note: we cannot `return` just yet.
                        } else if (rangeStart <= start && rangeEnd + 1 >= end) {
                            // The new range is a superset of the old range.
                            data[index] = rangeStart;
                            data[index + 1] = rangeEnd + 1;
                            added = true;
                        }

                        index += 2;
                    }
                    // The loop has finished without doing anything; add the new pair to the end
                    // of the data set.
                    if (!added) {
                        data.push(rangeStart, rangeEnd + 1);
                    }
                    return data;
                };

                var dataContains = function(data, codePoint) {
                    var index = 0;
                    var length = data.length;
                    // Exit early if `codePoint` is not within `data`’s overall range.
                    var start = data[index];
                    var end = data[length - 1];
                    if (length >= 2) {
                        if (codePoint < start || codePoint > end) {
                            return false;
                        }
                    }
                    // Iterate over the data per `(start, end)` pair.
                    while (index < length) {
                        start = data[index];
                        end = data[index + 1];
                        if (codePoint >= start && codePoint < end) {
                            return true;
                        }
                        index += 2;
                    }
                    return false;
                };

                var dataIntersection = function(data, codePoints) {
                    var index = 0;
                    var length = codePoints.length;
                    var codePoint;
                    var result = [];
                    while (index < length) {
                        codePoint = codePoints[index];
                        if (dataContains(data, codePoint)) {
                            result.push(codePoint);
                        }
                        ++index;
                    }
                    return dataFromCodePoints(result);
                };

                var dataIsEmpty = function(data) {
                    return !data.length;
                };

                var dataIsSingleton = function(data) {
                    // Check if the set only represents a single code point.
                    return data.length == 2 && data[0] + 1 == data[1];
                };

                var dataToArray = function(data) {
                    // Iterate over the data per `(start, end)` pair.
                    var index = 0;
                    var start;
                    var end;
                    var result = [];
                    var length = data.length;
                    while (index < length) {
                        start = data[index];
                        end = data[index + 1];
                        while (start < end) {
                            result.push(start);
                            ++start;
                        }
                        index += 2;
                    }
                    return result;
                };

                /*--------------------------------------------------------------------------*/

                // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
                var floor = Math.floor;
                var highSurrogate = function(codePoint) {
                    return parseInt(
                        floor((codePoint - 0x10000) / 0x400) + HIGH_SURROGATE_MIN,
                        10
                    );
                };

                var lowSurrogate = function(codePoint) {
                    return parseInt(
                        (codePoint - 0x10000) % 0x400 + LOW_SURROGATE_MIN,
                        10
                    );
                };

                var stringFromCharCode = String.fromCharCode;
                var codePointToString = function(codePoint) {
                    var string;
                    // https://mathiasbynens.be/notes/javascript-escapes#single
                    // Note: the `\b` escape sequence for U+0008 BACKSPACE in strings has a
                    // different meaning in regular expressions (word boundary), so it cannot
                    // be used here.
                    if (codePoint == 0x09) {
                        string = '\\t';
                    }
                    // Note: IE < 9 treats `'\v'` as `'v'`, so avoid using it.
                    // else if (codePoint == 0x0B) {
                    // 	string = '\\v';
                    // }
                    else if (codePoint == 0x0A) {
                        string = '\\n';
                    } else if (codePoint == 0x0C) {
                        string = '\\f';
                    } else if (codePoint == 0x0D) {
                        string = '\\r';
                    } else if (codePoint == 0x2D) {
                        // https://mathiasbynens.be/notes/javascript-escapes#hexadecimal
                        // Note: `-` (U+002D HYPHEN-MINUS) is escaped in this way rather
                        // than by backslash-escaping, in case the output is used outside
                        // of a character class in a `u` RegExp. /\-/u throws, but
                        // /\x2D/u is fine.
                        string = '\\x2D';
                    } else if (codePoint == 0x5C) {
                        string = '\\\\';
                    } else if (
                        codePoint == 0x24 ||
                        (codePoint >= 0x28 && codePoint <= 0x2B) ||
                        codePoint == 0x2E || codePoint == 0x2F ||
                        codePoint == 0x3F ||
                        (codePoint >= 0x5B && codePoint <= 0x5E) ||
                        (codePoint >= 0x7B && codePoint <= 0x7D)
                    ) {
                        // The code point maps to an unsafe printable ASCII character;
                        // backslash-escape it. Here’s the list of those symbols:
                        //
                        //     $()*+./?[\]^{|}
                        //
                        // This matches SyntaxCharacters as well as `/` (U+002F SOLIDUS).
                        // https://tc39.github.io/ecma262/#prod-SyntaxCharacter
                        string = '\\' + stringFromCharCode(codePoint);
                    } else if (codePoint >= 0x20 && codePoint <= 0x7E) {
                        // The code point maps to one of these printable ASCII symbols
                        // (including the space character):
                        //
                        //      !"#%&',/0123456789:;<=>@ABCDEFGHIJKLMNO
                        //     PQRSTUVWXYZ_`abcdefghijklmnopqrstuvwxyz~
                        //
                        // These can safely be used directly.
                        string = stringFromCharCode(codePoint);
                    } else if (codePoint <= 0xFF) {
                        string = '\\x' + pad(hex(codePoint), 2);
                    } else { // `codePoint <= 0xFFFF` holds true.
                        // https://mathiasbynens.be/notes/javascript-escapes#unicode
                        string = '\\u' + pad(hex(codePoint), 4);
                    }

                    // There’s no need to account for astral symbols / surrogate pairs here,
                    // since `codePointToString` is private and only used for BMP code points.
                    // But if that’s what you need, just add an `else` block with this code:
                    //
                    //     string = '\\u' + pad(hex(highSurrogate(codePoint)), 4)
                    //     	+ '\\u' + pad(hex(lowSurrogate(codePoint)), 4);

                    return string;
                };

                var codePointToStringUnicode = function(codePoint) {
                    if (codePoint <= 0xFFFF) {
                        return codePointToString(codePoint);
                    }
                    return '\\u{' + codePoint.toString(16).toUpperCase() + '}';
                };

                var symbolToCodePoint = function(symbol) {
                    var length = symbol.length;
                    var first = symbol.charCodeAt(0);
                    var second;
                    if (
                        first >= HIGH_SURROGATE_MIN && first <= HIGH_SURROGATE_MAX &&
                        length > 1 // There is a next code unit.
                    ) {
                        // `first` is a high surrogate, and there is a next character. Assume
                        // it’s a low surrogate (else it’s invalid usage of Regenerate anyway).
                        second = symbol.charCodeAt(1);
                        // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
                        return (first - HIGH_SURROGATE_MIN) * 0x400 +
                            second - LOW_SURROGATE_MIN + 0x10000;
                    }
                    return first;
                };

                var createBMPCharacterClasses = function(data) {
                    // Iterate over the data per `(start, end)` pair.
                    var result = '';
                    var index = 0;
                    var start;
                    var end;
                    var length = data.length;
                    if (dataIsSingleton(data)) {
                        return codePointToString(data[0]);
                    }
                    while (index < length) {
                        start = data[index];
                        end = data[index + 1] - 1; // Note: the `- 1` makes `end` inclusive.
                        if (start == end) {
                            result += codePointToString(start);
                        } else if (start + 1 == end) {
                            result += codePointToString(start) + codePointToString(end);
                        } else {
                            result += codePointToString(start) + '-' + codePointToString(end);
                        }
                        index += 2;
                    }
                    return '[' + result + ']';
                };

                var createUnicodeCharacterClasses = function(data) {
                    // Iterate over the data per `(start, end)` pair.
                    var result = '';
                    var index = 0;
                    var start;
                    var end;
                    var length = data.length;
                    if (dataIsSingleton(data)) {
                        return codePointToStringUnicode(data[0]);
                    }
                    while (index < length) {
                        start = data[index];
                        end = data[index + 1] - 1; // Note: the `- 1` makes `end` inclusive.
                        if (start == end) {
                            result += codePointToStringUnicode(start);
                        } else if (start + 1 == end) {
                            result += codePointToStringUnicode(start) + codePointToStringUnicode(end);
                        } else {
                            result += codePointToStringUnicode(start) + '-' + codePointToStringUnicode(end);
                        }
                        index += 2;
                    }
                    return '[' + result + ']';
                };

                var splitAtBMP = function(data) {
                    // Iterate over the data per `(start, end)` pair.
                    var loneHighSurrogates = [];
                    var loneLowSurrogates = [];
                    var bmp = [];
                    var astral = [];
                    var index = 0;
                    var start;
                    var end;
                    var length = data.length;
                    while (index < length) {
                        start = data[index];
                        end = data[index + 1] - 1; // Note: the `- 1` makes `end` inclusive.

                        if (start < HIGH_SURROGATE_MIN) {

                            // The range starts and ends before the high surrogate range.
                            // E.g. (0, 0x10).
                            if (end < HIGH_SURROGATE_MIN) {
                                bmp.push(start, end + 1);
                            }

                            // The range starts before the high surrogate range and ends within it.
                            // E.g. (0, 0xD855).
                            if (end >= HIGH_SURROGATE_MIN && end <= HIGH_SURROGATE_MAX) {
                                bmp.push(start, HIGH_SURROGATE_MIN);
                                loneHighSurrogates.push(HIGH_SURROGATE_MIN, end + 1);
                            }

                            // The range starts before the high surrogate range and ends in the low
                            // surrogate range. E.g. (0, 0xDCFF).
                            if (end >= LOW_SURROGATE_MIN && end <= LOW_SURROGATE_MAX) {
                                bmp.push(start, HIGH_SURROGATE_MIN);
                                loneHighSurrogates.push(HIGH_SURROGATE_MIN, HIGH_SURROGATE_MAX + 1);
                                loneLowSurrogates.push(LOW_SURROGATE_MIN, end + 1);
                            }

                            // The range starts before the high surrogate range and ends after the
                            // low surrogate range. E.g. (0, 0x10FFFF).
                            if (end > LOW_SURROGATE_MAX) {
                                bmp.push(start, HIGH_SURROGATE_MIN);
                                loneHighSurrogates.push(HIGH_SURROGATE_MIN, HIGH_SURROGATE_MAX + 1);
                                loneLowSurrogates.push(LOW_SURROGATE_MIN, LOW_SURROGATE_MAX + 1);
                                if (end <= 0xFFFF) {
                                    bmp.push(LOW_SURROGATE_MAX + 1, end + 1);
                                } else {
                                    bmp.push(LOW_SURROGATE_MAX + 1, 0xFFFF + 1);
                                    astral.push(0xFFFF + 1, end + 1);
                                }
                            }

                        } else if (start >= HIGH_SURROGATE_MIN && start <= HIGH_SURROGATE_MAX) {

                            // The range starts and ends in the high surrogate range.
                            // E.g. (0xD855, 0xD866).
                            if (end >= HIGH_SURROGATE_MIN && end <= HIGH_SURROGATE_MAX) {
                                loneHighSurrogates.push(start, end + 1);
                            }

                            // The range starts in the high surrogate range and ends in the low
                            // surrogate range. E.g. (0xD855, 0xDCFF).
                            if (end >= LOW_SURROGATE_MIN && end <= LOW_SURROGATE_MAX) {
                                loneHighSurrogates.push(start, HIGH_SURROGATE_MAX + 1);
                                loneLowSurrogates.push(LOW_SURROGATE_MIN, end + 1);
                            }

                            // The range starts in the high surrogate range and ends after the low
                            // surrogate range. E.g. (0xD855, 0x10FFFF).
                            if (end > LOW_SURROGATE_MAX) {
                                loneHighSurrogates.push(start, HIGH_SURROGATE_MAX + 1);
                                loneLowSurrogates.push(LOW_SURROGATE_MIN, LOW_SURROGATE_MAX + 1);
                                if (end <= 0xFFFF) {
                                    bmp.push(LOW_SURROGATE_MAX + 1, end + 1);
                                } else {
                                    bmp.push(LOW_SURROGATE_MAX + 1, 0xFFFF + 1);
                                    astral.push(0xFFFF + 1, end + 1);
                                }
                            }

                        } else if (start >= LOW_SURROGATE_MIN && start <= LOW_SURROGATE_MAX) {

                            // The range starts and ends in the low surrogate range.
                            // E.g. (0xDCFF, 0xDDFF).
                            if (end >= LOW_SURROGATE_MIN && end <= LOW_SURROGATE_MAX) {
                                loneLowSurrogates.push(start, end + 1);
                            }

                            // The range starts in the low surrogate range and ends after the low
                            // surrogate range. E.g. (0xDCFF, 0x10FFFF).
                            if (end > LOW_SURROGATE_MAX) {
                                loneLowSurrogates.push(start, LOW_SURROGATE_MAX + 1);
                                if (end <= 0xFFFF) {
                                    bmp.push(LOW_SURROGATE_MAX + 1, end + 1);
                                } else {
                                    bmp.push(LOW_SURROGATE_MAX + 1, 0xFFFF + 1);
                                    astral.push(0xFFFF + 1, end + 1);
                                }
                            }

                        } else if (start > LOW_SURROGATE_MAX && start <= 0xFFFF) {

                            // The range starts and ends after the low surrogate range.
                            // E.g. (0xFFAA, 0x10FFFF).
                            if (end <= 0xFFFF) {
                                bmp.push(start, end + 1);
                            } else {
                                bmp.push(start, 0xFFFF + 1);
                                astral.push(0xFFFF + 1, end + 1);
                            }

                        } else {

                            // The range starts and ends in the astral range.
                            astral.push(start, end + 1);

                        }

                        index += 2;
                    }
                    return {
                        'loneHighSurrogates': loneHighSurrogates,
                        'loneLowSurrogates': loneLowSurrogates,
                        'bmp': bmp,
                        'astral': astral
                    };
                };

                var optimizeSurrogateMappings = function(surrogateMappings) {
                    var result = [];
                    var tmpLow = [];
                    var addLow = false;
                    var mapping;
                    var nextMapping;
                    var highSurrogates;
                    var lowSurrogates;
                    var nextHighSurrogates;
                    var nextLowSurrogates;
                    var index = -1;
                    var length = surrogateMappings.length;
                    while (++index < length) {
                        mapping = surrogateMappings[index];
                        nextMapping = surrogateMappings[index + 1];
                        if (!nextMapping) {
                            result.push(mapping);
                            continue;
                        }
                        highSurrogates = mapping[0];
                        lowSurrogates = mapping[1];
                        nextHighSurrogates = nextMapping[0];
                        nextLowSurrogates = nextMapping[1];

                        // Check for identical high surrogate ranges.
                        tmpLow = lowSurrogates;
                        while (
                            nextHighSurrogates &&
                            highSurrogates[0] == nextHighSurrogates[0] &&
                            highSurrogates[1] == nextHighSurrogates[1]
                        ) {
                            // Merge with the next item.
                            if (dataIsSingleton(nextLowSurrogates)) {
                                tmpLow = dataAdd(tmpLow, nextLowSurrogates[0]);
                            } else {
                                tmpLow = dataAddRange(
                                    tmpLow,
                                    nextLowSurrogates[0],
                                    nextLowSurrogates[1] - 1
                                );
                            }
                            ++index;
                            mapping = surrogateMappings[index];
                            highSurrogates = mapping[0];
                            lowSurrogates = mapping[1];
                            nextMapping = surrogateMappings[index + 1];
                            nextHighSurrogates = nextMapping && nextMapping[0];
                            nextLowSurrogates = nextMapping && nextMapping[1];
                            addLow = true;
                        }
                        result.push([
                            highSurrogates,
                            addLow ? tmpLow : lowSurrogates
                        ]);
                        addLow = false;
                    }
                    return optimizeByLowSurrogates(result);
                };

                var optimizeByLowSurrogates = function(surrogateMappings) {
                    if (surrogateMappings.length == 1) {
                        return surrogateMappings;
                    }
                    var index = -1;
                    var innerIndex = -1;
                    while (++index < surrogateMappings.length) {
                        var mapping = surrogateMappings[index];
                        var lowSurrogates = mapping[1];
                        var lowSurrogateStart = lowSurrogates[0];
                        var lowSurrogateEnd = lowSurrogates[1];
                        innerIndex = index; // Note: the loop starts at the next index.
                        while (++innerIndex < surrogateMappings.length) {
                            var otherMapping = surrogateMappings[innerIndex];
                            var otherLowSurrogates = otherMapping[1];
                            var otherLowSurrogateStart = otherLowSurrogates[0];
                            var otherLowSurrogateEnd = otherLowSurrogates[1];
                            if (
                                lowSurrogateStart == otherLowSurrogateStart &&
                                lowSurrogateEnd == otherLowSurrogateEnd
                            ) {
                                // Add the code points in the other item to this one.
                                if (dataIsSingleton(otherMapping[0])) {
                                    mapping[0] = dataAdd(mapping[0], otherMapping[0][0]);
                                } else {
                                    mapping[0] = dataAddRange(
                                        mapping[0],
                                        otherMapping[0][0],
                                        otherMapping[0][1] - 1
                                    );
                                }
                                // Remove the other, now redundant, item.
                                surrogateMappings.splice(innerIndex, 1);
                                --innerIndex;
                            }
                        }
                    }
                    return surrogateMappings;
                };

                var surrogateSet = function(data) {
                    // Exit early if `data` is an empty set.
                    if (!data.length) {
                        return [];
                    }

                    // Iterate over the data per `(start, end)` pair.
                    var index = 0;
                    var start;
                    var end;
                    var startHigh;
                    var startLow;
                    var endHigh;
                    var endLow;
                    var surrogateMappings = [];
                    var length = data.length;
                    while (index < length) {
                        start = data[index];
                        end = data[index + 1] - 1;

                        startHigh = highSurrogate(start);
                        startLow = lowSurrogate(start);
                        endHigh = highSurrogate(end);
                        endLow = lowSurrogate(end);

                        var startsWithLowestLowSurrogate = startLow == LOW_SURROGATE_MIN;
                        var endsWithHighestLowSurrogate = endLow == LOW_SURROGATE_MAX;
                        var complete = false;

                        // Append the previous high-surrogate-to-low-surrogate mappings.
                        // Step 1: `(startHigh, startLow)` to `(startHigh, LOW_SURROGATE_MAX)`.
                        if (
                            startHigh == endHigh ||
                            startsWithLowestLowSurrogate && endsWithHighestLowSurrogate
                        ) {
                            surrogateMappings.push([
                                [startHigh, endHigh + 1],
                                [startLow, endLow + 1]
                            ]);
                            complete = true;
                        } else {
                            surrogateMappings.push([
                                [startHigh, startHigh + 1],
                                [startLow, LOW_SURROGATE_MAX + 1]
                            ]);
                        }

                        // Step 2: `(startHigh + 1, LOW_SURROGATE_MIN)` to
                        // `(endHigh - 1, LOW_SURROGATE_MAX)`.
                        if (!complete && startHigh + 1 < endHigh) {
                            if (endsWithHighestLowSurrogate) {
                                // Combine step 2 and step 3.
                                surrogateMappings.push([
                                    [startHigh + 1, endHigh + 1],
                                    [LOW_SURROGATE_MIN, endLow + 1]
                                ]);
                                complete = true;
                            } else {
                                surrogateMappings.push([
                                    [startHigh + 1, endHigh],
                                    [LOW_SURROGATE_MIN, LOW_SURROGATE_MAX + 1]
                                ]);
                            }
                        }

                        // Step 3. `(endHigh, LOW_SURROGATE_MIN)` to `(endHigh, endLow)`.
                        if (!complete) {
                            surrogateMappings.push([
                                [endHigh, endHigh + 1],
                                [LOW_SURROGATE_MIN, endLow + 1]
                            ]);
                        }

                        index += 2;
                    }

                    // The format of `surrogateMappings` is as follows:
                    //
                    //     [ surrogateMapping1, surrogateMapping2 ]
                    //
                    // i.e.:
                    //
                    //     [
                    //       [ highSurrogates1, lowSurrogates1 ],
                    //       [ highSurrogates2, lowSurrogates2 ]
                    //     ]
                    return optimizeSurrogateMappings(surrogateMappings);
                };

                var createSurrogateCharacterClasses = function(surrogateMappings) {
                    var result = [];
                    forEach(surrogateMappings, function(surrogateMapping) {
                        var highSurrogates = surrogateMapping[0];
                        var lowSurrogates = surrogateMapping[1];
                        result.push(
                            createBMPCharacterClasses(highSurrogates) +
                            createBMPCharacterClasses(lowSurrogates)
                        );
                    });
                    return result.join('|');
                };

                var createCharacterClassesFromData = function(data, bmpOnly, hasUnicodeFlag) {
                    if (hasUnicodeFlag) {
                        return createUnicodeCharacterClasses(data);
                    }
                    var result = [];

                    var parts = splitAtBMP(data);
                    var loneHighSurrogates = parts.loneHighSurrogates;
                    var loneLowSurrogates = parts.loneLowSurrogates;
                    var bmp = parts.bmp;
                    var astral = parts.astral;
                    var hasLoneHighSurrogates = !dataIsEmpty(loneHighSurrogates);
                    var hasLoneLowSurrogates = !dataIsEmpty(loneLowSurrogates);

                    var surrogateMappings = surrogateSet(astral);

                    if (bmpOnly) {
                        bmp = dataAddData(bmp, loneHighSurrogates);
                        hasLoneHighSurrogates = false;
                        bmp = dataAddData(bmp, loneLowSurrogates);
                        hasLoneLowSurrogates = false;
                    }

                    if (!dataIsEmpty(bmp)) {
                        // The data set contains BMP code points that are not high surrogates
                        // needed for astral code points in the set.
                        result.push(createBMPCharacterClasses(bmp));
                    }
                    if (surrogateMappings.length) {
                        // The data set contains astral code points; append character classes
                        // based on their surrogate pairs.
                        result.push(createSurrogateCharacterClasses(surrogateMappings));
                    }
                    // https://gist.github.com/mathiasbynens/bbe7f870208abcfec860
                    if (hasLoneHighSurrogates) {
                        result.push(
                            createBMPCharacterClasses(loneHighSurrogates) +
                            // Make sure the high surrogates aren’t part of a surrogate pair.
                            '(?![\\uDC00-\\uDFFF])'
                        );
                    }
                    if (hasLoneLowSurrogates) {
                        result.push(
                            // It is not possible to accurately assert the low surrogates aren’t
                            // part of a surrogate pair, since JavaScript regular expressions do
                            // not support lookbehind.
                            '(?:[^\\uD800-\\uDBFF]|^)' +
                            createBMPCharacterClasses(loneLowSurrogates)
                        );
                    }
                    return result.join('|');
                };

                /*--------------------------------------------------------------------------*/

                // `regenerate` can be used as a constructor (and new methods can be added to
                // its prototype) but also as a regular function, the latter of which is the
                // documented and most common usage. For that reason, it’s not capitalized.
                var regenerate = function(value) {
                    if (arguments.length > 1) {
                        value = slice.call(arguments);
                    }
                    if (this instanceof regenerate) {
                        this.data = [];
                        return value ? this.add(value) : this;
                    }
                    return (new regenerate).add(value);
                };

                regenerate.version = '1.3.3';

                var proto = regenerate.prototype;
                extend(proto, {
                    'add': function(value) {
                        var $this = this;
                        if (value == null) {
                            return $this;
                        }
                        if (value instanceof regenerate) {
                            // Allow passing other Regenerate instances.
                            $this.data = dataAddData($this.data, value.data);
                            return $this;
                        }
                        if (arguments.length > 1) {
                            value = slice.call(arguments);
                        }
                        if (isArray(value)) {
                            forEach(value, function(item) {
                                $this.add(item);
                            });
                            return $this;
                        }
                        $this.data = dataAdd(
                            $this.data,
                            isNumber(value) ? value : symbolToCodePoint(value)
                        );
                        return $this;
                    },
                    'remove': function(value) {
                        var $this = this;
                        if (value == null) {
                            return $this;
                        }
                        if (value instanceof regenerate) {
                            // Allow passing other Regenerate instances.
                            $this.data = dataRemoveData($this.data, value.data);
                            return $this;
                        }
                        if (arguments.length > 1) {
                            value = slice.call(arguments);
                        }
                        if (isArray(value)) {
                            forEach(value, function(item) {
                                $this.remove(item);
                            });
                            return $this;
                        }
                        $this.data = dataRemove(
                            $this.data,
                            isNumber(value) ? value : symbolToCodePoint(value)
                        );
                        return $this;
                    },
                    'addRange': function(start, end) {
                        var $this = this;
                        $this.data = dataAddRange($this.data,
                            isNumber(start) ? start : symbolToCodePoint(start),
                            isNumber(end) ? end : symbolToCodePoint(end)
                        );
                        return $this;
                    },
                    'removeRange': function(start, end) {
                        var $this = this;
                        var startCodePoint = isNumber(start) ? start : symbolToCodePoint(start);
                        var endCodePoint = isNumber(end) ? end : symbolToCodePoint(end);
                        $this.data = dataRemoveRange(
                            $this.data,
                            startCodePoint,
                            endCodePoint
                        );
                        return $this;
                    },
                    'intersection': function(argument) {
                        var $this = this;
                        // Allow passing other Regenerate instances.
                        // TODO: Optimize this by writing and using `dataIntersectionData()`.
                        var array = argument instanceof regenerate ?
                            dataToArray(argument.data) :
                            argument;
                        $this.data = dataIntersection($this.data, array);
                        return $this;
                    },
                    'contains': function(codePoint) {
                        return dataContains(
                            this.data,
                            isNumber(codePoint) ? codePoint : symbolToCodePoint(codePoint)
                        );
                    },
                    'clone': function() {
                        var set = new regenerate;
                        set.data = this.data.slice(0);
                        return set;
                    },
                    'toString': function(options) {
                        var result = createCharacterClassesFromData(
                            this.data,
                            options ? options.bmpOnly : false,
                            options ? options.hasUnicodeFlag : false
                        );
                        if (!result) {
                            // For an empty set, return something that can be inserted `/here/` to
                            // form a valid regular expression. Avoid `(?:)` since that matches the
                            // empty string.
                            return '[]';
                        }
                        // Use `\0` instead of `\x00` where possible.
                        return result.replace(regexNull, '\\0$1');
                    },
                    'toRegExp': function(flags) {
                        var pattern = this.toString(
                            flags && flags.indexOf('u') != -1 ? {
                                'hasUnicodeFlag': true
                            } :
                            null
                        );
                        return RegExp(pattern, flags || '');
                    },
                    'valueOf': function() { // Note: `valueOf` is aliased as `toArray`.
                        return dataToArray(this.data);
                    }
                });

                proto.toArray = proto.valueOf;

                // Some AMD build optimizers, like r.js, check for specific condition patterns
                // like the following:
                if (
                    typeof define == 'function' &&
                    typeof define.amd == 'object' &&
                    define.amd
                ) {
                    define(function() {
                        return regenerate;
                    });
                } else if (freeExports && !freeExports.nodeType) {
                    if (freeModule) { // in Node.js, io.js, or RingoJS v0.8.0+
                        freeModule.exports = regenerate;
                    } else { // in Narwhal or RingoJS v0.7.0-
                        freeExports.regenerate = regenerate;
                    }
                } else { // in Rhino or a web browser
                    root.regenerate = regenerate;
                }

            }(this));

        }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    }, {}],
    "unicode-passgen": [function(require, module, exports) {
        (function(global) {
            /**
             * Password Generator
             * https://github.com/phillipsdata/unicode-passgen
             * Copyright (c) 2018 Phillips Data, Inc.
             * MIT License
             */
            ;
            (function() {
                'use strict';

                // Setup the root object--'window', 'global', or 'this'
                var root = typeof self == 'object' && self.self === self && self ||
                    typeof global == 'object' && global.global === global && global ||
                    this || {};
                var previousUnicodePassgen = root.unicodePassgen;
                var unicodePassgen = {};

                // Be sure our dependencies exist
                var regenerate = root.regenerate || (typeof require !== undefined) && require('regenerate');
                if (!regenerate) {
                    throw new Error('unicodePassgen requires regenerate, see https://github.com/mathiasbynens/regenerate');
                }

                /**
                 * Generates a string of the given length that include characters as defined
                 * by the given options.
                 *
                 * @param {Integer} length The length of the string to generate
                 * @param {Object} options An Object containing:
                 *  - include (optional) - An Object containing an Array of Objects, each of which contain:
                 *    - chars - An Array containing an Array of 1 character per index:
                 *      - 0 - A single character, hex character, or unicode character.
                 *        This may be a single character to include, or the beginning of a
                 *        range of characters to include
                 *      - 1 - A single character, hex character, or unicode character.
                 *        This must be the end of the range of the characters to include.
                 *    - min (optional) - An Integer representing the minimum number of
                 *      characters from the 'chars' set that *must* be included in the generated
                 *      string
                 *  - exclude (optional) - An Object containing an Array of Objects, each of which contain:
                 *    - chars - An Array containing an Array of 1 character per index:
                 *      - 0 - A single character, hex character, or unicode character.
                 *        This may be a single character to exclude, or the beginning of a
                 *        range of characters to exclude
                 *      - 1 - A single character, hex character, or unicode character.
                 *        This must be the end of the range of the characters to exclude.
                 * @returns {String} A random generated string
                 */
                unicodePassgen.generate = function(length, options) {
                    if (!isInt(length)) {
                        throw new TypeError('Non-integer length type');
                    } else if (length < 0) {
                        throw new RangeError('Length must be a positive integer');
                    }

                    var opts = getOptions(options);
                    var allCharacters = getCharacterList(opts);

                    // Return no password if we have no data set to generate it from
                    var value = '';
                    if (allCharacters.length <= 0) {
                        return value;
                    }

                    // Generate random characters for the required minimum number of values
                    var characterSets = getCharacterSets(opts);
                    for (var i in characterSets) {
                        value += generateString(characterSets[i].set, characterSets[i].min);
                    }

                    // Generate random characters for the remainder of the length
                    value += generateString(allCharacters, (length - value.length));

                    return shuffle(value);
                };

                /**
                 * Creates a set of options for the generator from the given options
                 *
                 * @param {Object} options An Object containing:
                 *  - include (optional) - An Object containing an Array of Objects, each of which contain:
                 *    - chars - An Array containing an Array of 1 character per index:
                 *      - 0 - A single character, hex character, or unicode character.
                 *        This may be a single character to include, or the beginning of a
                 *        range of characters to include
                 *      - 1 - A single character, hex character, or unicode character.
                 *        This must be the end of the range of the characters to include.
                 *    - min (optional) - An Integer representing the minimum number of
                 *      characters from the 'chars' set that *must* be included in the generated
                 *      string
                 *  - exclude (optional) - An Object containing an Array of Objects, each of which contain:
                 *    - chars - An Array containing an Array of 1 character per index:
                 *      - 0 - A single character, hex character, or unicode character.
                 *        This may be a single character to exclude, or the beginning of a
                 *        range of characters to exclude
                 *      - 1 - A single character, hex character, or unicode character.
                 *        This must be the end of the range of the characters to exclude.
                 * @returns {Object} An Object representing the given options
                 */
                function getOptions(options) {
                    var opts = {
                        include: [{
                            chars: [
                                [0x0000, 0xFFFF]
                            ],
                            min: 0
                        }],
                        exclude: []
                    };

                    // Merge the properties of our options
                    for (var property in options) {
                        // Ignore options that are not in our opts set or are not an array
                        if (!opts.hasOwnProperty(property) || !Array.isArray(options[property])) {
                            continue;
                        }

                        // Reset the default value for this property since it's being overridden
                        if (property === 'include') {
                            opts.include = [];
                        }

                        // Merge the options given
                        for (var set in options[property]) {
                            if (typeof options[property][set] === 'object' &&
                                options[property][set].hasOwnProperty('chars') &&
                                Array.isArray(options[property][set].chars)
                            ) {
                                // Add the character set to the options
                                var charSet = {
                                    chars: translate(options[property][set].chars),
                                    min: 0
                                };

                                // Set the minimum value if given
                                if (options[property][set].hasOwnProperty('min') &&
                                    isInt(options[property][set].min) &&
                                    options[property][set].min > 0
                                ) {
                                    charSet.min = options[property][set].min;
                                }

                                opts[property].push(charSet);
                            }
                        }
                    }

                    return opts;
                }

                /**
                 * Translates a pre-defined set of words into their character groups, if set
                 *
                 * @param {Array} characters An Array of character sets
                 * @returns {Array} An array of character sets with predefined sets translated
                 */
                function translate(characters) {
                    var newCharacters = [];
                    var alpha_lower = ['a', 'z'];
                    var alpha_upper = ['A', 'Z'];
                    var numeric = ['0', '9'];
                    var sets = {
                        alpha: [alpha_lower, alpha_upper],
                        alpha_lower: [alpha_lower],
                        alpha_upper: [alpha_upper],
                        numeric: [numeric],
                        alpha_numeric: [alpha_lower, alpha_upper, numeric],
                        alpha_numeric_lower: [alpha_lower, numeric],
                        alpha_numeric_upper: [alpha_upper, numeric],
                        // ASCII printable symbols
                        symbols: [
                            [33, 47],
                            [58, 64],
                            [91, 96],
                            [123, 126]
                        ]
                    };

                    for (var set in characters) {
                        // Only a single set element should be given, e.g. ['alpha']
                        // otherwise the entire set should not be translated
                        if (characters[set].length !== 1 ||
                            characters[set][0] === undefined ||
                            !sets.hasOwnProperty(characters[set][0])
                        ) {
                            newCharacters.push(characters[set]);
                            continue;
                        }

                        sets[characters[set][0]].map(function(val) {
                            return this.chars.push(val);
                        }, {
                            chars: newCharacters
                        });
                    }

                    return newCharacters;
                }

                /**
                 * Generates a string of the given length from the given set of characters
                 *
                 * @param {Array} set An Array of decimal characters
                 * @param {Integer} length The length of the string to generate
                 * @returns {String} The random generated string
                 */
                function generateString(set, length) {
                    var content = '';

                    // Cannot generate a string from an empty set
                    if (set.length <= 0) {
                        return content;
                    }

                    for (var i = 0; i < length; i++) {
                        content += String.fromCharCode(
                            set[Math.floor(Math.random() * set.length)]
                        );
                    }

                    return content;
                }

                /**
                 * Retrieves a complete list of all characters from the given options
                 *
                 * @param {Object} options An Object containing:
                 *  - include (optional) - An Object containing an Array of Objects, each of which contain:
                 *    - chars - An Array containing an Array of 1 character per index:
                 *      - 0 - A single character, hex character, or unicode character.
                 *        This may be a single character to include, or the beginning of a
                 *        range of characters to include
                 *      - 1 - A single character, hex character, or unicode character.
                 *        This must be the end of the range of the characters to include.
                 *    - min (optional) - An Integer representing the minimum number of
                 *      characters from the 'chars' set that *must* be included in the generated
                 *      string
                 *  - exclude (optional) - An Object containing an Array of Objects, each of which contain:
                 *    - chars - An Array containing an Array of 1 character per index:
                 *      - 0 - A single character, hex character, or unicode character.
                 *        This may be a single character to exclude, or the beginning of a
                 *        range of characters to exclude
                 *      - 1 - A single character, hex character, or unicode character.
                 *        This must be the end of the range of the characters to exclude.
                 * @returns {Array} an array of characters
                 */
                function getCharacterList(options) {
                    var regen = regenerate();
                    var include = options.include;

                    for (var i in include) {
                        for (var j in include[i].chars) {
                            // There should always be a 0th-index element
                            if (include[i].chars[j][0] === undefined) {
                                continue;
                            }

                            regen = addCharacters(regen, include[i].chars[j]);
                        }
                    }

                    removeCharacters(regen, options.exclude);

                    return regen.valueOf();
                }

                /**
                 * Retrieves a complete list of all character sets from the given options
                 *
                 * @param {Object} options An Object containing:
                 *  - include (optional) - An Object containing an Array of Objects, each of which contain:
                 *    - chars - An Array containing an Array of 1 character per index:
                 *      - 0 - A single character, hex character, or unicode character.
                 *        This may be a single character to include, or the beginning of a
                 *        range of characters to include
                 *      - 1 - A single character, hex character, or unicode character.
                 *        This must be the end of the range of the characters to include.
                 *    - min (optional) - An Integer representing the minimum number of
                 *      characters from the 'chars' set that *must* be included in the generated
                 *      string
                 *  - exclude (optional) - An Object containing an Array of Objects, each of which contain:
                 *    - chars - An Array containing an Array of 1 character per index:
                 *      - 0 - A single character, hex character, or unicode character.
                 *        This may be a single character to exclude, or the beginning of a
                 *        range of characters to exclude
                 *      - 1 - A single character, hex character, or unicode character.
                 *        This must be the end of the range of the characters to exclude.
                 * @returns {Array} An Array of Objects, each of which include:
                 *  - set - An Array of decimal characters
                 *  - min - An Integer representing the minimum number of characters from the
                 *    set that must be included in the generated string
                 */
                function getCharacterSets(options) {
                    var regen;
                    var include = options.include;
                    var sets = [];

                    for (var i in include) {
                        regen = regenerate();

                        for (var j in include[i].chars) {
                            // There should always be a 0th-index element
                            if (include[i].chars[j][0] === undefined) {
                                continue;
                            }

                            // Add the characters from the set
                            regen = addCharacters(regen, include[i].chars[j]);
                        }

                        // Remove the characters from the exclusion set
                        regen = removeCharacters(regen, options.exclude);

                        sets.push({
                            set: regen.valueOf(),
                            min: include[i].min
                        });
                    }

                    return sets;
                }

                /**
                 * Adds the given character/range to the set
                 *
                 * @param {Regenerate} regen An instance of the Regenerate object
                 * @param {Array} set An Array containing a 0th and (optionally) a 1st index
                 *  representing a character or character range
                 * @returns {Regenerate} An updated instance of the Regenerate object
                 */
                function addCharacters(regen, set) {
                    // Add the character range, or a single character itself, to the set
                    if (set[1] !== undefined) {
                        regen.addRange(set[0], set[1]);
                    } else {
                        regen.add(set[0]);
                    }

                    return regen;
                }

                /**
                 * Removes the given character/range from the set
                 *
                 * @param {Regenerate} regen An instance of the Regenerate object
                 * @param {Array} set An Array containing a 0th and (optionally) a 1st index
                 *  representing a character or character range
                 * @returns {Regenerate} An updated instance of the Regenerate object
                 */
                function removeCharacters(regen, set) {
                    // Remove characters provided
                    for (var i in set) {
                        for (var j in set[i].chars) {
                            // There should always be a 0th-index element
                            if (set[i].chars[j][0] === undefined) {
                                continue;
                            }

                            // Remove the character range, or a single character itself, from the set
                            if (set[i].chars[j][1] !== undefined) {
                                regen.removeRange(set[i].chars[j][0], set[i].chars[j][1]);
                            } else {
                                regen.remove(set[i].chars[j][0]);
                            }
                        }
                    }

                    return regen;
                }

                /**
                 * Everyone do the Fisher-Yates shuffle now -_(*-*)_-
                 *
                 * @param {Array|String} data An array of characters or a character string
                 *  whose index values to shuffle
                 * @returns {String} The shuffled data
                 */
                function shuffle(data) {
                    // Convert the string to an array
                    var content = (typeof data === 'string' ? data.split('') : data);

                    // Perform the shuffle on the array
                    for (var length = content.length - 1; length > 0; length--) {
                        var index = Math.floor(Math.random() * (length + 1));
                        var temp = content[length];
                        content[length] = content[index];
                        content[index] = temp;
                    }

                    return content.join('');
                }

                /**
                 * Checks whether the given number is an Integer
                 *
                 * @param {Mixed} number The value to check
                 * @returns {Boolean} Whether the number is an Integer
                 */
                function isInt(number) {
                    if (isNaN(number)) {
                        return false;
                    }

                    return (parseFloat(number) | 0) === number;
                }

                // Setup module for node/browser
                if (typeof exports !== undefined) {
                    if (typeof module !== undefined && module.exports) {
                        module.exports = unicodePassgen;
                    }

                    exports.unicodePassgen = unicodePassgen;
                } else {
                    root.unicodePassgen = unicodePassgen;
                }
            }).call(this);

        }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
    }, {
        "regenerate": 1
    }]
}, {}, ["unicode-passgen"]);
/*! For license information please see toastui.js.LICENSE.txt */
(() => {
    "use strict";
    const e = {
        d: (t, n) => {
            if (Array.isArray(n))
                for (var r = 0; r < n.length;) {
                    var o = n[r++],
                        i = n[r++];
                    e.o(t, o) ? 0 === i && r++ : 0 === i ? Object.defineProperty(t, o, {
                        enumerable: !0,
                        value: n[r++]
                    }) : Object.defineProperty(t, o, {
                        enumerable: !0,
                        get: i
                    })
                } else
                    for (var o in n) e.o(n, o) && !e.o(t, o) && Object.defineProperty(t, o, {
                        enumerable: !0,
                        get: n[o]
                    })
        }
    };
    e.g = function() {
        if ("object" == typeof globalThis) return globalThis;
        try {
            return this || new Function("return this")()
        } catch (e) {
            if ("object" == typeof window) return window
        }
    }(), e.o = (e, t) => Object.prototype.hasOwnProperty.call(e, t), e.r = e => {
        Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
            value: "Module"
        }), Object.defineProperty(e, "__esModule", {
            value: !0
        })
    };
    let t = {};

    function n(e) {
        this.content = e
    }
    e.r(t), e.d(t, {
        Editor: () => Zy
    }), n.prototype = {
        constructor: n,
        find: function(e) {
            for (var t = 0; t < this.content.length; t += 2)
                if (this.content[t] === e) return t;
            return -1
        },
        get: function(e) {
            var t = this.find(e);
            return -1 == t ? void 0 : this.content[t + 1]
        },
        update: function(e, t, r) {
            var o = r && r != e ? this.remove(r) : this,
                i = o.find(e),
                s = o.content.slice();
            return -1 == i ? s.push(r || e, t) : (s[i + 1] = t, r && (s[i] = r)), new n(s)
        },
        remove: function(e) {
            var t = this.find(e);
            if (-1 == t) return this;
            var r = this.content.slice();
            return r.splice(t, 2), new n(r)
        },
        addToStart: function(e, t) {
            return new n([e, t].concat(this.remove(e).content))
        },
        addToEnd: function(e, t) {
            var r = this.remove(e).content.slice();
            return r.push(e, t), new n(r)
        },
        addBefore: function(e, t, r) {
            var o = this.remove(t),
                i = o.content.slice(),
                s = o.find(e);
            return i.splice(-1 == s ? i.length : s, 0, t, r), new n(i)
        },
        forEach: function(e) {
            for (var t = 0; t < this.content.length; t += 2) e(this.content[t], this.content[t + 1])
        },
        prepend: function(e) {
            return (e = n.from(e)).size ? new n(e.content.concat(this.subtract(e).content)) : this
        },
        append: function(e) {
            return (e = n.from(e)).size ? new n(this.subtract(e).content.concat(e.content)) : this
        },
        subtract: function(e) {
            var t = this;
            e = n.from(e);
            for (var r = 0; r < e.content.length; r += 2) t = t.remove(e.content[r]);
            return t
        },
        toObject: function() {
            var e = {};
            return this.forEach(function(t, n) {
                e[t] = n
            }), e
        },
        get size() {
            return this.content.length >> 1
        }
    }, n.from = function(e) {
        if (e instanceof n) return e;
        var t = [];
        if (e)
            for (var r in e) t.push(r, e[r]);
        return new n(t)
    };
    const r = n;

    function o(e, t, n) {
        for (let r = 0;; r++) {
            if (r == e.childCount || r == t.childCount) return e.childCount == t.childCount ? null : n;
            let i = e.child(r),
                l = t.child(r);
            if (i != l) {
                if (!i.sameMarkup(l)) return n;
                if (i.isText && i.text != l.text) {
                    let e = i.text,
                        t = l.text,
                        r = 0;
                    for (; e[r] == t[r]; r++) n++;
                    return r && r < e.length && r < t.length && a(e.charCodeAt(r - 1)) && s(e.charCodeAt(r)) && n--, n
                }
                if (i.content.size || l.content.size) {
                    let e = o(i.content, l.content, n + 1);
                    if (null != e) return e
                }
                n += i.nodeSize
            } else n += i.nodeSize
        }
    }

    function i(e, t, n, r) {
        for (let o = e.childCount, l = t.childCount;;) {
            if (0 == o || 0 == l) return o == l ? null : {
                a: n,
                b: r
            };
            let c = e.child(--o),
                u = t.child(--l),
                d = c.nodeSize;
            if (c != u) {
                if (!c.sameMarkup(u)) return {
                    a: n,
                    b: r
                };
                if (c.isText && c.text != u.text) {
                    let e = c.text,
                        t = u.text,
                        o = e.length,
                        i = t.length;
                    for (; o > 0 && i > 0 && e[o - 1] == t[i - 1];) o--, i--, n--, r--;
                    return o && i && o < e.length && a(e.charCodeAt(o - 1)) && s(e.charCodeAt(o)) && (n++, r++), {
                        a: n,
                        b: r
                    }
                }
                if (c.content.size || u.content.size) {
                    let e = i(c.content, u.content, n - 1, r - 1);
                    if (e) return e
                }
                n -= d, r -= d
            } else n -= d, r -= d
        }
    }

    function s(e) {
        return e >= 56320 && e < 57344
    }

    function a(e) {
        return e >= 55296 && e < 56320
    }
    class l {
        constructor(e, t) {
            if (this.content = e, this.size = t || 0, null == t)
                for (let t = 0; t < e.length; t++) this.size += e[t].nodeSize
        }
        nodesBetween(e, t, n, r = 0, o) {
            for (let i = 0, s = 0; s < t; i++) {
                let a = this.content[i],
                    l = s + a.nodeSize;
                if (l > e && !1 !== n(a, r + s, o || null, i) && a.content.size) {
                    let o = s + 1;
                    a.nodesBetween(Math.max(0, e - o), Math.min(a.content.size, t - o), n, r + o)
                }
                s = l
            }
        }
        descendants(e) {
            this.nodesBetween(0, this.size, e)
        }
        textBetween(e, t, n, r) {
            let o = "",
                i = !0;
            return this.nodesBetween(e, t, (s, a) => {
                let l = s.isText ? s.text.slice(Math.max(e, a) - a, t - a) : s.isLeaf ? r ? "function" == typeof r ? r(s) : r : s.type.spec.leafText ? s.type.spec.leafText(s) : "" : "";
                s.isBlock && (s.isLeaf && l || s.isTextblock) && n && (i ? i = !1 : o += n), o += l
            }, 0), o
        }
        append(e) {
            if (!e.size) return this;
            if (!this.size) return e;
            let t = this.lastChild,
                n = e.firstChild,
                r = this.content.slice(),
                o = 0;
            for (t.isText && t.sameMarkup(n) && (r[r.length - 1] = t.withText(t.text + n.text), o = 1); o < e.content.length; o++) r.push(e.content[o]);
            return new l(r, this.size + e.size)
        }
        cut(e, t = this.size) {
            if (0 == e && t == this.size) return this;
            let n = [],
                r = 0;
            if (t > e)
                for (let o = 0, i = 0; i < t; o++) {
                    let s = this.content[o],
                        a = i + s.nodeSize;
                    a > e && ((i < e || a > t) && (s = s.isText ? s.cut(Math.max(0, e - i), Math.min(s.text.length, t - i)) : s.cut(Math.max(0, e - i - 1), Math.min(s.content.size, t - i - 1))), n.push(s), r += s.nodeSize), i = a
                }
            return new l(n, r)
        }
        cutByIndex(e, t) {
            return e == t ? l.empty : 0 == e && t == this.content.length ? this : new l(this.content.slice(e, t))
        }
        replaceChild(e, t) {
            let n = this.content[e];
            if (n == t) return this;
            let r = this.content.slice(),
                o = this.size + t.nodeSize - n.nodeSize;
            return r[e] = t, new l(r, o)
        }
        addToStart(e) {
            return new l([e].concat(this.content), this.size + e.nodeSize)
        }
        addToEnd(e) {
            return new l(this.content.concat(e), this.size + e.nodeSize)
        }
        eq(e) {
            if (this.content.length != e.content.length) return !1;
            for (let t = 0; t < this.content.length; t++)
                if (!this.content[t].eq(e.content[t])) return !1;
            return !0
        }
        get firstChild() {
            return this.content.length ? this.content[0] : null
        }
        get lastChild() {
            return this.content.length ? this.content[this.content.length - 1] : null
        }
        get childCount() {
            return this.content.length
        }
        child(e) {
            let t = this.content[e];
            if (!t) throw new RangeError("Index " + e + " out of range for " + this);
            return t
        }
        maybeChild(e) {
            return this.content[e] || null
        }
        forEach(e) {
            for (let t = 0, n = 0; t < this.content.length; t++) {
                let r = this.content[t];
                e(r, n, t), n += r.nodeSize
            }
        }
        findDiffStart(e, t = 0) {
            return o(this, e, t)
        }
        findDiffEnd(e, t = this.size, n = e.size) {
            return i(this, e, t, n)
        }
        findIndex(e) {
            if (0 == e) return u(0, e);
            if (e == this.size) return u(this.content.length, e);
            if (e > this.size || e < 0) throw new RangeError(`Position ${e} outside of fragment (${this})`);
            for (let t = 0, n = 0;; t++) {
                let r = n + this.child(t).nodeSize;
                if (r >= e) return r == e ? u(t + 1, r) : u(t, n);
                n = r
            }
        }
        toString() {
            return "<" + this.toStringInner() + ">"
        }
        toStringInner() {
            return this.content.join(", ")
        }
        toJSON() {
            return this.content.length ? this.content.map(e => e.toJSON()) : null
        }
        static fromJSON(e, t) {
            if (!t) return l.empty;
            if (!Array.isArray(t)) throw new RangeError("Invalid input for Fragment.fromJSON");
            return l.fromArray(t.map(e.nodeFromJSON))
        }
        static fromArray(e) {
            if (!e.length) return l.empty;
            let t, n = 0;
            for (let r = 0; r < e.length; r++) {
                let o = e[r];
                n += o.nodeSize, r && o.isText && e[r - 1].sameMarkup(o) ? (t || (t = e.slice(0, r)), t[t.length - 1] = o.withText(t[t.length - 1].text + o.text)) : t && t.push(o)
            }
            return new l(t || e, n)
        }
        static from(e) {
            if (!e) return l.empty;
            if (e instanceof l) return e;
            if (Array.isArray(e)) return this.fromArray(e);
            if (e.attrs) return new l([e], e.nodeSize);
            throw new RangeError("Can not convert " + e + " to a Fragment" + (e.nodesBetween ? " (looks like multiple versions of prosemirror-model were loaded)" : ""))
        }
    }
    l.empty = new l([], 0);
    const c = {
        index: 0,
        offset: 0
    };

    function u(e, t) {
        return c.index = e, c.offset = t, c
    }

    function d(e, t) {
        if (e === t) return !0;
        if (!e || "object" != typeof e || !t || "object" != typeof t) return !1;
        let n = Array.isArray(e);
        if (Array.isArray(t) != n) return !1;
        if (n) {
            if (e.length != t.length) return !1;
            for (let n = 0; n < e.length; n++)
                if (!d(e[n], t[n])) return !1
        } else {
            for (let n in e)
                if (!(n in t) || !d(e[n], t[n])) return !1;
            for (let n in t)
                if (!(n in e)) return !1
        }
        return !0
    }
    class p {
        constructor(e, t) {
            this.type = e, this.attrs = t
        }
        addToSet(e) {
            let t, n = !1;
            for (let r = 0; r < e.length; r++) {
                let o = e[r];
                if (this.eq(o)) return e;
                if (this.type.excludes(o.type)) t || (t = e.slice(0, r));
                else {
                    if (o.type.excludes(this.type)) return e;
                    !n && o.type.rank > this.type.rank && (t || (t = e.slice(0, r)), t.push(this), n = !0), t && t.push(o)
                }
            }
            return t || (t = e.slice()), n || t.push(this), t
        }
        removeFromSet(e) {
            for (let t = 0; t < e.length; t++)
                if (this.eq(e[t])) return e.slice(0, t).concat(e.slice(t + 1));
            return e
        }
        isInSet(e) {
            for (let t = 0; t < e.length; t++)
                if (this.eq(e[t])) return !0;
            return !1
        }
        eq(e) {
            return this == e || this.type == e.type && d(this.attrs, e.attrs)
        }
        toJSON() {
            let e = {
                type: this.type.name
            };
            for (let t in this.attrs) {
                e.attrs = this.attrs;
                break
            }
            return e
        }
        static fromJSON(e, t) {
            if (!t) throw new RangeError("Invalid input for Mark.fromJSON");
            let n = e.marks[t.type];
            if (!n) throw new RangeError(`There is no mark type ${t.type} in this schema`);
            let r = n.create(t.attrs);
            return n.checkAttrs(r.attrs), r
        }
        static sameSet(e, t) {
            if (e == t) return !0;
            if (e.length != t.length) return !1;
            for (let n = 0; n < e.length; n++)
                if (!e[n].eq(t[n])) return !1;
            return !0
        }
        static setFrom(e) {
            if (!e || Array.isArray(e) && 0 == e.length) return p.none;
            if (e instanceof p) return [e];
            let t = e.slice();
            return t.sort((e, t) => e.type.rank - t.type.rank), t
        }
    }
    p.none = [];
    class h extends Error {}
    class f {
        constructor(e, t, n) {
            this.content = e, this.openStart = t, this.openEnd = n
        }
        get size() {
            return this.content.size - this.openStart - this.openEnd
        }
        insertAt(e, t) {
            let n = g(this.content, e + this.openStart, t, this.openStart + 1, this.openEnd + 1);
            return n && new f(n, this.openStart, this.openEnd)
        }
        removeBetween(e, t) {
            return new f(m(this.content, e + this.openStart, t + this.openStart), this.openStart, this.openEnd)
        }
        eq(e) {
            return this.content.eq(e.content) && this.openStart == e.openStart && this.openEnd == e.openEnd
        }
        toString() {
            return this.content + "(" + this.openStart + "," + this.openEnd + ")"
        }
        toJSON() {
            if (!this.content.size) return null;
            let e = {
                content: this.content.toJSON()
            };
            return this.openStart > 0 && (e.openStart = this.openStart), this.openEnd > 0 && (e.openEnd = this.openEnd), e
        }
        static fromJSON(e, t) {
            if (!t) return f.empty;
            let n = t.openStart || 0,
                r = t.openEnd || 0;
            if ("number" != typeof n || "number" != typeof r) throw new RangeError("Invalid input for Slice.fromJSON");
            return new f(l.fromJSON(e, t.content), n, r)
        }
        static maxOpen(e, t = !0) {
            let n = 0,
                r = 0;
            for (let r = e.firstChild; r && !r.isLeaf && (t || !r.type.spec.isolating); r = r.firstChild) n++;
            for (let n = e.lastChild; n && !n.isLeaf && (t || !n.type.spec.isolating); n = n.lastChild) r++;
            return new f(e, n, r)
        }
    }

    function m(e, t, n) {
        let {
            index: r,
            offset: o
        } = e.findIndex(t), i = e.maybeChild(r), {
            index: s,
            offset: a
        } = e.findIndex(n);
        if (o == t || i.isText) {
            if (a != n && !e.child(s).isText) throw new RangeError("Removing non-flat range");
            return e.cut(0, t).append(e.cut(n))
        }
        if (r != s) throw new RangeError("Removing non-flat range");
        return e.replaceChild(r, i.copy(m(i.content, t - o - 1, n - o - 1)))
    }

    function g(e, t, n, r, o, i) {
        let {
            index: s,
            offset: a
        } = e.findIndex(t), l = e.maybeChild(s);
        if (a == t || l.isText) return i && r <= 0 && o <= 0 && !i.canReplace(s, s, n) ? null : e.cut(0, t).append(n).append(e.cut(t));
        let c = g(l.content, t - a - 1, n, 0 == s ? r - 1 : 0, s == e.childCount - 1 ? o - 1 : 0, l);
        return c && e.replaceChild(s, l.copy(c))
    }

    function v(e, t, n) {
        if (n.openStart > e.depth) throw new h("Inserted content deeper than insertion position");
        if (e.depth - n.openStart != t.depth - n.openEnd) throw new h("Inconsistent open depths");
        return y(e, t, n, 0)
    }

    function y(e, t, n, r) {
        let o = e.index(r),
            i = e.node(r);
        if (o == t.index(r) && r < e.depth - n.openStart) {
            let s = y(e, t, n, r + 1);
            return i.copy(i.content.replaceChild(o, s))
        }
        if (n.content.size) {
            if (n.openStart || n.openEnd || e.depth != r || t.depth != r) {
                let {
                    start: o,
                    end: s
                } = function(e, t) {
                    let n = t.depth - e.openStart,
                        r = t.node(n).copy(e.content);
                    for (let e = n - 1; e >= 0; e--) r = t.node(e).copy(l.from(r));
                    return {
                        start: r.resolveNoCache(e.openStart + n),
                        end: r.resolveNoCache(r.content.size - e.openEnd - n)
                    }
                }(n, e);
                return C(i, T(e, o, s, t, r))
            } {
                let r = e.parent,
                    o = r.content;
                return C(r, o.cut(0, e.parentOffset).append(n.content).append(o.cut(t.parentOffset)))
            }
        }
        return C(i, M(e, t, r))
    }

    function b(e, t) {
        if (!t.type.compatibleContent(e.type)) throw new h("Cannot join " + t.type.name + " onto " + e.type.name)
    }

    function w(e, t, n) {
        let r = e.node(n);
        return b(r, t.node(n)), r
    }

    function k(e, t) {
        let n = t.length - 1;
        n >= 0 && e.isText && e.sameMarkup(t[n]) ? t[n] = e.withText(t[n].text + e.text) : t.push(e)
    }

    function x(e, t, n, r) {
        let o = (t || e).node(n),
            i = 0,
            s = t ? t.index(n) : o.childCount;
        e && (i = e.index(n), e.depth > n ? i++ : e.textOffset && (k(e.nodeAfter, r), i++));
        for (let e = i; e < s; e++) k(o.child(e), r);
        t && t.depth == n && t.textOffset && k(t.nodeBefore, r)
    }

    function C(e, t) {
        if (!e.type.validContent(t)) throw new h("Invalid content for node " + e.type.name);
        return e.copy(t)
    }

    function T(e, t, n, r, o) {
        let i = e.depth > o && w(e, t, o + 1),
            s = r.depth > o && w(n, r, o + 1),
            a = [];
        return x(null, e, o, a), i && s && t.index(o) == n.index(o) ? (b(i, s), k(C(i, T(e, t, n, r, o + 1)), a)) : (i && k(C(i, M(e, t, o + 1)), a), x(t, n, o, a), s && k(C(s, M(n, r, o + 1)), a)), x(r, null, o, a), new l(a)
    }

    function M(e, t, n) {
        let r = [];
        return x(null, e, n, r), e.depth > n && k(C(w(e, t, n + 1), M(e, t, n + 1)), r), x(t, null, n, r), new l(r)
    }
    f.empty = new f(l.empty, 0, 0);
    class S {
        constructor(e, t, n) {
            this.pos = e, this.path = t, this.parentOffset = n, this.depth = t.length / 3 - 1
        }
        resolveDepth(e) {
            return null == e ? this.depth : e < 0 ? this.depth + e : e
        }
        get parent() {
            return this.node(this.depth)
        }
        get doc() {
            return this.node(0)
        }
        node(e) {
            return this.path[3 * this.resolveDepth(e)]
        }
        index(e) {
            return this.path[3 * this.resolveDepth(e) + 1]
        }
        indexAfter(e) {
            return e = this.resolveDepth(e), this.index(e) + (e != this.depth || this.textOffset ? 1 : 0)
        }
        start(e) {
            return 0 == (e = this.resolveDepth(e)) ? 0 : this.path[3 * e - 1] + 1
        }
        end(e) {
            return e = this.resolveDepth(e), this.start(e) + this.node(e).content.size
        }
        before(e) {
            if (!(e = this.resolveDepth(e))) throw new RangeError("There is no position before the top-level node");
            return e == this.depth + 1 ? this.pos : this.path[3 * e - 1]
        }
        after(e) {
            if (!(e = this.resolveDepth(e))) throw new RangeError("There is no position after the top-level node");
            return e == this.depth + 1 ? this.pos : this.path[3 * e - 1] + this.path[3 * e].nodeSize
        }
        get textOffset() {
            return this.pos - this.path[this.path.length - 1]
        }
        get nodeAfter() {
            let e = this.parent,
                t = this.index(this.depth);
            if (t == e.childCount) return null;
            let n = this.pos - this.path[this.path.length - 1],
                r = e.child(t);
            return n ? e.child(t).cut(n) : r
        }
        get nodeBefore() {
            let e = this.index(this.depth),
                t = this.pos - this.path[this.path.length - 1];
            return t ? this.parent.child(e).cut(0, t) : 0 == e ? null : this.parent.child(e - 1)
        }
        posAtIndex(e, t) {
            t = this.resolveDepth(t);
            let n = this.path[3 * t],
                r = 0 == t ? 0 : this.path[3 * t - 1] + 1;
            for (let t = 0; t < e; t++) r += n.child(t).nodeSize;
            return r
        }
        marks() {
            let e = this.parent,
                t = this.index();
            if (0 == e.content.size) return p.none;
            if (this.textOffset) return e.child(t).marks;
            let n = e.maybeChild(t - 1),
                r = e.maybeChild(t);
            if (!n) {
                let e = n;
                n = r, r = e
            }
            let o = n.marks;
            for (var i = 0; i < o.length; i++) !1 !== o[i].type.spec.inclusive || r && o[i].isInSet(r.marks) || (o = o[i--].removeFromSet(o));
            return o
        }
        marksAcross(e) {
            let t = this.parent.maybeChild(this.index());
            if (!t || !t.isInline) return null;
            let n = t.marks,
                r = e.parent.maybeChild(e.index());
            for (var o = 0; o < n.length; o++) !1 !== n[o].type.spec.inclusive || r && n[o].isInSet(r.marks) || (n = n[o--].removeFromSet(n));
            return n
        }
        sharedDepth(e) {
            for (let t = this.depth; t > 0; t--)
                if (this.start(t) <= e && this.end(t) >= e) return t;
            return 0
        }
        blockRange(e = this, t) {
            if (e.pos < this.pos) return e.blockRange(this);
            for (let n = this.depth - (this.parent.inlineContent || this.pos == e.pos ? 1 : 0); n >= 0; n--)
                if (e.pos <= this.end(n) && (!t || t(this.node(n)))) return new D(this, e, n);
            return null
        }
        sameParent(e) {
            return this.pos - this.parentOffset == e.pos - e.parentOffset
        }
        max(e) {
            return e.pos > this.pos ? e : this
        }
        min(e) {
            return e.pos < this.pos ? e : this
        }
        toString() {
            let e = "";
            for (let t = 1; t <= this.depth; t++) e += (e ? "/" : "") + this.node(t).type.name + "_" + this.index(t - 1);
            return e + ":" + this.parentOffset
        }
        static resolve(e, t) {
            if (!(t >= 0 && t <= e.content.size)) throw new RangeError("Position " + t + " out of range");
            let n = [],
                r = 0,
                o = t;
            for (let t = e;;) {
                let {
                    index: e,
                    offset: i
                } = t.content.findIndex(o), s = o - i;
                if (n.push(t, e, r + i), !s) break;
                if (t = t.child(e), t.isText) break;
                o = s - 1, r += i + 1
            }
            return new S(t, n, o)
        }
        static resolveCached(e, t) {
            let n = O.get(e);
            if (n)
                for (let e = 0; e < n.elts.length; e++) {
                    let r = n.elts[e];
                    if (r.pos == t) return r
                } else O.set(e, n = new E);
            let r = n.elts[n.i] = S.resolve(e, t);
            return n.i = (n.i + 1) % N, r
        }
    }
    class E {
        constructor() {
            this.elts = [], this.i = 0
        }
    }
    const N = 12,
        O = new WeakMap;
    class D {
        constructor(e, t, n) {
            this.$from = e, this.$to = t, this.depth = n
        }
        get start() {
            return this.$from.before(this.depth + 1)
        }
        get end() {
            return this.$to.after(this.depth + 1)
        }
        get parent() {
            return this.$from.node(this.depth)
        }
        get startIndex() {
            return this.$from.index(this.depth)
        }
        get endIndex() {
            return this.$to.indexAfter(this.depth)
        }
    }
    const A = Object.create(null);
    class L {
        constructor(e, t, n, r = p.none) {
            this.type = e, this.attrs = t, this.marks = r, this.content = n || l.empty
        }
        get children() {
            return this.content.content
        }
        get nodeSize() {
            return this.isLeaf ? 1 : 2 + this.content.size
        }
        get childCount() {
            return this.content.childCount
        }
        child(e) {
            return this.content.child(e)
        }
        maybeChild(e) {
            return this.content.maybeChild(e)
        }
        forEach(e) {
            this.content.forEach(e)
        }
        nodesBetween(e, t, n, r = 0) {
            this.content.nodesBetween(e, t, n, r, this)
        }
        descendants(e) {
            this.nodesBetween(0, this.content.size, e)
        }
        get textContent() {
            return this.isLeaf && this.type.spec.leafText ? this.type.spec.leafText(this) : this.textBetween(0, this.content.size, "")
        }
        textBetween(e, t, n, r) {
            return this.content.textBetween(e, t, n, r)
        }
        get firstChild() {
            return this.content.firstChild
        }
        get lastChild() {
            return this.content.lastChild
        }
        eq(e) {
            return this == e || this.sameMarkup(e) && this.content.eq(e.content)
        }
        sameMarkup(e) {
            return this.hasMarkup(e.type, e.attrs, e.marks)
        }
        hasMarkup(e, t, n) {
            return this.type == e && d(this.attrs, t || e.defaultAttrs || A) && p.sameSet(this.marks, n || p.none)
        }
        copy(e = null) {
            return e == this.content ? this : new L(this.type, this.attrs, e, this.marks)
        }
        mark(e) {
            return e == this.marks ? this : new L(this.type, this.attrs, this.content, e)
        }
        cut(e, t = this.content.size) {
            return 0 == e && t == this.content.size ? this : this.copy(this.content.cut(e, t))
        }
        slice(e, t = this.content.size, n = !1) {
            if (e == t) return f.empty;
            let r = this.resolve(e),
                o = this.resolve(t),
                i = n ? 0 : r.sharedDepth(t),
                s = r.start(i),
                a = r.node(i).content.cut(r.pos - s, o.pos - s);
            return new f(a, r.depth - i, o.depth - i)
        }
        replace(e, t, n) {
            return v(this.resolve(e), this.resolve(t), n)
        }
        nodeAt(e) {
            for (let t = this;;) {
                let {
                    index: n,
                    offset: r
                } = t.content.findIndex(e);
                if (t = t.maybeChild(n), !t) return null;
                if (r == e || t.isText) return t;
                e -= r + 1
            }
        }
        childAfter(e) {
            let {
                index: t,
                offset: n
            } = this.content.findIndex(e);
            return {
                node: this.content.maybeChild(t),
                index: t,
                offset: n
            }
        }
        childBefore(e) {
            if (0 == e) return {
                node: null,
                index: 0,
                offset: 0
            };
            let {
                index: t,
                offset: n
            } = this.content.findIndex(e);
            if (n < e) return {
                node: this.content.child(t),
                index: t,
                offset: n
            };
            let r = this.content.child(t - 1);
            return {
                node: r,
                index: t - 1,
                offset: n - r.nodeSize
            }
        }
        resolve(e) {
            return S.resolveCached(this, e)
        }
        resolveNoCache(e) {
            return S.resolve(this, e)
        }
        rangeHasMark(e, t, n) {
            let r = !1;
            return t > e && this.nodesBetween(e, t, e => (n.isInSet(e.marks) && (r = !0), !r)), r
        }
        get isBlock() {
            return this.type.isBlock
        }
        get isTextblock() {
            return this.type.isTextblock
        }
        get inlineContent() {
            return this.type.inlineContent
        }
        get isInline() {
            return this.type.isInline
        }
        get isText() {
            return this.type.isText
        }
        get isLeaf() {
            return this.type.isLeaf
        }
        get isAtom() {
            return this.type.isAtom
        }
        toString() {
            if (this.type.spec.toDebugString) return this.type.spec.toDebugString(this);
            let e = this.type.name;
            return this.content.size && (e += "(" + this.content.toStringInner() + ")"), R(this.marks, e)
        }
        contentMatchAt(e) {
            let t = this.type.contentMatch.matchFragment(this.content, 0, e);
            if (!t) throw new Error("Called contentMatchAt on a node with invalid content");
            return t
        }
        canReplace(e, t, n = l.empty, r = 0, o = n.childCount) {
            let i = this.contentMatchAt(e).matchFragment(n, r, o),
                s = i && i.matchFragment(this.content, t);
            if (!s || !s.validEnd) return !1;
            for (let e = r; e < o; e++)
                if (!this.type.allowsMarks(n.child(e).marks)) return !1;
            return !0
        }
        canReplaceWith(e, t, n, r) {
            if (r && !this.type.allowsMarks(r)) return !1;
            let o = this.contentMatchAt(e).matchType(n),
                i = o && o.matchFragment(this.content, t);
            return !!i && i.validEnd
        }
        canAppend(e) {
            return e.content.size ? this.canReplace(this.childCount, this.childCount, e.content) : this.type.compatibleContent(e.type)
        }
        check() {
            this.type.checkContent(this.content), this.type.checkAttrs(this.attrs);
            let e = p.none;
            for (let t = 0; t < this.marks.length; t++) {
                let n = this.marks[t];
                n.type.checkAttrs(n.attrs), e = n.addToSet(e)
            }
            if (!p.sameSet(e, this.marks)) throw new RangeError(`Invalid collection of marks for node ${this.type.name}: ${this.marks.map(e=>e.type.name)}`);
            this.content.forEach(e => e.check())
        }
        toJSON() {
            let e = {
                type: this.type.name
            };
            for (let t in this.attrs) {
                e.attrs = this.attrs;
                break
            }
            return this.content.size && (e.content = this.content.toJSON()), this.marks.length && (e.marks = this.marks.map(e => e.toJSON())), e
        }
        static fromJSON(e, t) {
            if (!t) throw new RangeError("Invalid input for Node.fromJSON");
            let n;
            if (t.marks) {
                if (!Array.isArray(t.marks)) throw new RangeError("Invalid mark data for Node.fromJSON");
                n = t.marks.map(e.markFromJSON)
            }
            if ("text" == t.type) {
                if ("string" != typeof t.text) throw new RangeError("Invalid text node in JSON");
                return e.text(t.text, n)
            }
            let r = l.fromJSON(e, t.content),
                o = e.nodeType(t.type).create(t.attrs, r, n);
            return o.type.checkAttrs(o.attrs), o
        }
    }
    L.prototype.text = void 0;
    class I extends L {
        constructor(e, t, n, r) {
            if (super(e, t, null, r), !n) throw new RangeError("Empty text nodes are not allowed");
            this.text = n
        }
        toString() {
            return this.type.spec.toDebugString ? this.type.spec.toDebugString(this) : R(this.marks, JSON.stringify(this.text))
        }
        get textContent() {
            return this.text
        }
        textBetween(e, t) {
            return this.text.slice(e, t)
        }
        get nodeSize() {
            return this.text.length
        }
        mark(e) {
            return e == this.marks ? this : new I(this.type, this.attrs, this.text, e)
        }
        withText(e) {
            return e == this.text ? this : new I(this.type, this.attrs, e, this.marks)
        }
        cut(e = 0, t = this.text.length) {
            return 0 == e && t == this.text.length ? this : this.withText(this.text.slice(e, t))
        }
        eq(e) {
            return this.sameMarkup(e) && this.text == e.text
        }
        toJSON() {
            let e = super.toJSON();
            return e.text = this.text, e
        }
    }

    function R(e, t) {
        for (let n = e.length - 1; n >= 0; n--) t = e[n].type.name + "(" + t + ")";
        return t
    }
    class P {
        constructor(e) {
            this.validEnd = e, this.next = [], this.wrapCache = []
        }
        static parse(e, t) {
            let n = new B(e, t);
            if (null == n.next) return P.empty;
            let r = F(n);
            n.next && n.err("Unexpected trailing text");
            let o = function(e) {
                let t = Object.create(null);
                return function n(r) {
                    let o = [];
                    r.forEach(t => {
                        e[t].forEach(({
                            term: t,
                            to: n
                        }) => {
                            if (!t) return;
                            let r;
                            for (let e = 0; e < o.length; e++) o[e][0] == t && (r = o[e][1]);
                            $(e, n).forEach(e => {
                                r || o.push([t, r = []]), -1 == r.indexOf(e) && r.push(e)
                            })
                        })
                    });
                    let i = t[r.join(",")] = new P(r.indexOf(e.length - 1) > -1);
                    for (let e = 0; e < o.length; e++) {
                        let r = o[e][1].sort(j);
                        i.next.push({
                            type: o[e][0],
                            next: t[r.join(",")] || n(r)
                        })
                    }
                    return i
                }($(e, 0))
            }(function(e) {
                let t = [
                    []
                ];
                return o(function e(t, i) {
                    if ("choice" == t.type) return t.exprs.reduce((t, n) => t.concat(e(n, i)), []);
                    if ("seq" != t.type) {
                        if ("star" == t.type) {
                            let s = n();
                            return r(i, s), o(e(t.expr, s), s), [r(s)]
                        }
                        if ("plus" == t.type) {
                            let s = n();
                            return o(e(t.expr, i), s), o(e(t.expr, s), s), [r(s)]
                        }
                        if ("opt" == t.type) return [r(i)].concat(e(t.expr, i));
                        if ("range" == t.type) {
                            let s = i;
                            for (let r = 0; r < t.min; r++) {
                                let r = n();
                                o(e(t.expr, s), r), s = r
                            }
                            if (-1 == t.max) o(e(t.expr, s), s);
                            else
                                for (let i = t.min; i < t.max; i++) {
                                    let i = n();
                                    r(s, i), o(e(t.expr, s), i), s = i
                                }
                            return [r(s)]
                        }
                        if ("name" == t.type) return [r(i, void 0, t.value)];
                        throw new Error("Unknown expr type")
                    }
                    for (let r = 0;; r++) {
                        let s = e(t.exprs[r], i);
                        if (r == t.exprs.length - 1) return s;
                        o(s, i = n())
                    }
                }(e, 0), n()), t;

                function n() {
                    return t.push([]) - 1
                }

                function r(e, n, r) {
                    let o = {
                        term: r,
                        to: n
                    };
                    return t[e].push(o), o
                }

                function o(e, t) {
                    e.forEach(e => e.to = t)
                }
            }(r));
            return function(e, t) {
                for (let n = 0, r = [e]; n < r.length; n++) {
                    let e = r[n],
                        o = !e.validEnd,
                        i = [];
                    for (let t = 0; t < e.next.length; t++) {
                        let {
                            type: n,
                            next: s
                        } = e.next[t];
                        i.push(n.name), !o || n.isText || n.hasRequiredAttrs() || (o = !1), -1 == r.indexOf(s) && r.push(s)
                    }
                    o && t.err("Only non-generatable nodes (" + i.join(", ") + ") in a required position (see https://prosemirror.net/docs/guide/#generatable)")
                }
            }(o, n), o
        }
        matchType(e) {
            for (let t = 0; t < this.next.length; t++)
                if (this.next[t].type == e) return this.next[t].next;
            return null
        }
        matchFragment(e, t = 0, n = e.childCount) {
            let r = this;
            for (let o = t; r && o < n; o++) r = r.matchType(e.child(o).type);
            return r
        }
        get inlineContent() {
            return 0 != this.next.length && this.next[0].type.isInline
        }
        get defaultType() {
            for (let e = 0; e < this.next.length; e++) {
                let {
                    type: t
                } = this.next[e];
                if (!t.isText && !t.hasRequiredAttrs()) return t
            }
            return null
        }
        compatible(e) {
            for (let t = 0; t < this.next.length; t++)
                for (let n = 0; n < e.next.length; n++)
                    if (this.next[t].type == e.next[n].type) return !0;
            return !1
        }
        fillBefore(e, t = !1, n = 0) {
            let r = [this];
            return function o(i, s) {
                let a = i.matchFragment(e, n);
                if (a && (!t || a.validEnd)) return l.from(s.map(e => e.createAndFill()));
                for (let e = 0; e < i.next.length; e++) {
                    let {
                        type: t,
                        next: n
                    } = i.next[e];
                    if (!t.isText && !t.hasRequiredAttrs() && -1 == r.indexOf(n)) {
                        r.push(n);
                        let e = o(n, s.concat(t));
                        if (e) return e
                    }
                }
                return null
            }(this, [])
        }
        findWrapping(e) {
            for (let t = 0; t < this.wrapCache.length; t += 2)
                if (this.wrapCache[t] == e) return this.wrapCache[t + 1];
            let t = this.computeWrapping(e);
            return this.wrapCache.push(e, t), t
        }
        computeWrapping(e) {
            let t = Object.create(null),
                n = [{
                    match: this,
                    type: null,
                    via: null
                }];
            for (; n.length;) {
                let r = n.shift(),
                    o = r.match;
                if (o.matchType(e)) {
                    let e = [];
                    for (let t = r; t.type; t = t.via) e.push(t.type);
                    return e.reverse()
                }
                for (let e = 0; e < o.next.length; e++) {
                    let {
                        type: i,
                        next: s
                    } = o.next[e];
                    i.isLeaf || i.hasRequiredAttrs() || i.name in t || r.type && !s.validEnd || (n.push({
                        match: i.contentMatch,
                        type: i,
                        via: r
                    }), t[i.name] = !0)
                }
            }
            return null
        }
        get edgeCount() {
            return this.next.length
        }
        edge(e) {
            if (e >= this.next.length) throw new RangeError(`There's no ${e}th edge in this content match`);
            return this.next[e]
        }
        toString() {
            let e = [];
            return function t(n) {
                e.push(n);
                for (let r = 0; r < n.next.length; r++) - 1 == e.indexOf(n.next[r].next) && t(n.next[r].next)
            }(this), e.map((t, n) => {
                let r = n + (t.validEnd ? "*" : " ") + " ";
                for (let n = 0; n < t.next.length; n++) r += (n ? ", " : "") + t.next[n].type.name + "->" + e.indexOf(t.next[n].next);
                return r
            }).join("\n")
        }
    }
    P.empty = new P(!0);
    class B {
        constructor(e, t) {
            this.string = e, this.nodeTypes = t, this.inline = null, this.pos = 0, this.tokens = e.split(/\s*(?=\b|\W|$)/), "" == this.tokens[this.tokens.length - 1] && this.tokens.pop(), "" == this.tokens[0] && this.tokens.shift()
        }
        get next() {
            return this.tokens[this.pos]
        }
        eat(e) {
            return this.next == e && (this.pos++ || !0)
        }
        err(e) {
            throw new SyntaxError(e + " (in content expression '" + this.string + "')")
        }
    }

    function F(e) {
        let t = [];
        do {
            t.push(H(e))
        } while (e.eat("|"));
        return 1 == t.length ? t[0] : {
            type: "choice",
            exprs: t
        }
    }

    function H(e) {
        let t = [];
        do {
            t.push(z(e))
        } while (e.next && ")" != e.next && "|" != e.next);
        return 1 == t.length ? t[0] : {
            type: "seq",
            exprs: t
        }
    }

    function z(e) {
        let t = function(e) {
            if (e.eat("(")) {
                let t = F(e);
                return e.eat(")") || e.err("Missing closing paren"), t
            }
            if (!/\W/.test(e.next)) {
                let t = function(e, t) {
                    let n = e.nodeTypes,
                        r = n[t];
                    if (r) return [r];
                    let o = [];
                    for (let e in n) {
                        let r = n[e];
                        r.isInGroup(t) && o.push(r)
                    }
                    return 0 == o.length && e.err("No node type or group '" + t + "' found"), o
                }(e, e.next).map(t => (null == e.inline ? e.inline = t.isInline : e.inline != t.isInline && e.err("Mixing inline and block content"), {
                    type: "name",
                    value: t
                }));
                return e.pos++, 1 == t.length ? t[0] : {
                    type: "choice",
                    exprs: t
                }
            }
            e.err("Unexpected token '" + e.next + "'")
        }(e);
        for (;;)
            if (e.eat("+")) t = {
                type: "plus",
                expr: t
            };
            else if (e.eat("*")) t = {
            type: "star",
            expr: t
        };
        else if (e.eat("?")) t = {
            type: "opt",
            expr: t
        };
        else {
            if (!e.eat("{")) break;
            t = V(e, t)
        }
        return t
    }

    function q(e) {
        /\D/.test(e.next) && e.err("Expected number, got '" + e.next + "'");
        let t = Number(e.next);
        return e.pos++, t
    }

    function V(e, t) {
        let n = q(e),
            r = n;
        return e.eat(",") && (r = "}" != e.next ? q(e) : -1), e.eat("}") || e.err("Unclosed braced range"), {
            type: "range",
            min: n,
            max: r,
            expr: t
        }
    }

    function j(e, t) {
        return t - e
    }

    function $(e, t) {
        let n = [];
        return function t(r) {
            let o = e[r];
            if (1 == o.length && !o[0].term) return t(o[0].to);
            n.push(r);
            for (let e = 0; e < o.length; e++) {
                let {
                    term: r,
                    to: i
                } = o[e];
                r || -1 != n.indexOf(i) || t(i)
            }
        }(t), n.sort(j)
    }

    function _(e) {
        let t = Object.create(null);
        for (let n in e) {
            let r = e[n];
            if (!r.hasDefault) return null;
            t[n] = r.default
        }
        return t
    }

    function U(e, t) {
        let n = Object.create(null);
        for (let r in e) {
            let o = t && t[r];
            if (void 0 === o) {
                let t = e[r];
                if (!t.hasDefault) throw new RangeError("No value supplied for attribute " + r);
                o = t.default
            }
            n[r] = o
        }
        return n
    }

    function W(e, t, n, r) {
        for (let o in t)
            if (!(o in e)) throw new RangeError(`Unsupported attribute ${o} for ${n} of type ${r}`);
        for (let n in e) e[n].validate && e[n].validate(t[n])
    }

    function J(e, t) {
        let n = Object.create(null);
        if (t)
            for (let r in t) n[r] = new G(e, r, t[r]);
        return n
    }
    class K {
        constructor(e, t, n) {
            this.name = e, this.schema = t, this.spec = n, this.markSet = null, this.groups = n.group ? n.group.split(" ") : [], this.attrs = J(e, n.attrs), this.defaultAttrs = _(this.attrs), this.contentMatch = null, this.inlineContent = null, this.isBlock = !(n.inline || "text" == e), this.isText = "text" == e
        }
        get isInline() {
            return !this.isBlock
        }
        get isTextblock() {
            return this.isBlock && this.inlineContent
        }
        get isLeaf() {
            return this.contentMatch == P.empty
        }
        get isAtom() {
            return this.isLeaf || !!this.spec.atom
        }
        isInGroup(e) {
            return this.groups.indexOf(e) > -1
        }
        get whitespace() {
            return this.spec.whitespace || (this.spec.code ? "pre" : "normal")
        }
        hasRequiredAttrs() {
            for (let e in this.attrs)
                if (this.attrs[e].isRequired) return !0;
            return !1
        }
        compatibleContent(e) {
            return this == e || this.contentMatch.compatible(e.contentMatch)
        }
        computeAttrs(e) {
            return !e && this.defaultAttrs ? this.defaultAttrs : U(this.attrs, e)
        }
        create(e = null, t, n) {
            if (this.isText) throw new Error("NodeType.create can't construct text nodes");
            return new L(this, this.computeAttrs(e), l.from(t), p.setFrom(n))
        }
        createChecked(e = null, t, n) {
            return t = l.from(t), this.checkContent(t), new L(this, this.computeAttrs(e), t, p.setFrom(n))
        }
        createAndFill(e = null, t, n) {
            if (e = this.computeAttrs(e), (t = l.from(t)).size) {
                let e = this.contentMatch.fillBefore(t);
                if (!e) return null;
                t = e.append(t)
            }
            let r = this.contentMatch.matchFragment(t),
                o = r && r.fillBefore(l.empty, !0);
            return o ? new L(this, e, t.append(o), p.setFrom(n)) : null
        }
        validContent(e) {
            let t = this.contentMatch.matchFragment(e);
            if (!t || !t.validEnd) return !1;
            for (let t = 0; t < e.childCount; t++)
                if (!this.allowsMarks(e.child(t).marks)) return !1;
            return !0
        }
        checkContent(e) {
            if (!this.validContent(e)) throw new RangeError(`Invalid content for node ${this.name}: ${e.toString().slice(0,50)}`)
        }
        checkAttrs(e) {
            W(this.attrs, e, "node", this.name)
        }
        allowsMarkType(e) {
            return null == this.markSet || this.markSet.indexOf(e) > -1
        }
        allowsMarks(e) {
            if (null == this.markSet) return !0;
            for (let t = 0; t < e.length; t++)
                if (!this.allowsMarkType(e[t].type)) return !1;
            return !0
        }
        allowedMarks(e) {
            if (null == this.markSet) return e;
            let t;
            for (let n = 0; n < e.length; n++) this.allowsMarkType(e[n].type) ? t && t.push(e[n]) : t || (t = e.slice(0, n));
            return t ? t.length ? t : p.none : e
        }
        static compile(e, t) {
            let n = Object.create(null);
            e.forEach((e, r) => n[e] = new K(e, t, r));
            let r = t.spec.topNode || "doc";
            if (!n[r]) throw new RangeError("Schema is missing its top node type ('" + r + "')");
            if (!n.text) throw new RangeError("Every schema needs a 'text' type");
            for (let e in n.text.attrs) throw new RangeError("The text node type should not have attributes");
            return n
        }
    }
    class G {
        constructor(e, t, n) {
            this.hasDefault = Object.prototype.hasOwnProperty.call(n, "default"), this.default = n.default, this.validate = "string" == typeof n.validate ? function(e, t, n) {
                let r = n.split("|");
                return n => {
                    let o = null === n ? "null" : typeof n;
                    if (r.indexOf(o) < 0) throw new RangeError(`Expected value of type ${r} for attribute ${t} on type ${e}, got ${o}`)
                }
            }(e, t, n.validate) : n.validate
        }
        get isRequired() {
            return !this.hasDefault
        }
    }
    class X {
        constructor(e, t, n, r) {
            this.name = e, this.rank = t, this.schema = n, this.spec = r, this.attrs = J(e, r.attrs), this.excluded = null;
            let o = _(this.attrs);
            this.instance = o ? new p(this, o) : null
        }
        create(e = null) {
            return !e && this.instance ? this.instance : new p(this, U(this.attrs, e))
        }
        static compile(e, t) {
            let n = Object.create(null),
                r = 0;
            return e.forEach((e, o) => n[e] = new X(e, r++, t, o)), n
        }
        removeFromSet(e) {
            for (var t = 0; t < e.length; t++) e[t].type == this && (e = e.slice(0, t).concat(e.slice(t + 1)), t--);
            return e
        }
        isInSet(e) {
            for (let t = 0; t < e.length; t++)
                if (e[t].type == this) return e[t]
        }
        checkAttrs(e) {
            W(this.attrs, e, "mark", this.name)
        }
        excludes(e) {
            return this.excluded.indexOf(e) > -1
        }
    }
    class Z {
        constructor(e) {
            this.linebreakReplacement = null, this.cached = Object.create(null);
            let t = this.spec = {};
            for (let n in e) t[n] = e[n];
            t.nodes = r.from(e.nodes), t.marks = r.from(e.marks || {}), this.nodes = K.compile(this.spec.nodes, this), this.marks = X.compile(this.spec.marks, this);
            let n = Object.create(null);
            for (let e in this.nodes) {
                if (e in this.marks) throw new RangeError(e + " can not be both a node and a mark");
                let t = this.nodes[e],
                    r = t.spec.content || "",
                    o = t.spec.marks;
                if (t.contentMatch = n[r] || (n[r] = P.parse(r, this.nodes)), t.inlineContent = t.contentMatch.inlineContent, t.spec.linebreakReplacement) {
                    if (this.linebreakReplacement) throw new RangeError("Multiple linebreak nodes defined");
                    if (!t.isInline || !t.isLeaf) throw new RangeError("Linebreak replacement nodes must be inline leaf nodes");
                    this.linebreakReplacement = t
                }
                t.markSet = "_" == o ? null : o ? Q(this, o.split(" ")) : "" != o && t.inlineContent ? null : []
            }
            for (let e in this.marks) {
                let t = this.marks[e],
                    n = t.spec.excludes;
                t.excluded = null == n ? [t] : "" == n ? [] : Q(this, n.split(" "))
            }
            this.nodeFromJSON = e => L.fromJSON(this, e), this.markFromJSON = e => p.fromJSON(this, e), this.topNodeType = this.nodes[this.spec.topNode || "doc"], this.cached.wrappings = Object.create(null)
        }
        node(e, t = null, n, r) {
            if ("string" == typeof e) e = this.nodeType(e);
            else {
                if (!(e instanceof K)) throw new RangeError("Invalid node type: " + e);
                if (e.schema != this) throw new RangeError("Node type from different schema used (" + e.name + ")")
            }
            return e.createChecked(t, n, r)
        }
        text(e, t) {
            let n = this.nodes.text;
            return new I(n, n.defaultAttrs, e, p.setFrom(t))
        }
        mark(e, t) {
            return "string" == typeof e && (e = this.marks[e]), e.create(t)
        }
        nodeType(e) {
            let t = this.nodes[e];
            if (!t) throw new RangeError("Unknown node type: " + e);
            return t
        }
    }

    function Q(e, t) {
        let n = [];
        for (let r = 0; r < t.length; r++) {
            let o = t[r],
                i = e.marks[o],
                s = i;
            if (i) n.push(i);
            else
                for (let t in e.marks) {
                    let r = e.marks[t];
                    ("_" == o || r.spec.group && r.spec.group.split(" ").indexOf(o) > -1) && n.push(s = r)
                }
            if (!s) throw new SyntaxError("Unknown mark type: '" + t[r] + "'")
        }
        return n
    }
    class Y {
        constructor(e, t) {
            this.schema = e, this.rules = t, this.tags = [], this.styles = [];
            let n = this.matchedStyles = [];
            t.forEach(e => {
                if (function(e) {
                        return null != e.tag
                    }(e)) this.tags.push(e);
                else if (function(e) {
                        return null != e.style
                    }(e)) {
                    let t = /[^=]*/.exec(e.style)[0];
                    n.indexOf(t) < 0 && n.push(t), this.styles.push(e)
                }
            }), this.normalizeLists = !this.tags.some(t => {
                if (!/^(ul|ol)\b/.test(t.tag) || !t.node) return !1;
                let n = e.nodes[t.node];
                return n.contentMatch.matchType(n)
            })
        }
        parse(e, t = {}) {
            let n = new ie(this, t, !1);
            return n.addAll(e, p.none, t.from, t.to), n.finish()
        }
        parseSlice(e, t = {}) {
            let n = new ie(this, t, !0);
            return n.addAll(e, p.none, t.from, t.to), f.maxOpen(n.finish())
        }
        matchTag(e, t, n) {
            for (let r = n ? this.tags.indexOf(n) + 1 : 0; r < this.tags.length; r++) {
                let n = this.tags[r];
                if (se(e, n.tag) && (void 0 === n.namespace || e.namespaceURI == n.namespace) && (!n.context || t.matchesContext(n.context))) {
                    if (n.getAttrs) {
                        let t = n.getAttrs(e);
                        if (!1 === t) continue;
                        n.attrs = t || void 0
                    }
                    return n
                }
            }
        }
        matchStyle(e, t, n, r) {
            for (let o = r ? this.styles.indexOf(r) + 1 : 0; o < this.styles.length; o++) {
                let r = this.styles[o],
                    i = r.style;
                if (!(0 != i.indexOf(e) || r.context && !n.matchesContext(r.context) || i.length > e.length && (61 != i.charCodeAt(e.length) || i.slice(e.length + 1) != t))) {
                    if (r.getAttrs) {
                        let e = r.getAttrs(t);
                        if (!1 === e) continue;
                        r.attrs = e || void 0
                    }
                    return r
                }
            }
        }
        static schemaRules(e) {
            let t = [];

            function n(e) {
                let n = null == e.priority ? 50 : e.priority,
                    r = 0;
                for (; r < t.length; r++) {
                    let e = t[r];
                    if ((null == e.priority ? 50 : e.priority) < n) break
                }
                t.splice(r, 0, e)
            }
            for (let t in e.marks) {
                let r = e.marks[t].spec.parseDOM;
                r && r.forEach(e => {
                    n(e = ae(e)), e.mark || e.ignore || e.clearMark || (e.mark = t)
                })
            }
            for (let t in e.nodes) {
                let r = e.nodes[t].spec.parseDOM;
                r && r.forEach(e => {
                    n(e = ae(e)), e.node || e.ignore || e.mark || (e.node = t)
                })
            }
            return t
        }
        static fromSchema(e) {
            return e.cached.domParser || (e.cached.domParser = new Y(e, Y.schemaRules(e)))
        }
    }
    const ee = {
            address: !0,
            article: !0,
            aside: !0,
            blockquote: !0,
            body: !0,
            canvas: !0,
            dd: !0,
            div: !0,
            dl: !0,
            fieldset: !0,
            figcaption: !0,
            figure: !0,
            footer: !0,
            form: !0,
            h1: !0,
            h2: !0,
            h3: !0,
            h4: !0,
            h5: !0,
            h6: !0,
            header: !0,
            hgroup: !0,
            hr: !0,
            li: !0,
            noscript: !0,
            ol: !0,
            output: !0,
            p: !0,
            pre: !0,
            section: !0,
            table: !0,
            tfoot: !0,
            ul: !0
        },
        te = {
            head: !0,
            noscript: !0,
            object: !0,
            script: !0,
            style: !0,
            title: !0
        },
        ne = {
            ol: !0,
            ul: !0
        };

    function re(e, t, n) {
        return null != t ? (t ? 1 : 0) | ("full" === t ? 2 : 0) : e && "pre" == e.whitespace ? 3 : -5 & n
    }
    class oe {
        constructor(e, t, n, r, o, i) {
            this.type = e, this.attrs = t, this.marks = n, this.solid = r, this.options = i, this.content = [], this.activeMarks = p.none, this.match = o || (4 & i ? null : e.contentMatch)
        }
        findWrapping(e) {
            if (!this.match) {
                if (!this.type) return [];
                let t = this.type.contentMatch.fillBefore(l.from(e));
                if (!t) {
                    let t, n = this.type.contentMatch;
                    return (t = n.findWrapping(e.type)) ? (this.match = n, t) : null
                }
                this.match = this.type.contentMatch.matchFragment(t)
            }
            return this.match.findWrapping(e.type)
        }
        finish(e) {
            if (!(1 & this.options)) {
                let e, t = this.content[this.content.length - 1];
                if (t && t.isText && (e = /[ \t\r\n\u000c]+$/.exec(t.text))) {
                    let n = t;
                    t.text.length == e[0].length ? this.content.pop() : this.content[this.content.length - 1] = n.withText(n.text.slice(0, n.text.length - e[0].length))
                }
            }
            let t = l.from(this.content);
            return !e && this.match && (t = t.append(this.match.fillBefore(l.empty, !0))), this.type ? this.type.create(this.attrs, t, this.marks) : t
        }
        inlineContext(e) {
            return this.type ? this.type.inlineContent : this.content.length ? this.content[0].isInline : e.parentNode && !ee.hasOwnProperty(e.parentNode.nodeName.toLowerCase())
        }
    }
    class ie {
        constructor(e, t, n) {
            this.parser = e, this.options = t, this.isOpen = n, this.open = 0, this.localPreserveWS = !1;
            let r, o = t.topNode,
                i = re(null, t.preserveWhitespace, 0) | (n ? 4 : 0);
            r = o ? new oe(o.type, o.attrs, p.none, !0, t.topMatch || o.type.contentMatch, i) : new oe(n ? null : e.schema.topNodeType, null, p.none, !0, null, i), this.nodes = [r], this.find = t.findPositions, this.needsBlock = !1
        }
        get top() {
            return this.nodes[this.open]
        }
        addDOM(e, t) {
            3 == e.nodeType ? this.addTextNode(e, t) : 1 == e.nodeType && this.addElement(e, t)
        }
        addTextNode(e, t) {
            let n = e.nodeValue,
                r = this.top,
                o = 2 & r.options ? "full" : this.localPreserveWS || (1 & r.options) > 0,
                {
                    schema: i
                } = this.parser;
            if ("full" === o || r.inlineContext(e) || /[^ \t\r\n\u000c]/.test(n)) {
                if (o)
                    if ("full" === o) n = n.replace(/\r\n?/g, "\n");
                    else if (i.linebreakReplacement && /[\r\n]/.test(n) && this.top.findWrapping(i.linebreakReplacement.create())) {
                    let e = n.split(/\r?\n|\r/);
                    for (let n = 0; n < e.length; n++) n && this.insertNode(i.linebreakReplacement.create(), t, !0), e[n] && this.insertNode(i.text(e[n]), t, !/\S/.test(e[n]));
                    n = ""
                } else n = n.replace(/\r?\n|\r/g, " ");
                else if (n = n.replace(/[ \t\r\n\u000c]+/g, " "), /^[ \t\r\n\u000c]/.test(n) && this.open == this.nodes.length - 1) {
                    let t = r.content[r.content.length - 1],
                        o = e.previousSibling;
                    (!t || o && "BR" == o.nodeName || t.isText && /[ \t\r\n\u000c]$/.test(t.text)) && (n = n.slice(1))
                }
                n && this.insertNode(i.text(n), t, !/\S/.test(n)), this.findInText(e)
            } else this.findInside(e)
        }
        addElement(e, t, n) {
            let r = this.localPreserveWS,
                o = this.top;
            ("PRE" == e.tagName || /pre/.test(e.style && e.style.whiteSpace)) && (this.localPreserveWS = !0);
            let i, s = e.nodeName.toLowerCase();
            ne.hasOwnProperty(s) && this.parser.normalizeLists && function(e) {
                for (let t = e.firstChild, n = null; t; t = t.nextSibling) {
                    let e = 1 == t.nodeType ? t.nodeName.toLowerCase() : null;
                    e && ne.hasOwnProperty(e) && n ? (n.appendChild(t), t = n) : "li" == e ? n = t : e && (n = null)
                }
            }(e);
            let a = this.options.ruleFromNode && this.options.ruleFromNode(e) || (i = this.parser.matchTag(e, this, n));
            e: if (a ? a.ignore : te.hasOwnProperty(s)) this.findInside(e), this.ignoreFallback(e, t);
                else if (!a || a.skip || a.closeParent) {
                a && a.closeParent ? this.open = Math.max(0, this.open - 1) : a && a.skip.nodeType && (e = a.skip);
                let n, r = this.needsBlock;
                if (ee.hasOwnProperty(s)) o.content.length && o.content[0].isInline && this.open && (this.open--, o = this.top), n = !0, o.type || (this.needsBlock = !0);
                else if (!e.firstChild) {
                    this.leafFallback(e, t);
                    break e
                }
                let i = a && a.skip ? t : this.readStyles(e, t);
                i && this.addAll(e, i), n && this.sync(o), this.needsBlock = r
            } else {
                let n = this.readStyles(e, t);
                n && this.addElementByRule(e, a, n, !1 === a.consuming ? i : void 0)
            }
            this.localPreserveWS = r
        }
        leafFallback(e, t) {
            "BR" == e.nodeName && this.top.type && this.top.type.inlineContent && this.addTextNode(e.ownerDocument.createTextNode("\n"), t)
        }
        ignoreFallback(e, t) {
            "BR" != e.nodeName || this.top.type && this.top.type.inlineContent || this.findPlace(this.parser.schema.text("-"), t, !0)
        }
        readStyles(e, t) {
            let n = e.style;
            if (n && n.length)
                for (let e = 0; e < this.parser.matchedStyles.length; e++) {
                    let r = this.parser.matchedStyles[e],
                        o = n.getPropertyValue(r);
                    if (o)
                        for (let e;;) {
                            let n = this.parser.matchStyle(r, o, this, e);
                            if (!n) break;
                            if (n.ignore) return null;
                            if (t = n.clearMark ? t.filter(e => !n.clearMark(e)) : t.concat(this.parser.schema.marks[n.mark].create(n.attrs)), !1 !== n.consuming) break;
                            e = n
                        }
                }
            return t
        }
        addElementByRule(e, t, n, r) {
            let o, i;
            if (t.node)
                if (i = this.parser.schema.nodes[t.node], i.isLeaf) this.insertNode(i.create(t.attrs), n, "BR" == e.nodeName) || this.leafFallback(e, n);
                else {
                    let e = this.enter(i, t.attrs || null, n, t.preserveWhitespace);
                    e && (o = !0, n = e)
                }
            else {
                let e = this.parser.schema.marks[t.mark];
                n = n.concat(e.create(t.attrs))
            }
            let s = this.top;
            if (i && i.isLeaf) this.findInside(e);
            else if (r) this.addElement(e, n, r);
            else if (t.getContent) this.findInside(e), t.getContent(e, this.parser.schema).forEach(e => this.insertNode(e, n, !1));
            else {
                let r = e;
                "string" == typeof t.contentElement ? r = e.querySelector(t.contentElement) : "function" == typeof t.contentElement ? r = t.contentElement(e) : t.contentElement && (r = t.contentElement), this.findAround(e, r, !0), this.addAll(r, n), this.findAround(e, r, !1)
            }
            o && this.sync(s) && this.open--
        }
        addAll(e, t, n, r) {
            let o = n || 0;
            for (let i = n ? e.childNodes[n] : e.firstChild, s = null == r ? null : e.childNodes[r]; i != s; i = i.nextSibling, ++o) this.findAtPoint(e, o), this.addDOM(i, t);
            this.findAtPoint(e, o)
        }
        findPlace(e, t, n) {
            let r, o;
            for (let t = this.open, i = 0; t >= 0; t--) {
                let s = this.nodes[t],
                    a = s.findWrapping(e);
                if (a && (!r || r.length > a.length + i) && (r = a, o = s, !a.length)) break;
                if (s.solid) {
                    if (n) break;
                    i += 2
                }
            }
            if (!r) return null;
            this.sync(o);
            for (let e = 0; e < r.length; e++) t = this.enterInner(r[e], null, t, !1);
            return t
        }
        insertNode(e, t, n) {
            if (e.isInline && this.needsBlock && !this.top.type) {
                let e = this.textblockFromContext();
                e && (t = this.enterInner(e, null, t))
            }
            let r = this.findPlace(e, t, n);
            if (r) {
                this.closeExtra();
                let t = this.top;
                t.match && (t.match = t.match.matchType(e.type));
                let n = p.none;
                for (let o of r.concat(e.marks))(t.type ? t.type.allowsMarkType(o.type) : le(o.type, e.type)) && (n = o.addToSet(n));
                return t.content.push(e.mark(n)), !0
            }
            return !1
        }
        enter(e, t, n, r) {
            let o = this.findPlace(e.create(t), n, !1);
            return o && (o = this.enterInner(e, t, n, !0, r)), o
        }
        enterInner(e, t, n, r = !1, o) {
            this.closeExtra();
            let i = this.top;
            i.match = i.match && i.match.matchType(e);
            let s = re(e, o, i.options);
            4 & i.options && 0 == i.content.length && (s |= 4);
            let a = p.none;
            return n = n.filter(t => !(i.type ? i.type.allowsMarkType(t.type) : le(t.type, e)) || (a = t.addToSet(a), !1)), this.nodes.push(new oe(e, t, a, r, null, s)), this.open++, n
        }
        closeExtra(e = !1) {
            let t = this.nodes.length - 1;
            if (t > this.open) {
                for (; t > this.open; t--) this.nodes[t - 1].content.push(this.nodes[t].finish(e));
                this.nodes.length = this.open + 1
            }
        }
        finish() {
            return this.open = 0, this.closeExtra(this.isOpen), this.nodes[0].finish(!(!this.isOpen && !this.options.topOpen))
        }
        sync(e) {
            for (let t = this.open; t >= 0; t--) {
                if (this.nodes[t] == e) return this.open = t, !0;
                this.localPreserveWS && (this.nodes[t].options |= 1)
            }
            return !1
        }
        get currentPos() {
            this.closeExtra();
            let e = 0;
            for (let t = this.open; t >= 0; t--) {
                let n = this.nodes[t].content;
                for (let t = n.length - 1; t >= 0; t--) e += n[t].nodeSize;
                t && e++
            }
            return e
        }
        findAtPoint(e, t) {
            if (this.find)
                for (let n = 0; n < this.find.length; n++) this.find[n].node == e && this.find[n].offset == t && (this.find[n].pos = this.currentPos)
        }
        findInside(e) {
            if (this.find)
                for (let t = 0; t < this.find.length; t++) null == this.find[t].pos && 1 == e.nodeType && e.contains(this.find[t].node) && (this.find[t].pos = this.currentPos)
        }
        findAround(e, t, n) {
            if (e != t && this.find)
                for (let r = 0; r < this.find.length; r++) null == this.find[r].pos && 1 == e.nodeType && e.contains(this.find[r].node) && t.compareDocumentPosition(this.find[r].node) & (n ? 2 : 4) && (this.find[r].pos = this.currentPos)
        }
        findInText(e) {
            if (this.find)
                for (let t = 0; t < this.find.length; t++) this.find[t].node == e && (this.find[t].pos = this.currentPos - (e.nodeValue.length - this.find[t].offset))
        }
        matchesContext(e) {
            if (e.indexOf("|") > -1) return e.split(/\s*\|\s*/).some(this.matchesContext, this);
            let t = e.split("/"),
                n = this.options.context,
                r = !(this.isOpen || n && n.parent.type != this.nodes[0].type),
                o = -(n ? n.depth + 1 : 0) + (r ? 0 : 1),
                i = (e, s) => {
                    for (; e >= 0; e--) {
                        let a = t[e];
                        if ("" == a) {
                            if (e == t.length - 1 || 0 == e) continue;
                            for (; s >= o; s--)
                                if (i(e - 1, s)) return !0;
                            return !1
                        } {
                            let e = s > 0 || 0 == s && r ? this.nodes[s].type : n && s >= o ? n.node(s - o).type : null;
                            if (!e || e.name != a && !e.isInGroup(a)) return !1;
                            s--
                        }
                    }
                    return !0
                };
            return i(t.length - 1, this.open)
        }
        textblockFromContext() {
            let e = this.options.context;
            if (e)
                for (let t = e.depth; t >= 0; t--) {
                    let n = e.node(t).contentMatchAt(e.indexAfter(t)).defaultType;
                    if (n && n.isTextblock && n.defaultAttrs) return n
                }
            for (let e in this.parser.schema.nodes) {
                let t = this.parser.schema.nodes[e];
                if (t.isTextblock && t.defaultAttrs) return t
            }
        }
    }

    function se(e, t) {
        return (e.matches || e.msMatchesSelector || e.webkitMatchesSelector || e.mozMatchesSelector).call(e, t)
    }

    function ae(e) {
        let t = {};
        for (let n in e) t[n] = e[n];
        return t
    }

    function le(e, t) {
        let n = t.schema.nodes;
        for (let r in n) {
            let o = n[r];
            if (!o.allowsMarkType(e)) continue;
            let i = [],
                s = e => {
                    i.push(e);
                    for (let n = 0; n < e.edgeCount; n++) {
                        let {
                            type: r,
                            next: o
                        } = e.edge(n);
                        if (r == t) return !0;
                        if (i.indexOf(o) < 0 && s(o)) return !0
                    }
                };
            if (s(o.contentMatch)) return !0
        }
    }
    class ce {
        constructor(e, t) {
            this.nodes = e, this.marks = t
        }
        serializeFragment(e, t = {}, n) {
            n || (n = de(t).createDocumentFragment());
            let r = n,
                o = [];
            return e.forEach(e => {
                if (o.length || e.marks.length) {
                    let n = 0,
                        i = 0;
                    for (; n < o.length && i < e.marks.length;) {
                        let t = e.marks[i];
                        if (this.marks[t.type.name]) {
                            if (!t.eq(o[n][0]) || !1 === t.type.spec.spanning) break;
                            n++, i++
                        } else i++
                    }
                    for (; n < o.length;) r = o.pop()[1];
                    for (; i < e.marks.length;) {
                        let n = e.marks[i++],
                            s = this.serializeMark(n, e.isInline, t);
                        s && (o.push([n, r]), r.appendChild(s.dom), r = s.contentDOM || s.dom)
                    }
                }
                r.appendChild(this.serializeNodeInner(e, t))
            }), n
        }
        serializeNodeInner(e, t) {
            if (e.isText) return de(t).createTextNode(e.text);
            let {
                dom: n,
                contentDOM: r
            } = he(de(t), this.nodes[e.type.name](e), null, e.attrs);
            if (r) {
                if (e.isLeaf) throw new RangeError("Content hole not allowed in a leaf node spec");
                this.serializeFragment(e.content, t, r)
            }
            return n
        }
        serializeNode(e, t = {}) {
            let n = this.serializeNodeInner(e, t);
            for (let r = e.marks.length - 1; r >= 0; r--) {
                let o = this.serializeMark(e.marks[r], e.isInline, t);
                o && ((o.contentDOM || o.dom).appendChild(n), n = o.dom)
            }
            return n
        }
        serializeMark(e, t, n = {}) {
            let r = this.marks[e.type.name];
            return r && he(de(n), r(e, t), null, e.attrs)
        }
        static renderSpec(e, t, n = null, r) {
            return "string" == typeof t ? {
                dom: e.createTextNode(t)
            } : he(e, t, n, r)
        }
        static fromSchema(e) {
            return e.cached.domSerializer || (e.cached.domSerializer = new ce(this.nodesFromSchema(e), this.marksFromSchema(e)))
        }
        static nodesFromSchema(e) {
            let t = ue(e.nodes);
            return t.text || (t.text = e => e.text), t
        }
        static marksFromSchema(e) {
            return ue(e.marks)
        }
    }

    function ue(e) {
        let t = {};
        for (let n in e) {
            let r = e[n].spec.toDOM;
            r && (t[n] = r)
        }
        return t
    }

    function de(e) {
        return e.document || window.document
    }
    const pe = new WeakMap;

    function he(e, t, n, r) {
        if (1 == t.nodeType) return {
            dom: t
        };
        if (t.dom && 1 == t.dom.nodeType) return t;
        let o, i = t[0];
        if ("string" != typeof i) throw new RangeError("Invalid array passed to renderSpec");
        if (r && (o = function(e) {
                let t = pe.get(e);
                return void 0 === t && pe.set(e, t = function(e) {
                    let t = null;
                    return function e(n) {
                        if (n && "object" == typeof n)
                            if (Array.isArray(n))
                                if ("string" == typeof n[0]) t || (t = []), t.push(n);
                                else
                                    for (let t = 0; t < n.length; t++) e(n[t]);
                        else
                            for (let t in n) e(n[t])
                    }(e), t
                }(e)), t
            }(r)) && o.indexOf(t) > -1) throw new RangeError("Using an array from an attribute object as a DOM spec. This may be an attempted cross site scripting attack.");
        let s, a = i.indexOf(" ");
        a > 0 && (n = i.slice(0, a), i = i.slice(a + 1));
        let l = n ? e.createElementNS(n, i) : e.createElement(i),
            c = t[1],
            u = 1;
        if (c && "object" == typeof c && null == c.nodeType && !Array.isArray(c)) {
            u = 2;
            for (let e in c)
                if (null != c[e]) {
                    let t = e.indexOf(" ");
                    t > 0 ? l.setAttributeNS(e.slice(0, t), e.slice(t + 1), c[e]) : "style" == e && l.style ? l.style.cssText = c[e] : l.setAttribute(e, c[e])
                }
        }
        for (let o = u; o < t.length; o++) {
            let i = t[o];
            if (0 === i) {
                if (o < t.length - 1 || o > u) throw new RangeError("Content hole must be the only child of its parent node");
                return {
                    dom: l,
                    contentDOM: l
                }
            }
            if ("string" == typeof i) l.appendChild(e.createTextNode(i));
            else {
                let {
                    dom: t,
                    contentDOM: o
                } = he(e, i, n, r);
                if (l.appendChild(t), o) {
                    if (s) throw new RangeError("Multiple content holes");
                    s = o
                }
            }
        }
        return {
            dom: l,
            contentDOM: s
        }
    }
    const fe = Math.pow(2, 16);

    function me(e, t) {
        return e + t * fe
    }

    function ge(e) {
        return 65535 & e
    }
    class ve {
        constructor(e, t, n) {
            this.pos = e, this.delInfo = t, this.recover = n
        }
        get deleted() {
            return (8 & this.delInfo) > 0
        }
        get deletedBefore() {
            return (5 & this.delInfo) > 0
        }
        get deletedAfter() {
            return (6 & this.delInfo) > 0
        }
        get deletedAcross() {
            return (4 & this.delInfo) > 0
        }
    }
    class ye {
        constructor(e, t = !1) {
            if (this.ranges = e, this.inverted = t, !e.length && ye.empty) return ye.empty
        }
        recover(e) {
            let t = 0,
                n = ge(e);
            if (!this.inverted)
                for (let e = 0; e < n; e++) t += this.ranges[3 * e + 2] - this.ranges[3 * e + 1];
            return this.ranges[3 * n] + t + function(e) {
                return (e - (65535 & e)) / fe
            }(e)
        }
        mapResult(e, t = 1) {
            return this._map(e, t, !1)
        }
        map(e, t = 1) {
            return this._map(e, t, !0)
        }
        _map(e, t, n) {
            let r = 0,
                o = this.inverted ? 2 : 1,
                i = this.inverted ? 1 : 2;
            for (let s = 0; s < this.ranges.length; s += 3) {
                let a = this.ranges[s] - (this.inverted ? r : 0);
                if (a > e) break;
                let l = this.ranges[s + o],
                    c = this.ranges[s + i],
                    u = a + l;
                if (e <= u) {
                    let o = a + r + ((l ? e == a ? -1 : e == u ? 1 : t : t) < 0 ? 0 : c);
                    if (n) return o;
                    let i = e == (t < 0 ? a : u) ? null : me(s / 3, e - a),
                        d = e == a ? 2 : e == u ? 1 : 4;
                    return (t < 0 ? e != a : e != u) && (d |= 8), new ve(o, d, i)
                }
                r += c - l
            }
            return n ? e + r : new ve(e + r, 0, null)
        }
        touches(e, t) {
            let n = 0,
                r = ge(t),
                o = this.inverted ? 2 : 1,
                i = this.inverted ? 1 : 2;
            for (let t = 0; t < this.ranges.length; t += 3) {
                let s = this.ranges[t] - (this.inverted ? n : 0);
                if (s > e) break;
                let a = this.ranges[t + o];
                if (e <= s + a && t == 3 * r) return !0;
                n += this.ranges[t + i] - a
            }
            return !1
        }
        forEach(e) {
            let t = this.inverted ? 2 : 1,
                n = this.inverted ? 1 : 2;
            for (let r = 0, o = 0; r < this.ranges.length; r += 3) {
                let i = this.ranges[r],
                    s = i - (this.inverted ? o : 0),
                    a = i + (this.inverted ? 0 : o),
                    l = this.ranges[r + t],
                    c = this.ranges[r + n];
                e(s, s + l, a, a + c), o += c - l
            }
        }
        invert() {
            return new ye(this.ranges, !this.inverted)
        }
        toString() {
            return (this.inverted ? "-" : "") + JSON.stringify(this.ranges)
        }
        static offset(e) {
            return 0 == e ? ye.empty : new ye(e < 0 ? [0, -e, 0] : [0, 0, e])
        }
    }
    ye.empty = new ye([]);
    class be {
        constructor(e, t, n = 0, r = (e ? e.length : 0)) {
            this.mirror = t, this.from = n, this.to = r, this._maps = e || [], this.ownData = !(e || t)
        }
        get maps() {
            return this._maps
        }
        slice(e = 0, t = this.maps.length) {
            return new be(this._maps, this.mirror, e, t)
        }
        appendMap(e, t) {
            this.ownData || (this._maps = this._maps.slice(), this.mirror = this.mirror && this.mirror.slice(), this.ownData = !0), this.to = this._maps.push(e), null != t && this.setMirror(this._maps.length - 1, t)
        }
        appendMapping(e) {
            for (let t = 0, n = this._maps.length; t < e._maps.length; t++) {
                let r = e.getMirror(t);
                this.appendMap(e._maps[t], null != r && r < t ? n + r : void 0)
            }
        }
        getMirror(e) {
            if (this.mirror)
                for (let t = 0; t < this.mirror.length; t++)
                    if (this.mirror[t] == e) return this.mirror[t + (t % 2 ? -1 : 1)]
        }
        setMirror(e, t) {
            this.mirror || (this.mirror = []), this.mirror.push(e, t)
        }
        appendMappingInverted(e) {
            for (let t = e.maps.length - 1, n = this._maps.length + e._maps.length; t >= 0; t--) {
                let r = e.getMirror(t);
                this.appendMap(e._maps[t].invert(), null != r && r > t ? n - r - 1 : void 0)
            }
        }
        invert() {
            let e = new be;
            return e.appendMappingInverted(this), e
        }
        map(e, t = 1) {
            if (this.mirror) return this._map(e, t, !0);
            for (let n = this.from; n < this.to; n++) e = this._maps[n].map(e, t);
            return e
        }
        mapResult(e, t = 1) {
            return this._map(e, t, !1)
        }
        _map(e, t, n) {
            let r = 0;
            for (let n = this.from; n < this.to; n++) {
                let o = this._maps[n].mapResult(e, t);
                if (null != o.recover) {
                    let t = this.getMirror(n);
                    if (null != t && t > n && t < this.to) {
                        n = t, e = this._maps[t].recover(o.recover);
                        continue
                    }
                }
                r |= o.delInfo, e = o.pos
            }
            return n ? e : new ve(e, r, null)
        }
    }
    const we = Object.create(null);
    class ke {
        getMap() {
            return ye.empty
        }
        merge(e) {
            return null
        }
        static fromJSON(e, t) {
            if (!t || !t.stepType) throw new RangeError("Invalid input for Step.fromJSON");
            let n = we[t.stepType];
            if (!n) throw new RangeError(`No step type ${t.stepType} defined`);
            return n.fromJSON(e, t)
        }
        static jsonID(e, t) {
            if (e in we) throw new RangeError("Duplicate use of step JSON ID " + e);
            return we[e] = t, t.prototype.jsonID = e, t
        }
    }
    class xe {
        constructor(e, t) {
            this.doc = e, this.failed = t
        }
        static ok(e) {
            return new xe(e, null)
        }
        static fail(e) {
            return new xe(null, e)
        }
        static fromReplace(e, t, n, r) {
            try {
                return xe.ok(e.replace(t, n, r))
            } catch (e) {
                if (e instanceof h) return xe.fail(e.message);
                throw e
            }
        }
    }

    function Ce(e, t, n) {
        let r = [];
        for (let o = 0; o < e.childCount; o++) {
            let i = e.child(o);
            i.content.size && (i = i.copy(Ce(i.content, t, i))), i.isInline && (i = t(i, n, o)), r.push(i)
        }
        return l.fromArray(r)
    }
    class Te extends ke {
        constructor(e, t, n) {
            super(), this.from = e, this.to = t, this.mark = n
        }
        apply(e) {
            let t = e.slice(this.from, this.to),
                n = e.resolve(this.from),
                r = n.node(n.sharedDepth(this.to)),
                o = new f(Ce(t.content, (e, t) => e.isAtom && t.type.allowsMarkType(this.mark.type) ? e.mark(this.mark.addToSet(e.marks)) : e, r), t.openStart, t.openEnd);
            return xe.fromReplace(e, this.from, this.to, o)
        }
        invert() {
            return new Me(this.from, this.to, this.mark)
        }
        map(e) {
            let t = e.mapResult(this.from, 1),
                n = e.mapResult(this.to, -1);
            return t.deleted && n.deleted || t.pos >= n.pos ? null : new Te(t.pos, n.pos, this.mark)
        }
        merge(e) {
            return e instanceof Te && e.mark.eq(this.mark) && this.from <= e.to && this.to >= e.from ? new Te(Math.min(this.from, e.from), Math.max(this.to, e.to), this.mark) : null
        }
        toJSON() {
            return {
                stepType: "addMark",
                mark: this.mark.toJSON(),
                from: this.from,
                to: this.to
            }
        }
        static fromJSON(e, t) {
            if ("number" != typeof t.from || "number" != typeof t.to) throw new RangeError("Invalid input for AddMarkStep.fromJSON");
            return new Te(t.from, t.to, e.markFromJSON(t.mark))
        }
    }
    ke.jsonID("addMark", Te);
    class Me extends ke {
        constructor(e, t, n) {
            super(), this.from = e, this.to = t, this.mark = n
        }
        apply(e) {
            let t = e.slice(this.from, this.to),
                n = new f(Ce(t.content, e => e.mark(this.mark.removeFromSet(e.marks)), e), t.openStart, t.openEnd);
            return xe.fromReplace(e, this.from, this.to, n)
        }
        invert() {
            return new Te(this.from, this.to, this.mark)
        }
        map(e) {
            let t = e.mapResult(this.from, 1),
                n = e.mapResult(this.to, -1);
            return t.deleted && n.deleted || t.pos >= n.pos ? null : new Me(t.pos, n.pos, this.mark)
        }
        merge(e) {
            return e instanceof Me && e.mark.eq(this.mark) && this.from <= e.to && this.to >= e.from ? new Me(Math.min(this.from, e.from), Math.max(this.to, e.to), this.mark) : null
        }
        toJSON() {
            return {
                stepType: "removeMark",
                mark: this.mark.toJSON(),
                from: this.from,
                to: this.to
            }
        }
        static fromJSON(e, t) {
            if ("number" != typeof t.from || "number" != typeof t.to) throw new RangeError("Invalid input for RemoveMarkStep.fromJSON");
            return new Me(t.from, t.to, e.markFromJSON(t.mark))
        }
    }
    ke.jsonID("removeMark", Me);
    class Se extends ke {
        constructor(e, t) {
            super(), this.pos = e, this.mark = t
        }
        apply(e) {
            let t = e.nodeAt(this.pos);
            if (!t) return xe.fail("No node at mark step's position");
            let n = t.type.create(t.attrs, null, this.mark.addToSet(t.marks));
            return xe.fromReplace(e, this.pos, this.pos + 1, new f(l.from(n), 0, t.isLeaf ? 0 : 1))
        }
        invert(e) {
            let t = e.nodeAt(this.pos);
            if (t) {
                let e = this.mark.addToSet(t.marks);
                if (e.length == t.marks.length) {
                    for (let n = 0; n < t.marks.length; n++)
                        if (!t.marks[n].isInSet(e)) return new Se(this.pos, t.marks[n]);
                    return new Se(this.pos, this.mark)
                }
            }
            return new Ee(this.pos, this.mark)
        }
        map(e) {
            let t = e.mapResult(this.pos, 1);
            return t.deletedAfter ? null : new Se(t.pos, this.mark)
        }
        toJSON() {
            return {
                stepType: "addNodeMark",
                pos: this.pos,
                mark: this.mark.toJSON()
            }
        }
        static fromJSON(e, t) {
            if ("number" != typeof t.pos) throw new RangeError("Invalid input for AddNodeMarkStep.fromJSON");
            return new Se(t.pos, e.markFromJSON(t.mark))
        }
    }
    ke.jsonID("addNodeMark", Se);
    class Ee extends ke {
        constructor(e, t) {
            super(), this.pos = e, this.mark = t
        }
        apply(e) {
            let t = e.nodeAt(this.pos);
            if (!t) return xe.fail("No node at mark step's position");
            let n = t.type.create(t.attrs, null, this.mark.removeFromSet(t.marks));
            return xe.fromReplace(e, this.pos, this.pos + 1, new f(l.from(n), 0, t.isLeaf ? 0 : 1))
        }
        invert(e) {
            let t = e.nodeAt(this.pos);
            return t && this.mark.isInSet(t.marks) ? new Se(this.pos, this.mark) : this
        }
        map(e) {
            let t = e.mapResult(this.pos, 1);
            return t.deletedAfter ? null : new Ee(t.pos, this.mark)
        }
        toJSON() {
            return {
                stepType: "removeNodeMark",
                pos: this.pos,
                mark: this.mark.toJSON()
            }
        }
        static fromJSON(e, t) {
            if ("number" != typeof t.pos) throw new RangeError("Invalid input for RemoveNodeMarkStep.fromJSON");
            return new Ee(t.pos, e.markFromJSON(t.mark))
        }
    }
    ke.jsonID("removeNodeMark", Ee);
    class Ne extends ke {
        constructor(e, t, n, r = !1) {
            super(), this.from = e, this.to = t, this.slice = n, this.structure = r
        }
        apply(e) {
            return this.structure && De(e, this.from, this.to) ? xe.fail("Structure replace would overwrite content") : xe.fromReplace(e, this.from, this.to, this.slice)
        }
        getMap() {
            return new ye([this.from, this.to - this.from, this.slice.size])
        }
        invert(e) {
            return new Ne(this.from, this.from + this.slice.size, e.slice(this.from, this.to))
        }
        map(e) {
            let t = e.mapResult(this.to, -1),
                n = this.from == this.to && Ne.MAP_BIAS < 0 ? t : e.mapResult(this.from, 1);
            return n.deletedAcross && t.deletedAcross ? null : new Ne(n.pos, Math.max(n.pos, t.pos), this.slice, this.structure)
        }
        merge(e) {
            if (!(e instanceof Ne) || e.structure || this.structure) return null;
            if (this.from + this.slice.size != e.from || this.slice.openEnd || e.slice.openStart) {
                if (e.to != this.from || this.slice.openStart || e.slice.openEnd) return null;
                {
                    let t = this.slice.size + e.slice.size == 0 ? f.empty : new f(e.slice.content.append(this.slice.content), e.slice.openStart, this.slice.openEnd);
                    return new Ne(e.from, this.to, t, this.structure)
                }
            } {
                let t = this.slice.size + e.slice.size == 0 ? f.empty : new f(this.slice.content.append(e.slice.content), this.slice.openStart, e.slice.openEnd);
                return new Ne(this.from, this.to + (e.to - e.from), t, this.structure)
            }
        }
        toJSON() {
            let e = {
                stepType: "replace",
                from: this.from,
                to: this.to
            };
            return this.slice.size && (e.slice = this.slice.toJSON()), this.structure && (e.structure = !0), e
        }
        static fromJSON(e, t) {
            if ("number" != typeof t.from || "number" != typeof t.to) throw new RangeError("Invalid input for ReplaceStep.fromJSON");
            return new Ne(t.from, t.to, f.fromJSON(e, t.slice), !!t.structure)
        }
    }
    Ne.MAP_BIAS = 1, ke.jsonID("replace", Ne);
    class Oe extends ke {
        constructor(e, t, n, r, o, i, s = !1) {
            super(), this.from = e, this.to = t, this.gapFrom = n, this.gapTo = r, this.slice = o, this.insert = i, this.structure = s
        }
        apply(e) {
            if (this.structure && (De(e, this.from, this.gapFrom) || De(e, this.gapTo, this.to))) return xe.fail("Structure gap-replace would overwrite content");
            let t = e.slice(this.gapFrom, this.gapTo);
            if (t.openStart || t.openEnd) return xe.fail("Gap is not a flat range");
            let n = this.slice.insertAt(this.insert, t.content);
            return n ? xe.fromReplace(e, this.from, this.to, n) : xe.fail("Content does not fit in gap")
        }
        getMap() {
            return new ye([this.from, this.gapFrom - this.from, this.insert, this.gapTo, this.to - this.gapTo, this.slice.size - this.insert])
        }
        invert(e) {
            let t = this.gapTo - this.gapFrom;
            return new Oe(this.from, this.from + this.slice.size + t, this.from + this.insert, this.from + this.insert + t, e.slice(this.from, this.to).removeBetween(this.gapFrom - this.from, this.gapTo - this.from), this.gapFrom - this.from, this.structure)
        }
        map(e) {
            let t = e.mapResult(this.from, 1),
                n = e.mapResult(this.to, -1),
                r = this.from == this.gapFrom ? t.pos : e.map(this.gapFrom, -1),
                o = this.to == this.gapTo ? n.pos : e.map(this.gapTo, 1);
            return t.deletedAcross && n.deletedAcross || r < t.pos || o > n.pos ? null : new Oe(t.pos, n.pos, r, o, this.slice, this.insert, this.structure)
        }
        toJSON() {
            let e = {
                stepType: "replaceAround",
                from: this.from,
                to: this.to,
                gapFrom: this.gapFrom,
                gapTo: this.gapTo,
                insert: this.insert
            };
            return this.slice.size && (e.slice = this.slice.toJSON()), this.structure && (e.structure = !0), e
        }
        static fromJSON(e, t) {
            if ("number" != typeof t.from || "number" != typeof t.to || "number" != typeof t.gapFrom || "number" != typeof t.gapTo || "number" != typeof t.insert) throw new RangeError("Invalid input for ReplaceAroundStep.fromJSON");
            return new Oe(t.from, t.to, t.gapFrom, t.gapTo, f.fromJSON(e, t.slice), t.insert, !!t.structure)
        }
    }

    function De(e, t, n) {
        let r = e.resolve(t),
            o = n - t,
            i = r.depth;
        for (; o > 0 && i > 0 && r.indexAfter(i) == r.node(i).childCount;) i--, o--;
        if (o > 0) {
            let e = r.node(i).maybeChild(r.indexAfter(i));
            for (; o > 0;) {
                if (!e || e.isLeaf) return !0;
                e = e.firstChild, o--
            }
        }
        return !1
    }

    function Ae(e, t, n, r = n.contentMatch, o = !0) {
        let i = e.doc.nodeAt(t),
            s = [],
            a = t + 1;
        for (let t = 0; t < i.childCount; t++) {
            let c = i.child(t),
                u = a + c.nodeSize,
                d = r.matchType(c.type);
            if (d) {
                r = d;
                for (let t = 0; t < c.marks.length; t++) n.allowsMarkType(c.marks[t].type) || e.step(new Me(a, u, c.marks[t]));
                if (o && c.isText && "pre" != n.whitespace) {
                    let e, t, r = /\r?\n|\r/g;
                    for (; e = r.exec(c.text);) t || (t = new f(l.from(n.schema.text(" ", n.allowedMarks(c.marks))), 0, 0)), s.push(new Ne(a + e.index, a + e.index + e[0].length, t))
                }
            } else s.push(new Ne(a, u, f.empty));
            a = u
        }
        if (!r.validEnd) {
            let t = r.fillBefore(l.empty, !0);
            e.replace(a, a, new f(t, 0, 0))
        }
        for (let t = s.length - 1; t >= 0; t--) e.step(s[t])
    }

    function Le(e, t, n) {
        return (0 == t || e.canReplace(t, e.childCount)) && (n == e.childCount || e.canReplace(0, n))
    }

    function Ie(e) {
        let t = e.parent.content.cutByIndex(e.startIndex, e.endIndex);
        for (let n = e.depth, r = 0, o = 0;; --n) {
            let i = e.$from.node(n),
                s = e.$from.index(n) + r,
                a = e.$to.indexAfter(n) - o;
            if (n < e.depth && i.canReplace(s, a, t)) return n;
            if (0 == n || i.type.spec.isolating || !Le(i, s, a)) break;
            s && (r = 1), a < i.childCount && (o = 1)
        }
        return null
    }

    function Re(e) {
        return {
            type: e,
            attrs: null
        }
    }

    function Pe(e, t, n, r) {
        t.forEach((o, i) => {
            if (o.isText) {
                let s, a = /\r?\n|\r/g;
                for (; s = a.exec(o.text);) {
                    let o = e.mapping.slice(r).map(n + 1 + i + s.index);
                    e.replaceWith(o, o + 1, t.type.schema.linebreakReplacement.create())
                }
            }
        })
    }

    function Be(e, t, n, r) {
        t.forEach((o, i) => {
            if (o.type == o.type.schema.linebreakReplacement) {
                let o = e.mapping.slice(r).map(n + 1 + i);
                e.replaceWith(o, o + 1, t.type.schema.text("\n"))
            }
        })
    }

    function Fe(e, t, n = 1, r) {
        let o = e.resolve(t),
            i = o.depth - n,
            s = r && r[r.length - 1] || o.parent;
        if (i < 0 || o.parent.type.spec.isolating || !o.parent.canReplace(o.index(), o.parent.childCount) || !s.type.validContent(o.parent.content.cutByIndex(o.index(), o.parent.childCount))) return !1;
        for (let e = o.depth - 1, t = n - 2; e > i; e--, t--) {
            let n = o.node(e),
                i = o.index(e);
            if (n.type.spec.isolating) return !1;
            let s = n.content.cutByIndex(i, n.childCount),
                a = r && r[t + 1];
            a && (s = s.replaceChild(0, a.type.create(a.attrs)));
            let l = r && r[t] || n;
            if (!n.canReplace(i + 1, n.childCount) || !l.type.validContent(s)) return !1
        }
        let a = o.indexAfter(i),
            l = r && r[0];
        return o.node(i).canReplaceWith(a, a, l ? l.type : o.node(i + 1).type)
    }

    function He(e, t) {
        let n = e.resolve(t),
            r = n.index();
        return o = n.nodeBefore, i = n.nodeAfter, !(!o || !i || o.isLeaf || ! function(e, t) {
            t.content.size || e.type.compatibleContent(t.type);
            let n = e.contentMatchAt(e.childCount),
                {
                    linebreakReplacement: r
                } = e.type.schema;
            for (let o = 0; o < t.childCount; o++) {
                let i = t.child(o),
                    s = i.type == r ? e.type.schema.nodes.text : i.type;
                if (n = n.matchType(s), !n) return !1;
                if (!e.type.allowsMarks(i.marks)) return !1
            }
            return n.validEnd
        }(o, i)) && n.parent.canReplace(r, r + 1);
        var o, i
    }

    function ze(e, t, n = t, r = f.empty) {
        if (t == n && !r.size) return null;
        let o = e.resolve(t),
            i = e.resolve(n);
        return qe(o, i, r) ? new Ne(t, n, r) : new Ve(o, i, r).fit()
    }

    function qe(e, t, n) {
        return !n.openStart && !n.openEnd && e.start() == t.start() && e.parent.canReplace(e.index(), t.index(), n.content)
    }
    ke.jsonID("replaceAround", Oe);
    class Ve {
        constructor(e, t, n) {
            this.$from = e, this.$to = t, this.unplaced = n, this.frontier = [], this.placed = l.empty;
            for (let t = 0; t <= e.depth; t++) {
                let n = e.node(t);
                this.frontier.push({
                    type: n.type,
                    match: n.contentMatchAt(e.indexAfter(t))
                })
            }
            for (let t = e.depth; t > 0; t--) this.placed = l.from(e.node(t).copy(this.placed))
        }
        get depth() {
            return this.frontier.length - 1
        }
        fit() {
            for (; this.unplaced.size;) {
                let e = this.findFittable();
                e ? this.placeNodes(e) : this.openMore() || this.dropNode()
            }
            let e = this.mustMoveInline(),
                t = this.placed.size - this.depth - this.$from.depth,
                n = this.$from,
                r = this.close(e < 0 ? this.$to : n.doc.resolve(e));
            if (!r) return null;
            let o = this.placed,
                i = n.depth,
                s = r.depth;
            for (; i && s && 1 == o.childCount;) o = o.firstChild.content, i--, s--;
            let a = new f(o, i, s);
            return e > -1 ? new Oe(n.pos, e, this.$to.pos, this.$to.end(), a, t) : a.size || n.pos != this.$to.pos ? new Ne(n.pos, r.pos, a) : null
        }
        findFittable() {
            let e = this.unplaced.openStart;
            for (let t = this.unplaced.content, n = 0, r = this.unplaced.openEnd; n < e; n++) {
                let o = t.firstChild;
                if (t.childCount > 1 && (r = 0), o.type.spec.isolating && r <= n) {
                    e = n;
                    break
                }
                t = o.content
            }
            for (let t = 1; t <= 2; t++)
                for (let n = 1 == t ? e : this.unplaced.openStart; n >= 0; n--) {
                    let e, r = null;
                    n ? (r = _e(this.unplaced.content, n - 1).firstChild, e = r.content) : e = this.unplaced.content;
                    let o = e.firstChild;
                    for (let e = this.depth; e >= 0; e--) {
                        let i, {
                                type: s,
                                match: a
                            } = this.frontier[e],
                            c = null;
                        if (1 == t && (o ? a.matchType(o.type) || (c = a.fillBefore(l.from(o), !1)) : r && s.compatibleContent(r.type))) return {
                            sliceDepth: n,
                            frontierDepth: e,
                            parent: r,
                            inject: c
                        };
                        if (2 == t && o && (i = a.findWrapping(o.type))) return {
                            sliceDepth: n,
                            frontierDepth: e,
                            parent: r,
                            wrap: i
                        };
                        if (r && a.matchType(r.type)) break
                    }
                }
        }
        openMore() {
            let {
                content: e,
                openStart: t,
                openEnd: n
            } = this.unplaced, r = _e(e, t);
            return !(!r.childCount || r.firstChild.isLeaf || (this.unplaced = new f(e, t + 1, Math.max(n, r.size + t >= e.size - n ? t + 1 : 0)), 0))
        }
        dropNode() {
            let {
                content: e,
                openStart: t,
                openEnd: n
            } = this.unplaced, r = _e(e, t);
            if (r.childCount <= 1 && t > 0) {
                let o = e.size - t <= t + r.size;
                this.unplaced = new f(je(e, t - 1, 1), t - 1, o ? t - 1 : n)
            } else this.unplaced = new f(je(e, t, 1), t, n)
        }
        placeNodes({
            sliceDepth: e,
            frontierDepth: t,
            parent: n,
            inject: r,
            wrap: o
        }) {
            for (; this.depth > t;) this.closeFrontierNode();
            if (o)
                for (let e = 0; e < o.length; e++) this.openFrontierNode(o[e]);
            let i = this.unplaced,
                s = n ? n.content : i.content,
                a = i.openStart - e,
                c = 0,
                u = [],
                {
                    match: d,
                    type: p
                } = this.frontier[t];
            if (r) {
                for (let e = 0; e < r.childCount; e++) u.push(r.child(e));
                d = d.matchFragment(r)
            }
            let h = s.size + e - (i.content.size - i.openEnd);
            for (; c < s.childCount;) {
                let e = s.child(c),
                    t = d.matchType(e.type);
                if (!t) break;
                c++, (c > 1 || 0 == a || e.content.size) && (d = t, u.push(Ue(e.mark(p.allowedMarks(e.marks)), 1 == c ? a : 0, c == s.childCount ? h : -1)))
            }
            let m = c == s.childCount;
            m || (h = -1), this.placed = $e(this.placed, t, l.from(u)), this.frontier[t].match = d, m && h < 0 && n && n.type == this.frontier[this.depth].type && this.frontier.length > 1 && this.closeFrontierNode();
            for (let e = 0, t = s; e < h; e++) {
                let e = t.lastChild;
                this.frontier.push({
                    type: e.type,
                    match: e.contentMatchAt(e.childCount)
                }), t = e.content
            }
            this.unplaced = m ? 0 == e ? f.empty : new f(je(i.content, e - 1, 1), e - 1, h < 0 ? i.openEnd : e - 1) : new f(je(i.content, e, c), i.openStart, i.openEnd)
        }
        mustMoveInline() {
            if (!this.$to.parent.isTextblock) return -1;
            let e, t = this.frontier[this.depth];
            if (!t.type.isTextblock || !We(this.$to, this.$to.depth, t.type, t.match, !1) || this.$to.depth == this.depth && (e = this.findCloseLevel(this.$to)) && e.depth == this.depth) return -1;
            let {
                depth: n
            } = this.$to, r = this.$to.after(n);
            for (; n > 1 && r == this.$to.end(--n);) ++r;
            return r
        }
        findCloseLevel(e) {
            e: for (let t = Math.min(this.depth, e.depth); t >= 0; t--) {
                let {
                    match: n,
                    type: r
                } = this.frontier[t], o = t < e.depth && e.end(t + 1) == e.pos + (e.depth - (t + 1)), i = We(e, t, r, n, o);
                if (i) {
                    for (let n = t - 1; n >= 0; n--) {
                        let {
                            match: t,
                            type: r
                        } = this.frontier[n], o = We(e, n, r, t, !0);
                        if (!o || o.childCount) continue e
                    }
                    return {
                        depth: t,
                        fit: i,
                        move: o ? e.doc.resolve(e.after(t + 1)) : e
                    }
                }
            }
        }
        close(e) {
            let t = this.findCloseLevel(e);
            if (!t) return null;
            for (; this.depth > t.depth;) this.closeFrontierNode();
            t.fit.childCount && (this.placed = $e(this.placed, t.depth, t.fit)), e = t.move;
            for (let n = t.depth + 1; n <= e.depth; n++) {
                let t = e.node(n),
                    r = t.type.contentMatch.fillBefore(t.content, !0, e.index(n));
                this.openFrontierNode(t.type, t.attrs, r)
            }
            return e
        }
        openFrontierNode(e, t = null, n) {
            let r = this.frontier[this.depth];
            r.match = r.match.matchType(e), this.placed = $e(this.placed, this.depth, l.from(e.create(t, n))), this.frontier.push({
                type: e,
                match: e.contentMatch
            })
        }
        closeFrontierNode() {
            let e = this.frontier.pop().match.fillBefore(l.empty, !0);
            e.childCount && (this.placed = $e(this.placed, this.frontier.length, e))
        }
    }

    function je(e, t, n) {
        return 0 == t ? e.cutByIndex(n, e.childCount) : e.replaceChild(0, e.firstChild.copy(je(e.firstChild.content, t - 1, n)))
    }

    function $e(e, t, n) {
        return 0 == t ? e.append(n) : e.replaceChild(e.childCount - 1, e.lastChild.copy($e(e.lastChild.content, t - 1, n)))
    }

    function _e(e, t) {
        for (let n = 0; n < t; n++) e = e.firstChild.content;
        return e
    }

    function Ue(e, t, n) {
        if (t <= 0) return e;
        let r = e.content;
        return t > 1 && (r = r.replaceChild(0, Ue(r.firstChild, t - 1, 1 == r.childCount ? n - 1 : 0))), t > 0 && (r = e.type.contentMatch.fillBefore(r).append(r), n <= 0 && (r = r.append(e.type.contentMatch.matchFragment(r).fillBefore(l.empty, !0)))), e.copy(r)
    }

    function We(e, t, n, r, o) {
        let i = e.node(t),
            s = o ? e.indexAfter(t) : e.index(t);
        if (s == i.childCount && !n.compatibleContent(i.type)) return null;
        let a = r.fillBefore(i.content, !0, s);
        return a && ! function(e, t, n) {
            for (let r = n; r < t.childCount; r++)
                if (!e.allowsMarks(t.child(r).marks)) return !0;
            return !1
        }(n, i.content, s) ? a : null
    }

    function Je(e) {
        return e.spec.defining || e.spec.definingForContent
    }

    function Ke(e, t, n, r, o) {
        if (t < n) {
            let o = e.firstChild;
            e = e.replaceChild(0, o.copy(Ke(o.content, t + 1, n, r, o)))
        }
        if (t > r) {
            let t = o.contentMatchAt(0),
                n = t.fillBefore(e).append(e);
            e = n.append(t.matchFragment(n).fillBefore(l.empty, !0))
        }
        return e
    }

    function Ge(e, t) {
        let n = [];
        for (let r = Math.min(e.depth, t.depth); r >= 0; r--) {
            let o = e.start(r);
            if (o < e.pos - (e.depth - r) || t.end(r) > t.pos + (t.depth - r) || e.node(r).type.spec.isolating || t.node(r).type.spec.isolating) break;
            (o == t.start(r) || r == e.depth && r == t.depth && e.parent.inlineContent && t.parent.inlineContent && r && t.start(r - 1) == o - 1) && n.push(r)
        }
        return n
    }
    class Xe extends ke {
        constructor(e, t, n) {
            super(), this.pos = e, this.attr = t, this.value = n
        }
        apply(e) {
            let t = e.nodeAt(this.pos);
            if (!t) return xe.fail("No node at attribute step's position");
            let n = Object.create(null);
            for (let e in t.attrs) n[e] = t.attrs[e];
            n[this.attr] = this.value;
            let r = t.type.create(n, null, t.marks);
            return xe.fromReplace(e, this.pos, this.pos + 1, new f(l.from(r), 0, t.isLeaf ? 0 : 1))
        }
        getMap() {
            return ye.empty
        }
        invert(e) {
            return new Xe(this.pos, this.attr, e.nodeAt(this.pos).attrs[this.attr])
        }
        map(e) {
            let t = e.mapResult(this.pos, 1);
            return t.deletedAfter ? null : new Xe(t.pos, this.attr, this.value)
        }
        toJSON() {
            return {
                stepType: "attr",
                pos: this.pos,
                attr: this.attr,
                value: this.value
            }
        }
        static fromJSON(e, t) {
            if ("number" != typeof t.pos || "string" != typeof t.attr) throw new RangeError("Invalid input for AttrStep.fromJSON");
            return new Xe(t.pos, t.attr, t.value)
        }
    }
    ke.jsonID("attr", Xe);
    class Ze extends ke {
        constructor(e, t) {
            super(), this.attr = e, this.value = t
        }
        apply(e) {
            let t = Object.create(null);
            for (let n in e.attrs) t[n] = e.attrs[n];
            t[this.attr] = this.value;
            let n = e.type.create(t, e.content, e.marks);
            return xe.ok(n)
        }
        getMap() {
            return ye.empty
        }
        invert(e) {
            return new Ze(this.attr, e.attrs[this.attr])
        }
        map(e) {
            return this
        }
        toJSON() {
            return {
                stepType: "docAttr",
                attr: this.attr,
                value: this.value
            }
        }
        static fromJSON(e, t) {
            if ("string" != typeof t.attr) throw new RangeError("Invalid input for DocAttrStep.fromJSON");
            return new Ze(t.attr, t.value)
        }
    }
    ke.jsonID("docAttr", Ze);
    let Qe = class extends Error {};
    Qe = function e(t) {
        let n = Error.call(this, t);
        return n.__proto__ = e.prototype, n
    }, (Qe.prototype = Object.create(Error.prototype)).constructor = Qe, Qe.prototype.name = "TransformError";
    class Ye {
        constructor(e) {
            this.doc = e, this.steps = [], this.docs = [], this.mapping = new be
        }
        get before() {
            return this.docs.length ? this.docs[0] : this.doc
        }
        step(e) {
            let t = this.maybeStep(e);
            if (t.failed) throw new Qe(t.failed);
            return this
        }
        maybeStep(e) {
            let t = e.apply(this.doc);
            return t.failed || this.addStep(e, t.doc), t
        }
        get docChanged() {
            return this.steps.length > 0
        }
        changedRange() {
            let e = 1e9,
                t = -1e9;
            for (let n = 0; n < this.mapping.maps.length; n++) {
                let r = this.mapping.maps[n];
                n && (e = r.map(e, 1), t = r.map(t, -1)), r.forEach((n, r, o, i) => {
                    e = Math.min(e, o), t = Math.max(t, i)
                })
            }
            return 1e9 == e ? null : {
                from: e,
                to: t
            }
        }
        addStep(e, t) {
            this.docs.push(this.doc), this.steps.push(e), this.mapping.appendMap(e.getMap()), this.doc = t
        }
        replace(e, t = e, n = f.empty) {
            let r = ze(this.doc, e, t, n);
            return r && this.step(r), this
        }
        replaceWith(e, t, n) {
            return this.replace(e, t, new f(l.from(n), 0, 0))
        }
        delete(e, t) {
            return this.replace(e, t, f.empty)
        }
        insert(e, t) {
            return this.replaceWith(e, e, t)
        }
        replaceRange(e, t, n) {
            return function(e, t, n, r) {
                if (!r.size) return e.deleteRange(t, n);
                let o = e.doc.resolve(t),
                    i = e.doc.resolve(n);
                if (qe(o, i, r)) return e.step(new Ne(t, n, r));
                let s = Ge(o, i);
                0 == s[s.length - 1] && s.pop();
                let a = -(o.depth + 1);
                s.unshift(a);
                for (let e = o.depth, t = o.pos - 1; e > 0; e--, t--) {
                    let n = o.node(e).type.spec;
                    if (n.defining || n.definingAsContext || n.isolating) break;
                    s.indexOf(e) > -1 ? a = e : o.before(e) == t && s.splice(1, 0, -e)
                }
                let l = s.indexOf(a),
                    c = [],
                    u = r.openStart;
                for (let e = r.content, t = 0;; t++) {
                    let n = e.firstChild;
                    if (c.push(n), t == r.openStart) break;
                    e = n.content
                }
                for (let e = u - 1; e >= 0; e--) {
                    let t = c[e],
                        n = Je(t.type);
                    if (n && !t.sameMarkup(o.node(Math.abs(a) - 1))) u = e;
                    else if (n || !t.type.isTextblock) break
                }
                for (let t = r.openStart; t >= 0; t--) {
                    let a = (t + u + 1) % (r.openStart + 1),
                        d = c[a];
                    if (d)
                        for (let t = 0; t < s.length; t++) {
                            let c = s[(t + l) % s.length],
                                u = !0;
                            c < 0 && (u = !1, c = -c);
                            let p = o.node(c - 1),
                                h = o.index(c - 1);
                            if (p.canReplaceWith(h, h, d.type, d.marks)) return e.replace(o.before(c), u ? i.after(c) : n, new f(Ke(r.content, 0, r.openStart, a), a, r.openEnd))
                        }
                }
                let d = e.steps.length;
                for (let a = s.length - 1; a >= 0 && (e.replace(t, n, r), !(e.steps.length > d)); a--) {
                    let e = s[a];
                    e < 0 || (t = o.before(e), n = i.after(e))
                }
            }(this, e, t, n), this
        }
        replaceRangeWith(e, t, n) {
            return function(e, t, n, r) {
                if (!r.isInline && t == n && e.doc.resolve(t).parent.content.size) {
                    let o = function(e, t, n) {
                        let r = e.resolve(t);
                        if (r.parent.canReplaceWith(r.index(), r.index(), n)) return t;
                        if (0 == r.parentOffset)
                            for (let e = r.depth - 1; e >= 0; e--) {
                                let t = r.index(e);
                                if (r.node(e).canReplaceWith(t, t, n)) return r.before(e + 1);
                                if (t > 0) return null
                            }
                        if (r.parentOffset == r.parent.content.size)
                            for (let e = r.depth - 1; e >= 0; e--) {
                                let t = r.indexAfter(e);
                                if (r.node(e).canReplaceWith(t, t, n)) return r.after(e + 1);
                                if (t < r.node(e).childCount) return null
                            }
                        return null
                    }(e.doc, t, r.type);
                    null != o && (t = n = o)
                }
                e.replaceRange(t, n, new f(l.from(r), 0, 0))
            }(this, e, t, n), this
        }
        deleteRange(e, t) {
            return function(e, t, n) {
                let r = e.doc.resolve(t),
                    o = e.doc.resolve(n);
                if (r.parent.isTextblock && o.parent.isTextblock && r.start() != o.start() && 0 == r.parentOffset && 0 == o.parentOffset) {
                    let i = r.sharedDepth(n),
                        s = !1;
                    for (let e = r.depth; e > i; e--) r.node(e).type.spec.isolating && (s = !0);
                    for (let e = o.depth; e > i; e--) o.node(e).type.spec.isolating && (s = !0);
                    if (!s) {
                        for (let e = r.depth; e > 0 && t == r.start(e); e--) t = r.before(e);
                        for (let e = o.depth; e > 0 && n == o.start(e); e--) n = o.before(e);
                        r = e.doc.resolve(t), o = e.doc.resolve(n)
                    }
                }
                let i = Ge(r, o);
                for (let t = 0; t < i.length; t++) {
                    let n = i[t],
                        s = t == i.length - 1;
                    if (s && 0 == n || r.node(n).type.contentMatch.validEnd) return e.delete(r.start(n), o.end(n));
                    if (n > 0 && (s || r.node(n - 1).canReplace(r.index(n - 1), o.indexAfter(n - 1)))) return e.delete(r.before(n), o.after(n))
                }
                for (let i = 1; i <= r.depth && i <= o.depth; i++)
                    if (t - r.start(i) == r.depth - i && n > r.end(i) && o.end(i) - n != o.depth - i && r.start(i - 1) == o.start(i - 1) && r.node(i - 1).canReplace(r.index(i - 1), o.index(i - 1))) return e.delete(r.before(i), n);
                e.delete(t, n)
            }(this, e, t), this
        }
        lift(e, t) {
            return function(e, t, n) {
                let {
                    $from: r,
                    $to: o,
                    depth: i
                } = t, s = r.before(i + 1), a = o.after(i + 1), c = s, u = a, d = l.empty, p = 0;
                for (let e = i, t = !1; e > n; e--) t || r.index(e) > 0 ? (t = !0, d = l.from(r.node(e).copy(d)), p++) : c--;
                let h = l.empty,
                    m = 0;
                for (let e = i, t = !1; e > n; e--) t || o.after(e + 1) < o.end(e) ? (t = !0, h = l.from(o.node(e).copy(h)), m++) : u++;
                e.step(new Oe(c, u, s, a, new f(d.append(h), p, m), d.size - p, !0))
            }(this, e, t), this
        }
        join(e, t = 1) {
            return function(e, t, n) {
                let r = null,
                    {
                        linebreakReplacement: o
                    } = e.doc.type.schema,
                    i = e.doc.resolve(t - n),
                    s = i.node().type;
                if (o && s.inlineContent) {
                    let e = "pre" == s.whitespace,
                        t = !!s.contentMatch.matchType(o);
                    e && !t ? r = !1 : !e && t && (r = !0)
                }
                let a = e.steps.length;
                if (!1 === r) {
                    let r = e.doc.resolve(t + n);
                    Be(e, r.node(), r.before(), a)
                }
                s.inlineContent && Ae(e, t + n - 1, s, i.node().contentMatchAt(i.index()), null == r);
                let l = e.mapping.slice(a),
                    c = l.map(t - n);
                if (e.step(new Ne(c, l.map(t + n, -1), f.empty, !0)), !0 === r) {
                    let t = e.doc.resolve(c);
                    Pe(e, t.node(), t.before(), e.steps.length)
                }
            }(this, e, t), this
        }
        wrap(e, t) {
            return function(e, t, n) {
                let r = l.empty;
                for (let e = n.length - 1; e >= 0; e--) {
                    if (r.size) {
                        let t = n[e].type.contentMatch.matchFragment(r);
                        if (!t || !t.validEnd) throw new RangeError("Wrapper type given to Transform.wrap does not form valid content of its parent wrapper")
                    }
                    r = l.from(n[e].type.create(n[e].attrs, r))
                }
                let o = t.start,
                    i = t.end;
                e.step(new Oe(o, i, o, i, new f(r, 0, 0), n.length, !0))
            }(this, e, t), this
        }
        setBlockType(e, t = e, n, r = null) {
            return function(e, t, n, r, o) {
                if (!r.isTextblock) throw new RangeError("Type given to setBlockType should be a textblock");
                let i = e.steps.length;
                e.doc.nodesBetween(t, n, (t, n) => {
                    let s = "function" == typeof o ? o(t) : o;
                    if (t.isTextblock && !t.hasMarkup(r, s) && function(e, t, n) {
                            let r = e.resolve(t),
                                o = r.index();
                            return r.parent.canReplaceWith(o, o + 1, n)
                        }(e.doc, e.mapping.slice(i).map(n), r)) {
                        let o = null;
                        if (r.schema.linebreakReplacement) {
                            let e = "pre" == r.whitespace,
                                t = !!r.contentMatch.matchType(r.schema.linebreakReplacement);
                            e && !t ? o = !1 : !e && t && (o = !0)
                        }!1 === o && Be(e, t, n, i), Ae(e, e.mapping.slice(i).map(n, 1), r, void 0, null === o);
                        let a = e.mapping.slice(i),
                            c = a.map(n, 1),
                            u = a.map(n + t.nodeSize, 1);
                        return e.step(new Oe(c, u, c + 1, u - 1, new f(l.from(r.create(s, null, t.marks)), 0, 0), 1, !0)), !0 === o && Pe(e, t, n, i), !1
                    }
                })
            }(this, e, t, n, r), this
        }
        setNodeMarkup(e, t, n = null, r) {
            return function(e, t, n, r, o) {
                let i = e.doc.nodeAt(t);
                if (!i) throw new RangeError("No node at given position");
                n || (n = i.type);
                let s = n.create(r, null, o || i.marks);
                if (i.isLeaf) return e.replaceWith(t, t + i.nodeSize, s);
                if (!n.validContent(i.content)) throw new RangeError("Invalid content for node type " + n.name);
                e.step(new Oe(t, t + i.nodeSize, t + 1, t + i.nodeSize - 1, new f(l.from(s), 0, 0), 1, !0))
            }(this, e, t, n, r), this
        }
        setNodeAttribute(e, t, n) {
            return this.step(new Xe(e, t, n)), this
        }
        setDocAttribute(e, t) {
            return this.step(new Ze(e, t)), this
        }
        addNodeMark(e, t) {
            return this.step(new Se(e, t)), this
        }
        removeNodeMark(e, t) {
            let n = this.doc.nodeAt(e);
            if (!n) throw new RangeError("No node at position " + e);
            if (t instanceof p) t.isInSet(n.marks) && this.step(new Ee(e, t));
            else {
                let r, o = n.marks,
                    i = [];
                for (; r = t.isInSet(o);) i.push(new Ee(e, r)), o = r.removeFromSet(o);
                for (let e = i.length - 1; e >= 0; e--) this.step(i[e])
            }
            return this
        }
        split(e, t = 1, n) {
            return function(e, t, n = 1, r) {
                let o = e.doc.resolve(t),
                    i = l.empty,
                    s = l.empty;
                for (let e = o.depth, t = o.depth - n, a = n - 1; e > t; e--, a--) {
                    i = l.from(o.node(e).copy(i));
                    let t = r && r[a];
                    s = l.from(t ? t.type.create(t.attrs, s) : o.node(e).copy(s))
                }
                e.step(new Ne(t, t, new f(i.append(s), n, n), !0))
            }(this, e, t, n), this
        }
        addMark(e, t, n) {
            return function(e, t, n, r) {
                let o, i, s = [],
                    a = [];
                e.doc.nodesBetween(t, n, (e, l, c) => {
                    if (!e.isInline) return;
                    let u = e.marks;
                    if (!r.isInSet(u) && c.type.allowsMarkType(r.type)) {
                        let c = Math.max(l, t),
                            d = Math.min(l + e.nodeSize, n),
                            p = r.addToSet(u);
                        for (let e = 0; e < u.length; e++) u[e].isInSet(p) || (o && o.to == c && o.mark.eq(u[e]) ? o.to = d : s.push(o = new Me(c, d, u[e])));
                        i && i.to == c ? i.to = d : a.push(i = new Te(c, d, r))
                    }
                }), s.forEach(t => e.step(t)), a.forEach(t => e.step(t))
            }(this, e, t, n), this
        }
        removeMark(e, t, n) {
            return function(e, t, n, r) {
                let o = [],
                    i = 0;
                e.doc.nodesBetween(t, n, (e, s) => {
                    if (!e.isInline) return;
                    i++;
                    let a = null;
                    if (r instanceof X) {
                        let t, n = e.marks;
                        for (; t = r.isInSet(n);)(a || (a = [])).push(t), n = t.removeFromSet(n)
                    } else r ? r.isInSet(e.marks) && (a = [r]) : a = e.marks;
                    if (a && a.length) {
                        let r = Math.min(s + e.nodeSize, n);
                        for (let e = 0; e < a.length; e++) {
                            let n, l = a[e];
                            for (let e = 0; e < o.length; e++) {
                                let t = o[e];
                                t.step == i - 1 && l.eq(o[e].style) && (n = t)
                            }
                            n ? (n.to = r, n.step = i) : o.push({
                                style: l,
                                from: Math.max(s, t),
                                to: r,
                                step: i
                            })
                        }
                    }
                }), o.forEach(t => e.step(new Me(t.from, t.to, t.style)))
            }(this, e, t, n), this
        }
        clearIncompatible(e, t, n) {
            return Ae(this, e, t, n), this
        }
    }
    const et = Object.create(null);
    class tt {
        constructor(e, t, n) {
            this.$anchor = e, this.$head = t, this.ranges = n || [new nt(e.min(t), e.max(t))]
        }
        get anchor() {
            return this.$anchor.pos
        }
        get head() {
            return this.$head.pos
        }
        get from() {
            return this.$from.pos
        }
        get to() {
            return this.$to.pos
        }
        get $from() {
            return this.ranges[0].$from
        }
        get $to() {
            return this.ranges[0].$to
        }
        get empty() {
            let e = this.ranges;
            for (let t = 0; t < e.length; t++)
                if (e[t].$from.pos != e[t].$to.pos) return !1;
            return !0
        }
        content() {
            return this.$from.doc.slice(this.from, this.to, !0)
        }
        replace(e, t = f.empty) {
            let n = t.content.lastChild,
                r = null;
            for (let e = 0; e < t.openEnd; e++) r = n, n = n.lastChild;
            let o = e.steps.length,
                i = this.ranges;
            for (let s = 0; s < i.length; s++) {
                let {
                    $from: a,
                    $to: l
                } = i[s], c = e.mapping.slice(o);
                e.replaceRange(c.map(a.pos), c.map(l.pos), s ? f.empty : t), 0 == s && pt(e, o, (n ? n.isInline : r && r.isTextblock) ? -1 : 1)
            }
        }
        replaceWith(e, t) {
            let n = e.steps.length,
                r = this.ranges;
            for (let o = 0; o < r.length; o++) {
                let {
                    $from: i,
                    $to: s
                } = r[o], a = e.mapping.slice(n), l = a.map(i.pos), c = a.map(s.pos);
                o ? e.deleteRange(l, c) : (e.replaceRangeWith(l, c, t), pt(e, n, t.isInline ? -1 : 1))
            }
        }
        static findFrom(e, t, n = !1) {
            let r = e.parent.inlineContent ? new it(e) : dt(e.node(0), e.parent, e.pos, e.index(), t, n);
            if (r) return r;
            for (let r = e.depth - 1; r >= 0; r--) {
                let o = t < 0 ? dt(e.node(0), e.node(r), e.before(r + 1), e.index(r), t, n) : dt(e.node(0), e.node(r), e.after(r + 1), e.index(r) + 1, t, n);
                if (o) return o
            }
            return null
        }
        static near(e, t = 1) {
            return this.findFrom(e, t) || this.findFrom(e, -t) || new ct(e.node(0))
        }
        static atStart(e) {
            return dt(e, e, 0, 0, 1) || new ct(e)
        }
        static atEnd(e) {
            return dt(e, e, e.content.size, e.childCount, -1) || new ct(e)
        }
        static fromJSON(e, t) {
            if (!t || !t.type) throw new RangeError("Invalid input for Selection.fromJSON");
            let n = et[t.type];
            if (!n) throw new RangeError(`No selection type ${t.type} defined`);
            return n.fromJSON(e, t)
        }
        static jsonID(e, t) {
            if (e in et) throw new RangeError("Duplicate use of selection JSON ID " + e);
            return et[e] = t, t.prototype.jsonID = e, t
        }
        getBookmark() {
            return it.between(this.$anchor, this.$head).getBookmark()
        }
    }
    tt.prototype.visible = !0;
    class nt {
        constructor(e, t) {
            this.$from = e, this.$to = t
        }
    }
    let rt = !1;

    function ot(e) {
        rt || e.parent.inlineContent || (rt = !0, console.warn("TextSelection endpoint not pointing into a node with inline content (" + e.parent.type.name + ")"))
    }
    class it extends tt {
        constructor(e, t = e) {
            ot(e), ot(t), super(e, t)
        }
        get $cursor() {
            return this.$anchor.pos == this.$head.pos ? this.$head : null
        }
        map(e, t) {
            let n = e.resolve(t.map(this.head));
            if (!n.parent.inlineContent) return tt.near(n);
            let r = e.resolve(t.map(this.anchor));
            return new it(r.parent.inlineContent ? r : n, n)
        }
        replace(e, t = f.empty) {
            if (super.replace(e, t), t == f.empty) {
                let t = this.$from.marksAcross(this.$to);
                t && e.ensureMarks(t)
            }
        }
        eq(e) {
            return e instanceof it && e.anchor == this.anchor && e.head == this.head
        }
        getBookmark() {
            return new st(this.anchor, this.head)
        }
        toJSON() {
            return {
                type: "text",
                anchor: this.anchor,
                head: this.head
            }
        }
        static fromJSON(e, t) {
            if ("number" != typeof t.anchor || "number" != typeof t.head) throw new RangeError("Invalid input for TextSelection.fromJSON");
            return new it(e.resolve(t.anchor), e.resolve(t.head))
        }
        static create(e, t, n = t) {
            let r = e.resolve(t);
            return new this(r, n == t ? r : e.resolve(n))
        }
        static between(e, t, n) {
            let r = e.pos - t.pos;
            if (n && !r || (n = r >= 0 ? 1 : -1), !t.parent.inlineContent) {
                let e = tt.findFrom(t, n, !0) || tt.findFrom(t, -n, !0);
                if (!e) return tt.near(t, n);
                t = e.$head
            }
            return e.parent.inlineContent || (0 == r || (e = (tt.findFrom(e, -n, !0) || tt.findFrom(e, n, !0)).$anchor).pos < t.pos != r < 0) && (e = t), new it(e, t)
        }
    }
    tt.jsonID("text", it);
    class st {
        constructor(e, t) {
            this.anchor = e, this.head = t
        }
        map(e) {
            return new st(e.map(this.anchor), e.map(this.head))
        }
        resolve(e) {
            return it.between(e.resolve(this.anchor), e.resolve(this.head))
        }
    }
    class at extends tt {
        constructor(e) {
            let t = e.nodeAfter,
                n = e.node(0).resolve(e.pos + t.nodeSize);
            super(e, n), this.node = t
        }
        map(e, t) {
            let {
                deleted: n,
                pos: r
            } = t.mapResult(this.anchor), o = e.resolve(r);
            return n ? tt.near(o) : new at(o)
        }
        content() {
            return new f(l.from(this.node), 0, 0)
        }
        eq(e) {
            return e instanceof at && e.anchor == this.anchor
        }
        toJSON() {
            return {
                type: "node",
                anchor: this.anchor
            }
        }
        getBookmark() {
            return new lt(this.anchor)
        }
        static fromJSON(e, t) {
            if ("number" != typeof t.anchor) throw new RangeError("Invalid input for NodeSelection.fromJSON");
            return new at(e.resolve(t.anchor))
        }
        static create(e, t) {
            return new at(e.resolve(t))
        }
        static isSelectable(e) {
            return !e.isText && !1 !== e.type.spec.selectable
        }
    }
    at.prototype.visible = !1, tt.jsonID("node", at);
    class lt {
        constructor(e) {
            this.anchor = e
        }
        map(e) {
            let {
                deleted: t,
                pos: n
            } = e.mapResult(this.anchor);
            return t ? new st(n, n) : new lt(n)
        }
        resolve(e) {
            let t = e.resolve(this.anchor),
                n = t.nodeAfter;
            return n && at.isSelectable(n) ? new at(t) : tt.near(t)
        }
    }
    class ct extends tt {
        constructor(e) {
            super(e.resolve(0), e.resolve(e.content.size))
        }
        replace(e, t = f.empty) {
            if (t == f.empty) {
                e.delete(0, e.doc.content.size);
                let t = tt.atStart(e.doc);
                t.eq(e.selection) || e.setSelection(t)
            } else super.replace(e, t)
        }
        toJSON() {
            return {
                type: "all"
            }
        }
        static fromJSON(e) {
            return new ct(e)
        }
        map(e) {
            return new ct(e)
        }
        eq(e) {
            return e instanceof ct
        }
        getBookmark() {
            return ut
        }
    }
    tt.jsonID("all", ct);
    const ut = {
        map() {
            return this
        },
        resolve: e => new ct(e)
    };

    function dt(e, t, n, r, o, i = !1) {
        if (t.inlineContent) return it.create(e, n);
        for (let s = r - (o > 0 ? 0 : 1); o > 0 ? s < t.childCount : s >= 0; s += o) {
            let r = t.child(s);
            if (r.isAtom) {
                if (!i && at.isSelectable(r)) return at.create(e, n - (o < 0 ? r.nodeSize : 0))
            } else {
                let t = dt(e, r, n + o, o < 0 ? r.childCount : 0, o, i);
                if (t) return t
            }
            n += r.nodeSize * o
        }
        return null
    }

    function pt(e, t, n) {
        let r = e.steps.length - 1;
        if (r < t) return;
        let o, i = e.steps[r];
        (i instanceof Ne || i instanceof Oe) && (e.mapping.maps[r].forEach((e, t, n, r) => {
            null == o && (o = r)
        }), e.setSelection(tt.near(e.doc.resolve(o), n)))
    }
    class ht extends Ye {
        constructor(e) {
            super(e.doc), this.curSelectionFor = 0, this.updated = 0, this.meta = Object.create(null), this.time = Date.now(), this.curSelection = e.selection, this.storedMarks = e.storedMarks
        }
        get selection() {
            return this.curSelectionFor < this.steps.length && (this.curSelection = this.curSelection.map(this.doc, this.mapping.slice(this.curSelectionFor)), this.curSelectionFor = this.steps.length), this.curSelection
        }
        setSelection(e) {
            if (e.$from.doc != this.doc) throw new RangeError("Selection passed to setSelection must point at the current document");
            return this.curSelection = e, this.curSelectionFor = this.steps.length, this.updated = -3 & this.updated | 1, this.storedMarks = null, this
        }
        get selectionSet() {
            return (1 & this.updated) > 0
        }
        setStoredMarks(e) {
            return this.storedMarks = e, this.updated |= 2, this
        }
        ensureMarks(e) {
            return p.sameSet(this.storedMarks || this.selection.$from.marks(), e) || this.setStoredMarks(e), this
        }
        addStoredMark(e) {
            return this.ensureMarks(e.addToSet(this.storedMarks || this.selection.$head.marks()))
        }
        removeStoredMark(e) {
            return this.ensureMarks(e.removeFromSet(this.storedMarks || this.selection.$head.marks()))
        }
        get storedMarksSet() {
            return (2 & this.updated) > 0
        }
        addStep(e, t) {
            super.addStep(e, t), this.updated = -3 & this.updated, this.storedMarks = null
        }
        setTime(e) {
            return this.time = e, this
        }
        replaceSelection(e) {
            return this.selection.replace(this, e), this
        }
        replaceSelectionWith(e, t = !0) {
            let n = this.selection;
            return t && (e = e.mark(this.storedMarks || (n.empty ? n.$from.marks() : n.$from.marksAcross(n.$to) || p.none))), n.replaceWith(this, e), this
        }
        deleteSelection() {
            return this.selection.replace(this), this
        }
        insertText(e, t, n) {
            let r = this.doc.type.schema;
            if (null == t) return e ? this.replaceSelectionWith(r.text(e), !0) : this.deleteSelection();
            {
                if (null == n && (n = t), !e) return this.deleteRange(t, n);
                let o = this.storedMarks;
                if (!o) {
                    let e = this.doc.resolve(t);
                    o = n == t ? e.marks() : e.marksAcross(this.doc.resolve(n))
                }
                return this.replaceRangeWith(t, n, r.text(e, o)), this.selection.empty || this.selection.to != t + e.length || this.setSelection(tt.near(this.selection.$to)), this
            }
        }
        setMeta(e, t) {
            return this.meta["string" == typeof e ? e : e.key] = t, this
        }
        getMeta(e) {
            return this.meta["string" == typeof e ? e : e.key]
        }
        get isGeneric() {
            for (let e in this.meta) return !1;
            return !0
        }
        scrollIntoView() {
            return this.updated |= 4, this
        }
        get scrolledIntoView() {
            return (4 & this.updated) > 0
        }
    }

    function ft(e, t) {
        return t && e ? e.bind(t) : e
    }
    class mt {
        constructor(e, t, n) {
            this.name = e, this.init = ft(t.init, n), this.apply = ft(t.apply, n)
        }
    }
    const gt = [new mt("doc", {
        init: e => e.doc || e.schema.topNodeType.createAndFill(),
        apply: e => e.doc
    }), new mt("selection", {
        init: (e, t) => e.selection || tt.atStart(t.doc),
        apply: e => e.selection
    }), new mt("storedMarks", {
        init: e => e.storedMarks || null,
        apply: (e, t, n, r) => r.selection.$cursor ? e.storedMarks : null
    }), new mt("scrollToSelection", {
        init: () => 0,
        apply: (e, t) => e.scrolledIntoView ? t + 1 : t
    })];
    class vt {
        constructor(e, t) {
            this.schema = e, this.plugins = [], this.pluginsByKey = Object.create(null), this.fields = gt.slice(), t && t.forEach(e => {
                if (this.pluginsByKey[e.key]) throw new RangeError("Adding different instances of a keyed plugin (" + e.key + ")");
                this.plugins.push(e), this.pluginsByKey[e.key] = e, e.spec.state && this.fields.push(new mt(e.key, e.spec.state, e))
            })
        }
    }
    class yt {
        constructor(e) {
            this.config = e
        }
        get schema() {
            return this.config.schema
        }
        get plugins() {
            return this.config.plugins
        }
        apply(e) {
            return this.applyTransaction(e).state
        }
        filterTransaction(e, t = -1) {
            for (let n = 0; n < this.config.plugins.length; n++)
                if (n != t) {
                    let t = this.config.plugins[n];
                    if (t.spec.filterTransaction && !t.spec.filterTransaction.call(t, e, this)) return !1
                } return !0
        }
        applyTransaction(e) {
            if (!this.filterTransaction(e)) return {
                state: this,
                transactions: []
            };
            let t = [e],
                n = this.applyInner(e),
                r = null;
            for (;;) {
                let o = !1;
                for (let i = 0; i < this.config.plugins.length; i++) {
                    let s = this.config.plugins[i];
                    if (s.spec.appendTransaction) {
                        let a = r ? r[i].n : 0,
                            l = r ? r[i].state : this,
                            c = a < t.length && s.spec.appendTransaction.call(s, a ? t.slice(a) : t, l, n);
                        if (c && n.filterTransaction(c, i)) {
                            if (c.setMeta("appendedTransaction", e), !r) {
                                r = [];
                                for (let e = 0; e < this.config.plugins.length; e++) r.push(e < i ? {
                                    state: n,
                                    n: t.length
                                } : {
                                    state: this,
                                    n: 0
                                })
                            }
                            t.push(c), n = n.applyInner(c), o = !0
                        }
                        r && (r[i] = {
                            state: n,
                            n: t.length
                        })
                    }
                }
                if (!o) return {
                    state: n,
                    transactions: t
                }
            }
        }
        applyInner(e) {
            if (!e.before.eq(this.doc)) throw new RangeError("Applying a mismatched transaction");
            let t = new yt(this.config),
                n = this.config.fields;
            for (let r = 0; r < n.length; r++) {
                let o = n[r];
                t[o.name] = o.apply(e, this[o.name], this, t)
            }
            return t
        }
        get tr() {
            return new ht(this)
        }
        static create(e) {
            let t = new vt(e.doc ? e.doc.type.schema : e.schema, e.plugins),
                n = new yt(t);
            for (let r = 0; r < t.fields.length; r++) n[t.fields[r].name] = t.fields[r].init(e, n);
            return n
        }
        reconfigure(e) {
            let t = new vt(this.schema, e.plugins),
                n = t.fields,
                r = new yt(t);
            for (let t = 0; t < n.length; t++) {
                let o = n[t].name;
                r[o] = this.hasOwnProperty(o) ? this[o] : n[t].init(e, r)
            }
            return r
        }
        toJSON(e) {
            let t = {
                doc: this.doc.toJSON(),
                selection: this.selection.toJSON()
            };
            if (this.storedMarks && (t.storedMarks = this.storedMarks.map(e => e.toJSON())), e && "object" == typeof e)
                for (let n in e) {
                    if ("doc" == n || "selection" == n) throw new RangeError("The JSON fields `doc` and `selection` are reserved");
                    let r = e[n],
                        o = r.spec.state;
                    o && o.toJSON && (t[n] = o.toJSON.call(r, this[r.key]))
                }
            return t
        }
        static fromJSON(e, t, n) {
            if (!t) throw new RangeError("Invalid input for EditorState.fromJSON");
            if (!e.schema) throw new RangeError("Required config field 'schema' missing");
            let r = new vt(e.schema, e.plugins),
                o = new yt(r);
            return r.fields.forEach(r => {
                if ("doc" == r.name) o.doc = L.fromJSON(e.schema, t.doc);
                else if ("selection" == r.name) o.selection = tt.fromJSON(o.doc, t.selection);
                else if ("storedMarks" == r.name) t.storedMarks && (o.storedMarks = t.storedMarks.map(e.schema.markFromJSON));
                else {
                    if (n)
                        for (let i in n) {
                            let s = n[i],
                                a = s.spec.state;
                            if (s.key == r.name && a && a.fromJSON && Object.prototype.hasOwnProperty.call(t, i)) return void(o[r.name] = a.fromJSON.call(s, e, t[i], o))
                        }
                    o[r.name] = r.init(e, o)
                }
            }), o
        }
    }

    function bt(e, t, n) {
        for (let r in e) {
            let o = e[r];
            o instanceof Function ? o = o.bind(t) : "handleDOMEvents" == r && (o = bt(o, t, {})), n[r] = o
        }
        return n
    }
    class wt {
        constructor(e) {
            this.spec = e, this.props = {}, e.props && bt(e.props, this, this.props), this.key = e.key ? e.key.key : xt("plugin")
        }
        getState(e) {
            return e[this.key]
        }
    }
    const kt = Object.create(null);

    function xt(e) {
        return e in kt ? e + "$" + ++kt[e] : (kt[e] = 0, e + "$")
    }
    class Ct {
        constructor(e = "key") {
            this.key = xt(e)
        }
        get(e) {
            return e.config.pluginsByKey[this.key]
        }
        getState(e) {
            return e[this.key]
        }
    }
    const Tt = function(e) {
            for (var t = 0;; t++)
                if (!(e = e.previousSibling)) return t
        },
        Mt = function(e) {
            let t = e.assignedSlot || e.parentNode;
            return t && 11 == t.nodeType ? t.host : t
        };
    let St = null;
    const Et = function(e, t, n) {
            let r = St || (St = document.createRange());
            return r.setEnd(e, n ?? e.nodeValue.length), r.setStart(e, t || 0), r
        },
        Nt = function(e, t, n, r) {
            return n && (Dt(e, t, n, r, -1) || Dt(e, t, n, r, 1))
        },
        Ot = /^(img|br|input|textarea|hr)$/i;

    function Dt(e, t, n, r, o) {
        for (var i;;) {
            if (e == n && t == r) return !0;
            if (t == (o < 0 ? 0 : At(e))) {
                let n = e.parentNode;
                if (!n || 1 != n.nodeType || Lt(e) || Ot.test(e.nodeName) || "false" == e.contentEditable) return !1;
                t = Tt(e) + (o < 0 ? 0 : 1), e = n
            } else {
                if (1 != e.nodeType) return !1;
                {
                    let n = e.childNodes[t + (o < 0 ? -1 : 0)];
                    if (1 == n.nodeType && "false" == n.contentEditable) {
                        if (!(null === (i = n.pmViewDesc) || void 0 === i ? void 0 : i.ignoreForSelection)) return !1;
                        t += o
                    } else e = n, t = o < 0 ? At(e) : 0
                }
            }
        }
    }

    function At(e) {
        return 3 == e.nodeType ? e.nodeValue.length : e.childNodes.length
    }

    function Lt(e) {
        let t;
        for (let n = e; n && !(t = n.pmViewDesc); n = n.parentNode);
        return t && t.node && t.node.isBlock && (t.dom == e || t.contentDOM == e)
    }
    const It = function(e) {
        return e.focusNode && Nt(e.focusNode, e.focusOffset, e.anchorNode, e.anchorOffset)
    };

    function Rt(e, t) {
        let n = document.createEvent("Event");
        return n.initEvent("keydown", !0, !0), n.keyCode = e, n.key = n.code = t, n
    }
    const Pt = "undefined" != typeof navigator ? navigator : null,
        Bt = "undefined" != typeof document ? document : null,
        Ft = Pt && Pt.userAgent || "",
        Ht = /Edge\/(\d+)/.exec(Ft),
        zt = /MSIE \d/.exec(Ft),
        qt = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(Ft),
        Vt = !!(zt || qt || Ht),
        jt = zt ? document.documentMode : qt ? +qt[1] : Ht ? +Ht[1] : 0,
        $t = !Vt && /gecko\/(\d+)/i.test(Ft);
    $t && (/Firefox\/(\d+)/.exec(Ft) || [0, 0])[1];
    const _t = !Vt && /Chrome\/(\d+)/.exec(Ft),
        Ut = !!_t,
        Wt = _t ? +_t[1] : 0,
        Jt = !Vt && !!Pt && /Apple Computer/.test(Pt.vendor),
        Kt = Jt && (/Mobile\/\w+/.test(Ft) || !!Pt && Pt.maxTouchPoints > 2),
        Gt = Kt || !!Pt && /Mac/.test(Pt.platform),
        Xt = !!Pt && /Win/.test(Pt.platform),
        Zt = /Android \d/.test(Ft),
        Qt = !!Bt && "webkitFontSmoothing" in Bt.documentElement.style,
        Yt = Qt ? +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) || [0, 0])[1] : 0;

    function en(e) {
        let t = e.defaultView && e.defaultView.visualViewport;
        return t ? {
            left: 0,
            right: t.width,
            top: 0,
            bottom: t.height
        } : {
            left: 0,
            right: e.documentElement.clientWidth,
            top: 0,
            bottom: e.documentElement.clientHeight
        }
    }

    function tn(e, t) {
        return "number" == typeof e ? e : e[t]
    }

    function nn(e) {
        let t = e.getBoundingClientRect(),
            n = t.width / e.offsetWidth || 1,
            r = t.height / e.offsetHeight || 1;
        return {
            left: t.left,
            right: t.left + e.clientWidth * n,
            top: t.top,
            bottom: t.top + e.clientHeight * r
        }
    }

    function rn(e, t, n) {
        if (!pn(t) && 0 == t.left) return;
        let r = e.someProp("scrollThreshold") || 0,
            o = e.someProp("scrollMargin") || 5,
            i = e.dom.ownerDocument;
        for (let s = n || e.dom; s;) {
            if (1 != s.nodeType) {
                s = Mt(s);
                continue
            }
            let e = s,
                n = e == i.body,
                a = n ? en(i) : nn(e),
                l = 0,
                c = 0;
            if (t.top < a.top + tn(r, "top") ? c = -(a.top - t.top + tn(o, "top")) : t.bottom > a.bottom - tn(r, "bottom") && (c = t.bottom - t.top > a.bottom - a.top ? t.top + tn(o, "top") - a.top : t.bottom - a.bottom + tn(o, "bottom")), t.left < a.left + tn(r, "left") ? l = -(a.left - t.left + tn(o, "left")) : t.right > a.right - tn(r, "right") && (l = t.right - a.right + tn(o, "right")), l || c)
                if (n) i.defaultView.scrollBy(l, c);
                else {
                    let n = e.scrollLeft,
                        r = e.scrollTop;
                    c && (e.scrollTop += c), l && (e.scrollLeft += l);
                    let o = e.scrollLeft - n,
                        i = e.scrollTop - r;
                    t = {
                        left: t.left - o,
                        top: t.top - i,
                        right: t.right - o,
                        bottom: t.bottom - i
                    }
                } let u = n ? "fixed" : getComputedStyle(s).position;
            if (/^(fixed|sticky)$/.test(u)) break;
            s = "absolute" == u ? s.offsetParent : Mt(s)
        }
    }

    function on(e) {
        let t = [],
            n = e.ownerDocument;
        for (let r = e; r && (t.push({
                dom: r,
                top: r.scrollTop,
                left: r.scrollLeft
            }), e != n); r = Mt(r));
        return t
    }

    function sn(e, t) {
        for (let n = 0; n < e.length; n++) {
            let {
                dom: r,
                top: o,
                left: i
            } = e[n];
            r.scrollTop != o + t && (r.scrollTop = o + t), r.scrollLeft != i && (r.scrollLeft = i)
        }
    }
    let an = null;

    function ln(e, t) {
        let n, r, o, i, s = 2e8,
            a = 0,
            l = t.top,
            c = t.top;
        for (let u = e.firstChild, d = 0; u; u = u.nextSibling, d++) {
            let e;
            if (1 == u.nodeType) e = u.getClientRects();
            else {
                if (3 != u.nodeType) continue;
                e = Et(u).getClientRects()
            }
            for (let p = 0; p < e.length; p++) {
                let h = e[p];
                if (h.top <= l && h.bottom >= c) {
                    l = Math.max(h.bottom, l), c = Math.min(h.top, c);
                    let e = h.left > t.left ? h.left - t.left : h.right < t.left ? t.left - h.right : 0;
                    if (e < s) {
                        n = u, s = e, r = e && 3 == n.nodeType ? {
                            left: h.right < t.left ? h.right : h.left,
                            top: t.top
                        } : t, 1 == u.nodeType && e && (a = d + (t.left >= (h.left + h.right) / 2 ? 1 : 0));
                        continue
                    }
                } else h.top > t.top && !o && h.left <= t.left && h.right >= t.left && (o = u, i = {
                    left: Math.max(h.left, Math.min(h.right, t.left)),
                    top: h.top
                });
                !n && (t.left >= h.right && t.top >= h.top || t.left >= h.left && t.top >= h.bottom) && (a = d + 1)
            }
        }
        return !n && o && (n = o, r = i, s = 0), n && 3 == n.nodeType ? function(e, t) {
            let n, r = e.nodeValue.length,
                o = document.createRange();
            for (let i = 0; i < r; i++) {
                o.setEnd(e, i + 1), o.setStart(e, i);
                let r = hn(o, 1);
                if (r.top != r.bottom && cn(t, r)) {
                    n = {
                        node: e,
                        offset: i + (t.left >= (r.left + r.right) / 2 ? 1 : 0)
                    };
                    break
                }
            }
            return o.detach(), n || {
                node: e,
                offset: 0
            }
        }(n, r) : !n || s && 1 == n.nodeType ? {
            node: e,
            offset: a
        } : ln(n, r)
    }

    function cn(e, t) {
        return e.left >= t.left - 1 && e.left <= t.right + 1 && e.top >= t.top - 1 && e.top <= t.bottom + 1
    }

    function un(e, t, n) {
        let r = e.childNodes.length;
        if (r && n.top < n.bottom)
            for (let o = Math.max(0, Math.min(r - 1, Math.floor(r * (t.top - n.top) / (n.bottom - n.top)) - 2)), i = o;;) {
                let n = e.childNodes[i];
                if (1 == n.nodeType) {
                    let e = n.getClientRects();
                    for (let r = 0; r < e.length; r++) {
                        let o = e[r];
                        if (cn(t, o)) return un(n, t, o)
                    }
                }
                if ((i = (i + 1) % r) == o) break
            }
        return e
    }

    function dn(e, t) {
        let n, r = e.dom.ownerDocument,
            o = 0,
            i = function(e, t, n) {
                if (e.caretPositionFromPoint) try {
                    let r = e.caretPositionFromPoint(t, n);
                    if (r) return {
                        node: r.offsetNode,
                        offset: Math.min(At(r.offsetNode), r.offset)
                    }
                } catch (e) {}
                if (e.caretRangeFromPoint) {
                    let r = e.caretRangeFromPoint(t, n);
                    if (r) return {
                        node: r.startContainer,
                        offset: Math.min(At(r.startContainer), r.startOffset)
                    }
                }
            }(r, t.left, t.top);
        i && ({
            node: n,
            offset: o
        } = i);
        let s, a = (e.root.elementFromPoint ? e.root : r).elementFromPoint(t.left, t.top);
        if (!a || !e.dom.contains(1 != a.nodeType ? a.parentNode : a)) {
            let n = e.dom.getBoundingClientRect();
            if (!cn(t, n)) return null;
            if (a = un(e.dom, t, n), !a) return null
        }
        if (Jt)
            for (let e = a; n && e; e = Mt(e)) e.draggable && (n = void 0);
        if (a = function(e, t) {
                let n = e.parentNode;
                return n && /^li$/i.test(n.nodeName) && t.left < e.getBoundingClientRect().left ? n : e
            }(a, t), n) {
            if ($t && 1 == n.nodeType && (o = Math.min(o, n.childNodes.length), o < n.childNodes.length)) {
                let e, r = n.childNodes[o];
                "IMG" == r.nodeName && (e = r.getBoundingClientRect()).right <= t.left && e.bottom > t.top && o++
            }
            let r;
            Qt && o && 1 == n.nodeType && 1 == (r = n.childNodes[o - 1]).nodeType && "false" == r.contentEditable && r.getBoundingClientRect().top >= t.top && o--, n == e.dom && o == n.childNodes.length - 1 && 1 == n.lastChild.nodeType && t.top > n.lastChild.getBoundingClientRect().bottom ? s = e.state.doc.content.size : 0 != o && 1 == n.nodeType && "BR" == n.childNodes[o - 1].nodeName || (s = function(e, t, n, r) {
                let o = -1;
                for (let n = t, i = !1; n != e.dom;) {
                    let t, s = e.docView.nearestDesc(n, !0);
                    if (!s) return null;
                    if (1 == s.dom.nodeType && (s.node.isBlock && s.parent || !s.contentDOM) && ((t = s.dom.getBoundingClientRect()).width || t.height) && (s.node.isBlock && s.parent && !/^T(R|BODY|HEAD|FOOT)$/.test(s.dom.nodeName) && (!i && t.left > r.left || t.top > r.top ? o = s.posBefore : (!i && t.right < r.left || t.bottom < r.top) && (o = s.posAfter), i = !0), !s.contentDOM && o < 0 && !s.node.isText)) return (s.node.isBlock ? r.top < (t.top + t.bottom) / 2 : r.left < (t.left + t.right) / 2) ? s.posBefore : s.posAfter;
                    n = s.dom.parentNode
                }
                return o > -1 ? o : e.docView.posFromDOM(t, n, -1)
            }(e, n, o, t))
        }
        null == s && (s = function(e, t, n) {
            let {
                node: r,
                offset: o
            } = ln(t, n), i = -1;
            if (1 == r.nodeType && !r.firstChild) {
                let e = r.getBoundingClientRect();
                i = e.left != e.right && n.left > (e.left + e.right) / 2 ? 1 : -1
            }
            return e.docView.posFromDOM(r, o, i)
        }(e, a, t));
        let l = e.docView.nearestDesc(a, !0);
        return {
            pos: s,
            inside: l ? l.posAtStart - l.border : -1
        }
    }

    function pn(e) {
        return e.top < e.bottom || e.left < e.right
    }

    function hn(e, t) {
        let n = e.getClientRects();
        if (n.length) {
            let e = n[t < 0 ? 0 : n.length - 1];
            if (pn(e)) return e
        }
        return Array.prototype.find.call(n, pn) || e.getBoundingClientRect()
    }
    const fn = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;

    function mn(e, t, n) {
        let {
            node: r,
            offset: o,
            atom: i
        } = e.docView.domFromPos(t, n < 0 ? -1 : 1), s = Qt || $t;
        if (3 == r.nodeType) {
            if (!s || !fn.test(r.nodeValue) && (n < 0 ? o : o != r.nodeValue.length)) {
                let e = o,
                    t = o,
                    i = n < 0 ? 1 : -1;
                return n < 0 && !o ? (t++, i = -1) : n >= 0 && o == r.nodeValue.length ? (e--, i = 1) : n < 0 ? e-- : t++, gn(hn(Et(r, e, t), i), i < 0)
            } {
                let e = hn(Et(r, o, o), n);
                if ($t && o && /\s/.test(r.nodeValue[o - 1]) && o < r.nodeValue.length) {
                    let t = hn(Et(r, o - 1, o - 1), -1);
                    if (t.top == e.top) {
                        let n = hn(Et(r, o, o + 1), -1);
                        if (n.top != e.top) return gn(n, n.left < t.left)
                    }
                }
                return e
            }
        }
        if (!e.state.doc.resolve(t - (i || 0)).parent.inlineContent) {
            if (null == i && o && (n < 0 || o == At(r))) {
                let e = r.childNodes[o - 1];
                if (1 == e.nodeType) return vn(e.getBoundingClientRect(), !1)
            }
            if (null == i && o < At(r)) {
                let e = r.childNodes[o];
                if (1 == e.nodeType) return vn(e.getBoundingClientRect(), !0)
            }
            return vn(r.getBoundingClientRect(), n >= 0)
        }
        if (null == i && o && (n < 0 || o == At(r))) {
            let e = r.childNodes[o - 1],
                t = 3 == e.nodeType ? Et(e, At(e) - (s ? 0 : 1)) : 1 != e.nodeType || "BR" == e.nodeName && e.nextSibling ? null : e;
            if (t) return gn(hn(t, 1), !1)
        }
        if (null == i && o < At(r)) {
            let e = r.childNodes[o];
            for (; e.pmViewDesc && e.pmViewDesc.ignoreForCoords;) e = e.nextSibling;
            let t = e ? 3 == e.nodeType ? Et(e, 0, s ? 0 : 1) : 1 == e.nodeType ? e : null : null;
            if (t) return gn(hn(t, -1), !0)
        }
        return gn(hn(3 == r.nodeType ? Et(r) : r, -n), n >= 0)
    }

    function gn(e, t) {
        if (0 == e.width) return e;
        let n = t ? e.left : e.right;
        return {
            top: e.top,
            bottom: e.bottom,
            left: n,
            right: n
        }
    }

    function vn(e, t) {
        if (0 == e.height) return e;
        let n = t ? e.top : e.bottom;
        return {
            top: n,
            bottom: n,
            left: e.left,
            right: e.right
        }
    }

    function yn(e, t, n) {
        let r = e.state,
            o = e.root.activeElement;
        r != t && e.updateState(t), o != e.dom && e.focus();
        try {
            return n()
        } finally {
            r != t && e.updateState(r), o != e.dom && o && o.focus()
        }
    }
    const bn = /[\u0590-\u08ac]/;
    let wn = null,
        kn = null,
        xn = !1;
    class Cn {
        constructor(e, t, n, r) {
            this.parent = e, this.children = t, this.dom = n, this.contentDOM = r, this.dirty = 0, n.pmViewDesc = this
        }
        matchesWidget(e) {
            return !1
        }
        matchesMark(e) {
            return !1
        }
        matchesNode(e, t, n) {
            return !1
        }
        matchesHack(e) {
            return !1
        }
        parseRule(e) {
            return null
        }
        stopEvent(e) {
            return !1
        }
        get size() {
            let e = 0;
            for (let t = 0; t < this.children.length; t++) e += this.children[t].size;
            return e
        }
        get border() {
            return 0
        }
        destroy() {
            this.parent = void 0, this.dom.pmViewDesc == this && (this.dom.pmViewDesc = void 0);
            for (let e = 0; e < this.children.length; e++) this.children[e].destroy()
        }
        posBeforeChild(e) {
            for (let t = 0, n = this.posAtStart;; t++) {
                let r = this.children[t];
                if (r == e) return n;
                n += r.size
            }
        }
        get posBefore() {
            return this.parent.posBeforeChild(this)
        }
        get posAtStart() {
            return this.parent ? this.parent.posBeforeChild(this) + this.border : 0
        }
        get posAfter() {
            return this.posBefore + this.size
        }
        get posAtEnd() {
            return this.posAtStart + this.size - 2 * this.border
        }
        localPosFromDOM(e, t, n) {
            if (this.contentDOM && this.contentDOM.contains(1 == e.nodeType ? e : e.parentNode)) {
                if (n < 0) {
                    let n, r;
                    if (e == this.contentDOM) n = e.childNodes[t - 1];
                    else {
                        for (; e.parentNode != this.contentDOM;) e = e.parentNode;
                        n = e.previousSibling
                    }
                    for (; n && (!(r = n.pmViewDesc) || r.parent != this);) n = n.previousSibling;
                    return n ? this.posBeforeChild(r) + r.size : this.posAtStart
                } {
                    let n, r;
                    if (e == this.contentDOM) n = e.childNodes[t];
                    else {
                        for (; e.parentNode != this.contentDOM;) e = e.parentNode;
                        n = e.nextSibling
                    }
                    for (; n && (!(r = n.pmViewDesc) || r.parent != this);) n = n.nextSibling;
                    return n ? this.posBeforeChild(r) : this.posAtEnd
                }
            }
            let r;
            if (e == this.dom && this.contentDOM) r = t > Tt(this.contentDOM);
            else if (this.contentDOM && this.contentDOM != this.dom && this.dom.contains(this.contentDOM)) r = 2 & e.compareDocumentPosition(this.contentDOM);
            else if (this.dom.firstChild) {
                if (0 == t)
                    for (let t = e;; t = t.parentNode) {
                        if (t == this.dom) {
                            r = !1;
                            break
                        }
                        if (t.previousSibling) break
                    }
                if (null == r && t == e.childNodes.length)
                    for (let t = e;; t = t.parentNode) {
                        if (t == this.dom) {
                            r = !0;
                            break
                        }
                        if (t.nextSibling) break
                    }
            }
            return r ?? n > 0 ? this.posAtEnd : this.posAtStart
        }
        nearestDesc(e, t = !1) {
            for (let n = !0, r = e; r; r = r.parentNode) {
                let o, i = this.getDesc(r);
                if (i && (!t || i.node)) {
                    if (!n || !(o = i.nodeDOM) || (1 == o.nodeType ? o.contains(1 == e.nodeType ? e : e.parentNode) : o == e)) return i;
                    n = !1
                }
            }
        }
        getDesc(e) {
            let t = e.pmViewDesc;
            for (let e = t; e; e = e.parent)
                if (e == this) return t
        }
        posFromDOM(e, t, n) {
            for (let r = e; r; r = r.parentNode) {
                let o = this.getDesc(r);
                if (o) return o.localPosFromDOM(e, t, n)
            }
            return -1
        }
        descAt(e) {
            for (let t = 0, n = 0; t < this.children.length; t++) {
                let r = this.children[t],
                    o = n + r.size;
                if (n == e && o != n) {
                    for (; !r.border && r.children.length;)
                        for (let e = 0; e < r.children.length; e++) {
                            let t = r.children[e];
                            if (t.size) {
                                r = t;
                                break
                            }
                        }
                    return r
                }
                if (e < o) return r.descAt(e - n - r.border);
                n = o
            }
        }
        domFromPos(e, t) {
            if (!this.contentDOM) return {
                node: this.dom,
                offset: 0,
                atom: e + 1
            };
            let n = 0,
                r = 0;
            for (let t = 0; n < this.children.length; n++) {
                let o = this.children[n],
                    i = t + o.size;
                if (i > e || o instanceof Dn) {
                    r = e - t;
                    break
                }
                t = i
            }
            if (r) return this.children[n].domFromPos(r - this.children[n].border, t);
            for (let e; n && !(e = this.children[n - 1]).size && e instanceof Tn && e.side >= 0; n--);
            if (t <= 0) {
                let e, r = !0;
                for (; e = n ? this.children[n - 1] : null, e && e.dom.parentNode != this.contentDOM; n--, r = !1);
                return e && t && r && !e.border && !e.domAtom ? e.domFromPos(e.size, t) : {
                    node: this.contentDOM,
                    offset: e ? Tt(e.dom) + 1 : 0
                }
            } {
                let e, r = !0;
                for (; e = n < this.children.length ? this.children[n] : null, e && e.dom.parentNode != this.contentDOM; n++, r = !1);
                return e && r && !e.border && !e.domAtom ? e.domFromPos(0, t) : {
                    node: this.contentDOM,
                    offset: e ? Tt(e.dom) : this.contentDOM.childNodes.length
                }
            }
        }
        parseRange(e, t, n = 0) {
            if (0 == this.children.length) return {
                node: this.contentDOM,
                from: e,
                to: t,
                fromOffset: 0,
                toOffset: this.contentDOM.childNodes.length
            };
            let r = -1,
                o = -1;
            for (let i = n, s = 0;; s++) {
                let n = this.children[s],
                    a = i + n.size;
                if (-1 == r && e <= a) {
                    let o = i + n.border;
                    if (e >= o && t <= a - n.border && n.node && n.contentDOM && this.contentDOM.contains(n.contentDOM)) return n.parseRange(e, t, o);
                    e = i;
                    for (let t = s; t > 0; t--) {
                        let n = this.children[t - 1];
                        if (n.size && n.dom.parentNode == this.contentDOM && !n.emptyChildAt(1)) {
                            r = Tt(n.dom) + 1;
                            break
                        }
                        e -= n.size
                    } - 1 == r && (r = 0)
                }
                if (r > -1 && (a > t || s == this.children.length - 1)) {
                    t = a;
                    for (let e = s + 1; e < this.children.length; e++) {
                        let n = this.children[e];
                        if (n.size && n.dom.parentNode == this.contentDOM && !n.emptyChildAt(-1)) {
                            o = Tt(n.dom);
                            break
                        }
                        t += n.size
                    } - 1 == o && (o = this.contentDOM.childNodes.length);
                    break
                }
                i = a
            }
            return {
                node: this.contentDOM,
                from: e,
                to: t,
                fromOffset: r,
                toOffset: o
            }
        }
        emptyChildAt(e) {
            if (this.border || !this.contentDOM || !this.children.length) return !1;
            let t = this.children[e < 0 ? 0 : this.children.length - 1];
            return 0 == t.size || t.emptyChildAt(e)
        }
        domAfterPos(e) {
            let {
                node: t,
                offset: n
            } = this.domFromPos(e, 0);
            if (1 != t.nodeType || n == t.childNodes.length) throw new RangeError("No node after pos " + e);
            return t.childNodes[n]
        }
        setSelection(e, t, n, r = !1) {
            let o = Math.min(e, t),
                i = Math.max(e, t);
            for (let s = 0, a = 0; s < this.children.length; s++) {
                let l = this.children[s],
                    c = a + l.size;
                if (o > a && i < c) return l.setSelection(e - a - l.border, t - a - l.border, n, r);
                a = c
            }
            let s = this.domFromPos(e, e ? -1 : 1),
                a = t == e ? s : this.domFromPos(t, t ? -1 : 1),
                l = n.root.getSelection(),
                c = n.domSelectionRange(),
                u = !1;
            if (($t || Jt) && e == t) {
                let {
                    node: e,
                    offset: t
                } = s;
                if (3 == e.nodeType) {
                    if (u = !(!t || "\n" != e.nodeValue[t - 1]), u && t == e.nodeValue.length)
                        for (let t, n = e; n; n = n.parentNode) {
                            if (t = n.nextSibling) {
                                "BR" == t.nodeName && (s = a = {
                                    node: t.parentNode,
                                    offset: Tt(t) + 1
                                });
                                break
                            }
                            let e = n.pmViewDesc;
                            if (e && e.node && e.node.isBlock) break
                        }
                } else {
                    let n = e.childNodes[t - 1];
                    u = n && ("BR" == n.nodeName || "false" == n.contentEditable)
                }
            }
            if ($t && c.focusNode && c.focusNode != a.node && 1 == c.focusNode.nodeType) {
                let e = c.focusNode.childNodes[c.focusOffset];
                e && "false" == e.contentEditable && (r = !0)
            }
            if (!(r || u && Jt) && Nt(s.node, s.offset, c.anchorNode, c.anchorOffset) && Nt(a.node, a.offset, c.focusNode, c.focusOffset)) return;
            let d = !1;
            if ((l.extend || e == t) && (!u || !$t)) {
                l.collapse(s.node, s.offset);
                try {
                    e != t && l.extend(a.node, a.offset), d = !0
                } catch (e) {}
            }
            if (!d) {
                if (e > t) {
                    let e = s;
                    s = a, a = e
                }
                let n = document.createRange();
                n.setEnd(a.node, a.offset), n.setStart(s.node, s.offset), l.removeAllRanges(), l.addRange(n)
            }
        }
        ignoreMutation(e) {
            return !this.contentDOM && "selection" != e.type
        }
        get contentLost() {
            return this.contentDOM && this.contentDOM != this.dom && !this.dom.contains(this.contentDOM)
        }
        markDirty(e, t) {
            for (let n = 0, r = 0; r < this.children.length; r++) {
                let o = this.children[r],
                    i = n + o.size;
                if (n == i ? e <= i && t >= n : e < i && t > n) {
                    let r = n + o.border,
                        s = i - o.border;
                    if (e >= r && t <= s) return this.dirty = e == n || t == i ? 2 : 1, void(e != r || t != s || !o.contentLost && o.dom.parentNode == this.contentDOM ? o.markDirty(e - r, t - r) : o.dirty = 3);
                    o.dirty = o.dom != o.contentDOM || o.dom.parentNode != this.contentDOM || o.children.length ? 3 : 2
                }
                n = i
            }
            this.dirty = 2
        }
        markParentsDirty() {
            let e = 1;
            for (let t = this.parent; t; t = t.parent, e++) {
                let n = 1 == e ? 2 : 1;
                t.dirty < n && (t.dirty = n)
            }
        }
        get domAtom() {
            return !1
        }
        get ignoreForCoords() {
            return !1
        }
        get ignoreForSelection() {
            return !1
        }
        isText(e) {
            return !1
        }
    }
    class Tn extends Cn {
        constructor(e, t, n, r) {
            let o, i = t.type.toDOM;
            if ("function" == typeof i && (i = i(n, () => o ? o.parent ? o.parent.posBeforeChild(o) : void 0 : r)), !t.type.spec.raw) {
                if (1 != i.nodeType) {
                    let e = document.createElement("span");
                    e.appendChild(i), i = e
                }
                i.contentEditable = "false", i.classList.add("ProseMirror-widget")
            }
            super(e, [], i, null), this.widget = t, this.widget = t, o = this
        }
        matchesWidget(e) {
            return 0 == this.dirty && e.type.eq(this.widget.type)
        }
        parseRule() {
            return {
                ignore: !0
            }
        }
        stopEvent(e) {
            let t = this.widget.spec.stopEvent;
            return !!t && t(e)
        }
        ignoreMutation(e) {
            return "selection" != e.type || this.widget.spec.ignoreSelection
        }
        destroy() {
            this.widget.type.destroy(this.dom), super.destroy()
        }
        get domAtom() {
            return !0
        }
        get ignoreForSelection() {
            return !!this.widget.type.spec.relaxedSide
        }
        get side() {
            return this.widget.type.side
        }
    }
    class Mn extends Cn {
        constructor(e, t, n, r) {
            super(e, [], t, null), this.textDOM = n, this.text = r
        }
        get size() {
            return this.text.length
        }
        localPosFromDOM(e, t) {
            return e != this.textDOM ? this.posAtStart + (t ? this.size : 0) : this.posAtStart + t
        }
        domFromPos(e) {
            return {
                node: this.textDOM,
                offset: e
            }
        }
        ignoreMutation(e) {
            return "characterData" === e.type && e.target.nodeValue == e.oldValue
        }
    }
    class Sn extends Cn {
        constructor(e, t, n, r, o) {
            super(e, [], n, r), this.mark = t, this.spec = o
        }
        static create(e, t, n, r) {
            let o = r.nodeViews[t.type.name],
                i = o && o(t, r, n);
            return i && i.dom || (i = ce.renderSpec(document, t.type.spec.toDOM(t, n), null, t.attrs)), new Sn(e, t, i.dom, i.contentDOM || i.dom, i)
        }
        parseRule() {
            return 3 & this.dirty || this.mark.type.spec.reparseInView ? null : {
                mark: this.mark.type.name,
                attrs: this.mark.attrs,
                contentElement: this.contentDOM
            }
        }
        matchesMark(e) {
            return 3 != this.dirty && this.mark.eq(e)
        }
        markDirty(e, t) {
            if (super.markDirty(e, t), 0 != this.dirty) {
                let e = this.parent;
                for (; !e.node;) e = e.parent;
                e.dirty < this.dirty && (e.dirty = this.dirty), this.dirty = 0
            }
        }
        slice(e, t, n) {
            let r = Sn.create(this.parent, this.mark, !0, n),
                o = this.children,
                i = this.size;
            t < i && (o = $n(o, t, i, n)), e > 0 && (o = $n(o, 0, e, n));
            for (let e = 0; e < o.length; e++) o[e].parent = r;
            return r.children = o, r
        }
        ignoreMutation(e) {
            return this.spec.ignoreMutation ? this.spec.ignoreMutation(e) : super.ignoreMutation(e)
        }
        destroy() {
            this.spec.destroy && this.spec.destroy(), super.destroy()
        }
    }
    class En extends Cn {
        constructor(e, t, n, r, o, i, s) {
            super(e, [], o, i), this.node = t, this.outerDeco = n, this.innerDeco = r, this.nodeDOM = s
        }
        static create(e, t, n, r, o, i) {
            let s, a = o.nodeViews[t.type.name],
                l = a && a(t, o, () => s ? s.parent ? s.parent.posBeforeChild(s) : void 0 : i, n, r),
                c = l && l.dom,
                u = l && l.contentDOM;
            if (t.isText)
                if (c) {
                    if (3 != c.nodeType) throw new RangeError("Text must be rendered as a DOM text node")
                } else c = document.createTextNode(t.text);
            else if (!c) {
                let e = ce.renderSpec(document, t.type.spec.toDOM(t), null, t.attrs);
                ({
                    dom: c,
                    contentDOM: u
                } = e)
            }
            u || t.isText || "BR" == c.nodeName || (c.hasAttribute("contenteditable") || (c.contentEditable = "false"), t.type.spec.draggable && (c.draggable = !0));
            let d = c;
            return c = Hn(c, n, t), l ? s = new An(e, t, n, r, c, u || null, d, l) : t.isText ? new On(e, t, n, r, c, d) : new En(e, t, n, r, c, u || null, d)
        }
        parseRule(e) {
            if (this.node.type.spec.reparseInView) return null;
            let t = {
                node: this.node.type.name,
                attrs: this.node.attrs
            };
            if ("pre" == this.node.type.whitespace && (t.preserveWhitespace = "full"), this.contentDOM)
                if (this.contentLost) {
                    for (let e = this.children.length - 1; e >= 0; e--) {
                        let n = this.children[e];
                        if (this.dom.contains(n.dom.parentNode)) {
                            t.contentElement = n.dom.parentNode;
                            break
                        }
                    }
                    if (!t.contentElement) {
                        let n = e && e.find(t => 1 == t.nodeType && e.indexOf(t.parentNode) < 0 && this.dom.contains(t));
                        n ? t.contentElement = n : t.getContent = () => l.empty
                    }
                } else t.contentElement = this.contentDOM;
            else t.getContent = () => this.node.content;
            return t
        }
        matchesNode(e, t, n) {
            return 0 == this.dirty && e.eq(this.node) && zn(t, this.outerDeco) && n.eq(this.innerDeco)
        }
        get size() {
            return this.node.nodeSize
        }
        get border() {
            return this.node.isLeaf ? 0 : 1
        }
        updateChildren(e, t) {
            let n = this.node.inlineContent,
                r = t,
                o = e.composing ? this.localCompositionInfo(e, t) : null,
                i = o && o.pos > -1 ? o : null,
                s = o && o.pos < 0,
                a = new Vn(this, i && i.node, e);
            ! function(e, t, n, r) {
                let o = t.locals(e),
                    i = 0;
                if (0 == o.length) {
                    for (let n = 0; n < e.childCount; n++) {
                        let s = e.child(n);
                        r(s, o, t.forChild(i, s), n), i += s.nodeSize
                    }
                    return
                }
                let s = 0,
                    a = [],
                    l = null;
                for (let c = 0;;) {
                    let u, d, p, h;
                    for (; s < o.length && o[s].to == i;) {
                        let e = o[s++];
                        e.widget && (u ? (d || (d = [u])).push(e) : u = e)
                    }
                    if (u)
                        if (d) {
                            d.sort(jn);
                            for (let e = 0; e < d.length; e++) n(d[e], c, !!l)
                        } else n(u, c, !!l);
                    if (l) h = -1, p = l, l = null;
                    else {
                        if (!(c < e.childCount)) break;
                        h = c, p = e.child(c++)
                    }
                    for (let e = 0; e < a.length; e++) a[e].to <= i && a.splice(e--, 1);
                    for (; s < o.length && o[s].from <= i && o[s].to > i;) a.push(o[s++]);
                    let f = i + p.nodeSize;
                    if (p.isText) {
                        let e = f;
                        s < o.length && o[s].from < e && (e = o[s].from);
                        for (let t = 0; t < a.length; t++) a[t].to < e && (e = a[t].to);
                        e < f && (l = p.cut(e - i), p = p.cut(0, e - i), f = e, h = -1)
                    } else
                        for (; s < o.length && o[s].to < f;) s++;
                    r(p, p.isInline && !p.isLeaf ? a.filter(e => !e.inline) : a.slice(), t.forChild(i, p), h), i = f
                }
            }(this.node, this.innerDeco, (t, o, i) => {
                t.spec.marks ? a.syncToMarks(t.spec.marks, n, e, o) : t.type.side >= 0 && !i && a.syncToMarks(o == this.node.childCount ? p.none : this.node.child(o).marks, n, e, o), a.placeWidget(t, e, r)
            }, (t, i, l, c) => {
                let u;
                a.syncToMarks(t.marks, n, e, c), a.findNodeMatch(t, i, l, c) || s && e.state.selection.from > r && e.state.selection.to < r + t.nodeSize && (u = a.findIndexWithChild(o.node)) > -1 && a.updateNodeAt(t, i, l, u, e) || a.updateNextNode(t, i, l, e, c, r) || a.addNode(t, i, l, e, r), r += t.nodeSize
            }), a.syncToMarks([], n, e, 0), this.node.isTextblock && a.addTextblockHacks(), a.destroyRest(), (a.changed || 2 == this.dirty) && (i && this.protectLocalComposition(e, i), Ln(this.contentDOM, this.children, e), Kt && function(e) {
                if ("UL" == e.nodeName || "OL" == e.nodeName) {
                    let t = e.style.cssText;
                    e.style.cssText = t + "; list-style: square !important", window.getComputedStyle(e).listStyle, e.style.cssText = t
                }
            }(this.dom))
        }
        localCompositionInfo(e, t) {
            let {
                from: n,
                to: r
            } = e.state.selection;
            if (!(e.state.selection instanceof it) || n < t || r > t + this.node.content.size) return null;
            let o = e.input.compositionNode;
            if (!o || !this.dom.contains(o.parentNode)) return null;
            if (this.node.inlineContent) {
                let e = o.nodeValue,
                    i = function(e, t, n, r) {
                        for (let o = 0, i = 0; o < e.childCount && i <= r;) {
                            let s = e.child(o++),
                                a = i;
                            if (i += s.nodeSize, !s.isText) continue;
                            let l = s.text;
                            for (; o < e.childCount;) {
                                let t = e.child(o++);
                                if (i += t.nodeSize, !t.isText) break;
                                l += t.text
                            }
                            if (i >= n) {
                                if (i >= r && l.slice(r - t.length - a, r - a) == t) return r - t.length;
                                let e = a < r ? l.lastIndexOf(t, r - a - 1) : -1;
                                if (e >= 0 && e + t.length + a >= n) return a + e;
                                if (n == r && l.length >= r + t.length - a && l.slice(r - a, r - a + t.length) == t) return r
                            }
                        }
                        return -1
                    }(this.node.content, e, n - t, r - t);
                return i < 0 ? null : {
                    node: o,
                    pos: i,
                    text: e
                }
            }
            return {
                node: o,
                pos: -1,
                text: ""
            }
        }
        protectLocalComposition(e, {
            node: t,
            pos: n,
            text: r
        }) {
            if (this.getDesc(t)) return;
            let o = t;
            for (; o.parentNode != this.contentDOM; o = o.parentNode) {
                for (; o.previousSibling;) o.parentNode.removeChild(o.previousSibling);
                for (; o.nextSibling;) o.parentNode.removeChild(o.nextSibling);
                o.pmViewDesc && (o.pmViewDesc = void 0)
            }
            let i = new Mn(this, o, t, r);
            e.input.compositionNodes.push(i), this.children = $n(this.children, n, n + r.length, e, i)
        }
        update(e, t, n, r) {
            return !(3 == this.dirty || !e.sameMarkup(this.node) || (this.updateInner(e, t, n, r), 0))
        }
        updateInner(e, t, n, r) {
            this.updateOuterDeco(t), this.node = e, this.innerDeco = n, this.contentDOM && this.updateChildren(r, this.posAtStart), this.dirty = 0
        }
        updateOuterDeco(e) {
            if (zn(e, this.outerDeco)) return;
            let t = 1 != this.nodeDOM.nodeType,
                n = this.dom;
            this.dom = Bn(this.dom, this.nodeDOM, Pn(this.outerDeco, this.node, t), Pn(e, this.node, t)), this.dom != n && (n.pmViewDesc = void 0, this.dom.pmViewDesc = this), this.outerDeco = e
        }
        selectNode() {
            1 == this.nodeDOM.nodeType && (this.nodeDOM.classList.add("ProseMirror-selectednode"), !this.contentDOM && this.node.type.spec.draggable || (this.nodeDOM.draggable = !0))
        }
        deselectNode() {
            1 == this.nodeDOM.nodeType && (this.nodeDOM.classList.remove("ProseMirror-selectednode"), !this.contentDOM && this.node.type.spec.draggable || this.nodeDOM.removeAttribute("draggable"))
        }
        get domAtom() {
            return this.node.isAtom
        }
    }

    function Nn(e, t, n, r, o) {
        Hn(r, t, e);
        let i = new En(void 0, e, t, n, r, r, r);
        return i.contentDOM && i.updateChildren(o, 0), i
    }
    class On extends En {
        constructor(e, t, n, r, o, i) {
            super(e, t, n, r, o, null, i)
        }
        parseRule() {
            let e = this.nodeDOM.parentNode;
            for (; e && e != this.dom && !e.pmIsDeco;) e = e.parentNode;
            return {
                skip: e || !0
            }
        }
        update(e, t, n, r) {
            return !(3 == this.dirty || 0 != this.dirty && !this.inParent() || !e.sameMarkup(this.node) || (this.updateOuterDeco(t), 0 == this.dirty && e.text == this.node.text || e.text == this.nodeDOM.nodeValue || (this.nodeDOM.nodeValue = e.text, r.trackWrites == this.nodeDOM && (r.trackWrites = null)), this.node = e, this.dirty = 0, 0))
        }
        inParent() {
            let e = this.parent.contentDOM;
            for (let t = this.nodeDOM; t; t = t.parentNode)
                if (t == e) return !0;
            return !1
        }
        domFromPos(e) {
            return {
                node: this.nodeDOM,
                offset: e
            }
        }
        localPosFromDOM(e, t, n) {
            return e == this.nodeDOM ? this.posAtStart + Math.min(t, this.node.text.length) : super.localPosFromDOM(e, t, n)
        }
        ignoreMutation(e) {
            return "characterData" != e.type && "selection" != e.type
        }
        slice(e, t, n) {
            let r = this.node.cut(e, t),
                o = document.createTextNode(r.text);
            return new On(this.parent, r, this.outerDeco, this.innerDeco, o, o)
        }
        markDirty(e, t) {
            super.markDirty(e, t), this.dom == this.nodeDOM || 0 != e && t != this.nodeDOM.nodeValue.length || (this.dirty = 3)
        }
        get domAtom() {
            return !1
        }
        isText(e) {
            return this.node.text == e
        }
    }
    class Dn extends Cn {
        parseRule() {
            return {
                ignore: !0
            }
        }
        matchesHack(e) {
            return 0 == this.dirty && this.dom.nodeName == e
        }
        get domAtom() {
            return !0
        }
        get ignoreForCoords() {
            return "IMG" == this.dom.nodeName
        }
    }
    class An extends En {
        constructor(e, t, n, r, o, i, s, a) {
            super(e, t, n, r, o, i, s), this.spec = a
        }
        update(e, t, n, r) {
            if (3 == this.dirty) return !1;
            if (this.spec.update && (this.node.type == e.type || this.spec.multiType)) {
                let o = this.spec.update(e, t, n);
                return o && this.updateInner(e, t, n, r), o
            }
            return !(!this.contentDOM && !e.isLeaf) && super.update(e, t, n, r)
        }
        selectNode() {
            this.spec.selectNode ? this.spec.selectNode() : super.selectNode()
        }
        deselectNode() {
            this.spec.deselectNode ? this.spec.deselectNode() : super.deselectNode()
        }
        setSelection(e, t, n, r) {
            this.spec.setSelection ? this.spec.setSelection(e, t, n.root) : super.setSelection(e, t, n, r)
        }
        destroy() {
            this.spec.destroy && this.spec.destroy(), super.destroy()
        }
        stopEvent(e) {
            return !!this.spec.stopEvent && this.spec.stopEvent(e)
        }
        ignoreMutation(e) {
            return this.spec.ignoreMutation ? this.spec.ignoreMutation(e) : super.ignoreMutation(e)
        }
    }

    function Ln(e, t, n) {
        let r = e.firstChild,
            o = !1;
        for (let i = 0; i < t.length; i++) {
            let s = t[i],
                a = s.dom;
            if (a.parentNode == e) {
                for (; a != r;) r = qn(r), o = !0;
                r = r.nextSibling
            } else o = !0, e.insertBefore(a, r);
            if (s instanceof Sn) {
                let t = r ? r.previousSibling : e.lastChild;
                Ln(s.contentDOM, s.children, n), r = t ? t.nextSibling : e.firstChild
            }
        }
        for (; r;) r = qn(r), o = !0;
        o && n.trackWrites == e && (n.trackWrites = null)
    }
    const In = function(e) {
        e && (this.nodeName = e)
    };
    In.prototype = Object.create(null);
    const Rn = [new In];

    function Pn(e, t, n) {
        if (0 == e.length) return Rn;
        let r = n ? Rn[0] : new In,
            o = [r];
        for (let i = 0; i < e.length; i++) {
            let s = e[i].type.attrs;
            if (s) {
                s.nodeName && o.push(r = new In(s.nodeName));
                for (let e in s) {
                    let i = s[e];
                    null != i && (n && 1 == o.length && o.push(r = new In(t.isInline ? "span" : "div")), "class" == e ? r.class = (r.class ? r.class + " " : "") + i : "style" == e ? r.style = (r.style ? r.style + ";" : "") + i : "nodeName" != e && (r[e] = i))
                }
            }
        }
        return o
    }

    function Bn(e, t, n, r) {
        if (n == Rn && r == Rn) return t;
        let o = t;
        for (let t = 0; t < r.length; t++) {
            let i = r[t],
                s = n[t];
            if (t) {
                let t;
                s && s.nodeName == i.nodeName && o != e && (t = o.parentNode) && t.nodeName.toLowerCase() == i.nodeName || (t = document.createElement(i.nodeName), t.pmIsDeco = !0, t.appendChild(o), s = Rn[0]), o = t
            }
            Fn(o, s || Rn[0], i)
        }
        return o
    }

    function Fn(e, t, n) {
        for (let r in t) "class" == r || "style" == r || "nodeName" == r || r in n || e.removeAttribute(r);
        for (let r in n) "class" != r && "style" != r && "nodeName" != r && n[r] != t[r] && e.setAttribute(r, n[r]);
        if (t.class != n.class) {
            let r = t.class ? t.class.split(" ").filter(Boolean) : [],
                o = n.class ? n.class.split(" ").filter(Boolean) : [];
            for (let t = 0; t < r.length; t++) - 1 == o.indexOf(r[t]) && e.classList.remove(r[t]);
            for (let t = 0; t < o.length; t++) - 1 == r.indexOf(o[t]) && e.classList.add(o[t]);
            0 == e.classList.length && e.removeAttribute("class")
        }
        if (t.style != n.style) {
            if (t.style) {
                let n, r = /\s*([\w\-\xa1-\uffff]+)\s*:(?:"(?:\\.|[^"])*"|'(?:\\.|[^'])*'|\(.*?\)|[^;])*/g;
                for (; n = r.exec(t.style);) e.style.removeProperty(n[1])
            }
            n.style && (e.style.cssText += n.style)
        }
    }

    function Hn(e, t, n) {
        return Bn(e, e, Rn, Pn(t, n, 1 != e.nodeType))
    }

    function zn(e, t) {
        if (e.length != t.length) return !1;
        for (let n = 0; n < e.length; n++)
            if (!e[n].type.eq(t[n].type)) return !1;
        return !0
    }

    function qn(e) {
        let t = e.nextSibling;
        return e.parentNode.removeChild(e), t
    }
    class Vn {
        constructor(e, t, n) {
            this.lock = t, this.view = n, this.index = 0, this.stack = [], this.changed = !1, this.top = e, this.preMatch = function(e, t) {
                let n = t,
                    r = n.children.length,
                    o = e.childCount,
                    i = new Map,
                    s = [];
                e: for (; o > 0;) {
                    let a;
                    for (;;)
                        if (r) {
                            let e = n.children[r - 1];
                            if (!(e instanceof Sn)) {
                                a = e, r--;
                                break
                            }
                            n = e, r = e.children.length
                        } else {
                            if (n == t) break e;
                            r = n.parent.children.indexOf(n), n = n.parent
                        } let l = a.node;
                    if (l) {
                        if (l != e.child(o - 1)) break;
                        --o, i.set(a, o), s.push(a)
                    }
                }
                return {
                    index: o,
                    matched: i,
                    matches: s.reverse()
                }
            }(e.node.content, e)
        }
        destroyBetween(e, t) {
            if (e != t) {
                for (let n = e; n < t; n++) this.top.children[n].destroy();
                this.top.children.splice(e, t - e), this.changed = !0
            }
        }
        destroyRest() {
            this.destroyBetween(this.index, this.top.children.length)
        }
        syncToMarks(e, t, n, r) {
            let o = 0,
                i = this.stack.length >> 1,
                s = Math.min(i, e.length);
            for (; o < s && (o == i - 1 ? this.top : this.stack[o + 1 << 1]).matchesMark(e[o]) && !1 !== e[o].type.spec.spanning;) o++;
            for (; o < i;) this.destroyRest(), this.top.dirty = 0, this.index = this.stack.pop(), this.top = this.stack.pop(), i--;
            for (; i < e.length;) {
                this.stack.push(this.top, this.index + 1);
                let o = -1,
                    s = this.top.children.length;
                r < this.preMatch.index && (s = Math.min(this.index + 3, s));
                for (let t = this.index; t < s; t++) {
                    let n = this.top.children[t];
                    if (n.matchesMark(e[i]) && !this.isLocked(n.dom)) {
                        o = t;
                        break
                    }
                }
                if (o < 0 && this.index < this.top.children.length) {
                    let t = this.top.children[this.index];
                    t instanceof Sn && 3 != t.dirty && t.mark.type == e[i].type && t.spec.update && !this.isLocked(t.dom) && t.spec.update(e[i]) && (t.mark = e[i], o = this.index, this.changed = !0)
                }
                if (o > -1) o > this.index && (this.changed = !0, this.destroyBetween(this.index, o)), this.top = this.top.children[this.index];
                else {
                    let r = Sn.create(this.top, e[i], t, n);
                    this.top.children.splice(this.index, 0, r), this.top = r, this.changed = !0
                }
                this.index = 0, i++
            }
        }
        findNodeMatch(e, t, n, r) {
            let o, i = -1;
            if (r >= this.preMatch.index && (o = this.preMatch.matches[r - this.preMatch.index]).parent == this.top && o.matchesNode(e, t, n)) i = this.top.children.indexOf(o, this.index);
            else
                for (let r = this.index, o = Math.min(this.top.children.length, r + 5); r < o; r++) {
                    let o = this.top.children[r];
                    if (o.matchesNode(e, t, n) && !this.preMatch.matched.has(o)) {
                        i = r;
                        break
                    }
                }
            return !(i < 0 || (this.destroyBetween(this.index, i), this.index++, 0))
        }
        updateNodeAt(e, t, n, r, o) {
            let i = this.top.children[r];
            return 3 == i.dirty && i.dom == i.contentDOM && (i.dirty = 2), !!i.update(e, t, n, o) && (this.destroyBetween(this.index, r), this.index++, !0)
        }
        findIndexWithChild(e) {
            for (;;) {
                let t = e.parentNode;
                if (!t) return -1;
                if (t == this.top.contentDOM) {
                    let t = e.pmViewDesc;
                    if (t)
                        for (let e = this.index; e < this.top.children.length; e++)
                            if (this.top.children[e] == t) return e;
                    return -1
                }
                e = t
            }
        }
        updateNextNode(e, t, n, r, o, i) {
            for (let s = this.index; s < this.top.children.length; s++) {
                let a = this.top.children[s];
                if (a instanceof En) {
                    let l = this.preMatch.matched.get(a);
                    if (null != l && l != o) return !1;
                    let c, u = a.dom,
                        d = this.isLocked(u) && !(e.isText && a.node && a.node.isText && a.nodeDOM.nodeValue == e.text && 3 != a.dirty && zn(t, a.outerDeco));
                    if (!d && a.update(e, t, n, r)) return this.destroyBetween(this.index, s), a.dom != u && (this.changed = !0), this.index++, !0;
                    if (!d && (c = this.recreateWrapper(a, e, t, n, r, i))) return this.destroyBetween(this.index, s), this.top.children[this.index] = c, c.contentDOM && (c.dirty = 2, c.updateChildren(r, i + 1), c.dirty = 0), this.changed = !0, this.index++, !0;
                    break
                }
            }
            return !1
        }
        recreateWrapper(e, t, n, r, o, i) {
            if (e.dirty || t.isAtom || !e.children.length || !e.node.content.eq(t.content) || !zn(n, e.outerDeco) || !r.eq(e.innerDeco)) return null;
            let s = En.create(this.top, t, n, r, o, i);
            if (s.contentDOM) {
                s.children = e.children, e.children = [];
                for (let e of s.children) e.parent = s
            }
            return e.destroy(), s
        }
        addNode(e, t, n, r, o) {
            let i = En.create(this.top, e, t, n, r, o);
            i.contentDOM && i.updateChildren(r, o + 1), this.top.children.splice(this.index++, 0, i), this.changed = !0
        }
        placeWidget(e, t, n) {
            let r = this.index < this.top.children.length ? this.top.children[this.index] : null;
            if (!r || !r.matchesWidget(e) || e != r.widget && r.widget.type.toDOM.parentNode) {
                let r = new Tn(this.top, e, t, n);
                this.top.children.splice(this.index++, 0, r), this.changed = !0
            } else this.index++
        }
        addTextblockHacks() {
            let e = this.top.children[this.index - 1],
                t = this.top;
            for (; e instanceof Sn;) t = e, e = t.children[t.children.length - 1];
            (!e || !(e instanceof On) || /\n$/.test(e.node.text) || this.view.requiresGeckoHackNode && /\s$/.test(e.node.text)) && ((Jt || Ut) && e && "false" == e.dom.contentEditable && this.addHackNode("IMG", t), this.addHackNode("BR", this.top))
        }
        addHackNode(e, t) {
            if (t == this.top && this.index < t.children.length && t.children[this.index].matchesHack(e)) this.index++;
            else {
                let n = document.createElement(e);
                "IMG" == e && (n.className = "ProseMirror-separator", n.alt = ""), "BR" == e && (n.className = "ProseMirror-trailingBreak");
                let r = new Dn(this.top, [], n, null);
                t != this.top ? t.children.push(r) : t.children.splice(this.index++, 0, r), this.changed = !0
            }
        }
        isLocked(e) {
            return this.lock && (e == this.lock || 1 == e.nodeType && e.contains(this.lock.parentNode))
        }
    }

    function jn(e, t) {
        return e.type.side - t.type.side
    }

    function $n(e, t, n, r, o) {
        let i = [];
        for (let s = 0, a = 0; s < e.length; s++) {
            let l = e[s],
                c = a,
                u = a += l.size;
            c >= n || u <= t ? i.push(l) : (c < t && i.push(l.slice(0, t - c, r)), o && (i.push(o), o = void 0), u > n && i.push(l.slice(n - c, l.size, r)))
        }
        return i
    }

    function _n(e, t = null) {
        let n = e.domSelectionRange(),
            r = e.state.doc;
        if (!n.focusNode) return null;
        let o = e.docView.nearestDesc(n.focusNode),
            i = o && 0 == o.size,
            s = e.docView.posFromDOM(n.focusNode, n.focusOffset, 1);
        if (s < 0) return null;
        let a, l, c = r.resolve(s);
        if (It(n)) {
            for (a = s; o && !o.node;) o = o.parent;
            let e = o.node;
            if (o && e.isAtom && at.isSelectable(e) && o.parent && (!e.isInline || ! function(e, t, n) {
                    for (let r = 0 == t, o = t == At(e); r || o;) {
                        if (e == n) return !0;
                        let t = Tt(e);
                        if (!(e = e.parentNode)) return !1;
                        r = r && 0 == t, o = o && t == At(e)
                    }
                }(n.focusNode, n.focusOffset, o.dom))) {
                let e = o.posBefore;
                l = new at(s == e ? c : r.resolve(e))
            }
        } else {
            if (n instanceof e.dom.ownerDocument.defaultView.Selection && n.rangeCount > 1) {
                let t = s,
                    o = s;
                for (let r = 0; r < n.rangeCount; r++) {
                    let i = n.getRangeAt(r);
                    t = Math.min(t, e.docView.posFromDOM(i.startContainer, i.startOffset, 1)), o = Math.max(o, e.docView.posFromDOM(i.endContainer, i.endOffset, -1))
                }
                if (t < 0) return null;
                [a, s] = o == e.state.selection.anchor ? [o, t] : [t, o], c = r.resolve(s)
            } else a = e.docView.posFromDOM(n.anchorNode, n.anchorOffset, 1);
            if (a < 0) return null
        }
        let u = r.resolve(a);
        return l || (l = Yn(e, u, c, "pointer" == t || e.state.selection.head < c.pos && !i ? 1 : -1)), l
    }

    function Un(e) {
        return e.editable ? e.hasFocus() : tr(e) && document.activeElement && document.activeElement.contains(e.dom)
    }

    function Wn(e, t = !1) {
        let n = e.state.selection;
        if (Zn(e, n), !Un(e)) return;
        let r = e.input.mouseDown;
        if (!t && Ut && r) {
            let t = e.domSelectionRange(),
                n = e.domObserver.currentSelection;
            if (t.anchorNode && n.anchorNode && Nt(t.anchorNode, t.anchorOffset, n.anchorNode, n.anchorOffset) && r.delaySelUpdate()) return void e.domObserver.setCurSelection()
        }
        if (e.domObserver.disconnectSelection(), e.cursorWrapper) ! function(e) {
            let t = e.domSelection();
            if (!t) return;
            let n = e.cursorWrapper.dom,
                r = "IMG" == n.nodeName;
            r ? t.collapse(n.parentNode, Tt(n) + 1) : t.collapse(n, 0), !r && !e.state.selection.visible && Vt && jt <= 11 && (n.disabled = !0, n.disabled = !1)
        }(e);
        else {
            let r, o, {
                anchor: i,
                head: s
            } = n;
            !Jn || n instanceof it || (n.$from.parent.inlineContent || (r = Kn(e, n.from)), n.empty || n.$from.parent.inlineContent || (o = Kn(e, n.to))), e.docView.setSelection(i, s, e, t), Jn && (r && Xn(r), o && Xn(o)), n.visible ? e.dom.classList.remove("ProseMirror-hideselection") : (e.dom.classList.add("ProseMirror-hideselection"), "onselectionchange" in document && function(e) {
                let t = e.dom.ownerDocument;
                t.removeEventListener("selectionchange", e.input.hideSelectionGuard);
                let n = e.domSelectionRange(),
                    r = n.anchorNode,
                    o = n.anchorOffset;
                t.addEventListener("selectionchange", e.input.hideSelectionGuard = () => {
                    n.anchorNode == r && n.anchorOffset == o || (t.removeEventListener("selectionchange", e.input.hideSelectionGuard), setTimeout(() => {
                        Un(e) && !e.state.selection.visible || e.dom.classList.remove("ProseMirror-hideselection")
                    }, 20))
                })
            }(e))
        }
        e.domObserver.setCurSelection(), e.domObserver.connectSelection()
    }
    const Jn = Jt || Ut && Wt < 63;

    function Kn(e, t) {
        let {
            node: n,
            offset: r
        } = e.docView.domFromPos(t, 0), o = r < n.childNodes.length ? n.childNodes[r] : null, i = r ? n.childNodes[r - 1] : null;
        if (Jt && o && "false" == o.contentEditable) return Gn(o);
        if (!(o && "false" != o.contentEditable || i && "false" != i.contentEditable)) {
            if (o) return Gn(o);
            if (i) return Gn(i)
        }
    }

    function Gn(e) {
        return e.contentEditable = "true", Jt && e.draggable && (e.draggable = !1, e.wasDraggable = !0), e
    }

    function Xn(e) {
        e.contentEditable = "false", e.wasDraggable && (e.draggable = !0, e.wasDraggable = null)
    }

    function Zn(e, t) {
        if (t instanceof at) {
            let n = e.docView.descAt(t.from);
            n != e.lastSelectedViewDesc && (Qn(e), n && n.selectNode(), e.lastSelectedViewDesc = n)
        } else Qn(e)
    }

    function Qn(e) {
        e.lastSelectedViewDesc && (e.lastSelectedViewDesc.parent && e.lastSelectedViewDesc.deselectNode(), e.lastSelectedViewDesc = void 0)
    }

    function Yn(e, t, n, r) {
        return e.someProp("createSelectionBetween", r => r(e, t, n)) || it.between(t, n, r)
    }

    function er(e) {
        return !(e.editable && !e.hasFocus()) && tr(e)
    }

    function tr(e) {
        let t = e.domSelectionRange();
        if (!t.anchorNode) return !1;
        try {
            return e.dom.contains(3 == t.anchorNode.nodeType ? t.anchorNode.parentNode : t.anchorNode) && (e.editable || e.dom.contains(3 == t.focusNode.nodeType ? t.focusNode.parentNode : t.focusNode))
        } catch (e) {
            return !1
        }
    }

    function nr(e, t) {
        let {
            $anchor: n,
            $head: r
        } = e.selection, o = t > 0 ? n.max(r) : n.min(r), i = o.parent.inlineContent ? o.depth ? e.doc.resolve(t > 0 ? o.after() : o.before()) : null : o;
        return i && tt.findFrom(i, t)
    }

    function rr(e, t) {
        return e.dispatch(e.state.tr.setSelection(t).scrollIntoView()), !0
    }

    function or(e, t, n) {
        let r = e.state.selection;
        if (!(r instanceof it)) {
            if (r instanceof at && r.node.isInline) return rr(e, new it(t > 0 ? r.$to : r.$from));
            {
                let n = nr(e.state, t);
                return !!n && rr(e, n)
            }
        }
        if (n.indexOf("s") > -1) {
            let {
                $head: n
            } = r, o = n.textOffset ? null : t < 0 ? n.nodeBefore : n.nodeAfter;
            if (!o || o.isText || !o.isLeaf) return !1;
            let i = e.state.doc.resolve(n.pos + o.nodeSize * (t < 0 ? -1 : 1));
            return rr(e, new it(r.$anchor, i))
        }
        if (!r.empty) return !1;
        if (e.endOfTextblock(t > 0 ? "forward" : "backward")) {
            let n = nr(e.state, t);
            return !!(n && n instanceof at) && rr(e, n)
        }
        if (!(Gt && n.indexOf("m") > -1)) {
            let n, o = r.$head,
                i = o.textOffset ? null : t < 0 ? o.nodeBefore : o.nodeAfter;
            if (!i || i.isText) return !1;
            let s = t < 0 ? o.pos - i.nodeSize : o.pos;
            return !!(i.isAtom || (n = e.docView.descAt(s)) && !n.contentDOM) && (at.isSelectable(i) ? rr(e, new at(t < 0 ? e.state.doc.resolve(o.pos - i.nodeSize) : o)) : !!Qt && rr(e, new it(e.state.doc.resolve(t < 0 ? s : s + i.nodeSize))))
        }
    }

    function ir(e) {
        return 3 == e.nodeType ? e.nodeValue.length : e.childNodes.length
    }

    function sr(e, t) {
        let n = e.pmViewDesc;
        return n && 0 == n.size && (t < 0 || e.nextSibling || "BR" != e.nodeName)
    }

    function ar(e, t) {
        return t < 0 ? function(e) {
            let t = e.domSelectionRange(),
                n = t.focusNode,
                r = t.focusOffset;
            if (!n) return;
            let o, i, s = !1;
            for ($t && 1 == n.nodeType && r < ir(n) && sr(n.childNodes[r], -1) && (s = !0);;)
                if (r > 0) {
                    if (1 != n.nodeType) break;
                    {
                        let e = n.childNodes[r - 1];
                        if (sr(e, -1)) o = n, i = --r;
                        else {
                            if (3 != e.nodeType) break;
                            n = e, r = n.nodeValue.length
                        }
                    }
                } else {
                    if (lr(n)) break;
                    {
                        let t = n.previousSibling;
                        for (; t && sr(t, -1);) o = n.parentNode, i = Tt(t), t = t.previousSibling;
                        if (t) n = t, r = ir(n);
                        else {
                            if (n = n.parentNode, n == e.dom) break;
                            r = 0
                        }
                    }
                } s ? cr(e, n, r) : o && cr(e, o, i)
        }(e) : function(e) {
            let t = e.domSelectionRange(),
                n = t.focusNode,
                r = t.focusOffset;
            if (!n) return;
            let o, i, s = ir(n);
            for (;;)
                if (r < s) {
                    if (1 != n.nodeType) break;
                    if (!sr(n.childNodes[r], 1)) break;
                    o = n, i = ++r
                } else {
                    if (lr(n)) break;
                    {
                        let t = n.nextSibling;
                        for (; t && sr(t, 1);) o = t.parentNode, i = Tt(t) + 1, t = t.nextSibling;
                        if (t) n = t, r = 0, s = ir(n);
                        else {
                            if (n = n.parentNode, n == e.dom) break;
                            r = s = 0
                        }
                    }
                } o && cr(e, o, i)
        }(e)
    }

    function lr(e) {
        let t = e.pmViewDesc;
        return t && t.node && t.node.isBlock
    }

    function cr(e, t, n) {
        if (3 != t.nodeType) {
            let e, r;
            (r = function(e, t) {
                for (; e && t == e.childNodes.length && !Lt(e);) t = Tt(e) + 1, e = e.parentNode;
                for (; e && t < e.childNodes.length;) {
                    let n = e.childNodes[t];
                    if (3 == n.nodeType) return n;
                    if (1 == n.nodeType && "false" == n.contentEditable) break;
                    e = n, t = 0
                }
            }(t, n)) ? (t = r, n = 0) : (e = function(e, t) {
                for (; e && !t && !Lt(e);) t = Tt(e), e = e.parentNode;
                for (; e && t;) {
                    let n = e.childNodes[t - 1];
                    if (3 == n.nodeType) return n;
                    if (1 == n.nodeType && "false" == n.contentEditable) break;
                    t = (e = n).childNodes.length
                }
            }(t, n)) && (t = e, n = e.nodeValue.length)
        }
        let r = e.domSelection();
        if (!r) return;
        if (It(r)) {
            let e = document.createRange();
            e.setEnd(t, n), e.setStart(t, n), r.removeAllRanges(), r.addRange(e)
        } else r.extend && r.extend(t, n);
        e.domObserver.setCurSelection();
        let {
            state: o
        } = e;
        setTimeout(() => {
            e.state == o && Wn(e)
        }, 50)
    }

    function ur(e, t) {
        let n = e.state.doc.resolve(t);
        if (!Ut && !Xt && n.parent.inlineContent) {
            let r = e.coordsAtPos(t);
            if (t > n.start()) {
                let n = e.coordsAtPos(t - 1),
                    o = (n.top + n.bottom) / 2;
                if (o > r.top && o < r.bottom && Math.abs(n.left - r.left) > 1) return n.left < r.left ? "ltr" : "rtl"
            }
            if (t < n.end()) {
                let n = e.coordsAtPos(t + 1),
                    o = (n.top + n.bottom) / 2;
                if (o > r.top && o < r.bottom && Math.abs(n.left - r.left) > 1) return n.left > r.left ? "ltr" : "rtl"
            }
        }
        return "rtl" == getComputedStyle(e.dom).direction ? "rtl" : "ltr"
    }

    function dr(e, t, n) {
        let r = e.state.selection;
        if (r instanceof it && !r.empty || n.indexOf("s") > -1) return !1;
        if (Gt && n.indexOf("m") > -1) return !1;
        let {
            $from: o,
            $to: i
        } = r;
        if (!o.parent.inlineContent || e.endOfTextblock(t < 0 ? "up" : "down")) {
            let n = nr(e.state, t);
            if (n && n instanceof at) return rr(e, n)
        }
        if (!o.parent.inlineContent) {
            let n = t < 0 ? o : i,
                s = r instanceof ct ? tt.near(n, t) : tt.findFrom(n, t);
            return !!s && rr(e, s)
        }
        return !1
    }

    function pr(e, t) {
        if (!(e.state.selection instanceof it)) return !0;
        let {
            $head: n,
            $anchor: r,
            empty: o
        } = e.state.selection;
        if (!n.sameParent(r)) return !0;
        if (!o) return !1;
        if (e.endOfTextblock(t > 0 ? "forward" : "backward")) return !0;
        let i = !n.textOffset && (t < 0 ? n.nodeBefore : n.nodeAfter);
        if (i && !i.isText) {
            let r = e.state.tr;
            return t < 0 ? r.delete(n.pos - i.nodeSize, n.pos) : r.delete(n.pos, n.pos + i.nodeSize), e.dispatch(r), !0
        }
        return !1
    }

    function hr(e, t, n) {
        e.domObserver.stop(), t.contentEditable = n, e.domObserver.start()
    }

    function fr(e, t) {
        e.someProp("transformCopied", n => {
            t = n(t, e)
        });
        let n = [],
            {
                content: r,
                openStart: o,
                openEnd: i
            } = t;
        for (; o > 1 && i > 1 && 1 == r.childCount && 1 == r.firstChild.childCount;) {
            o--, i--;
            let e = r.firstChild;
            n.push(e.type.name, e.attrs != e.type.defaultAttrs ? e.attrs : null), r = e.content
        }
        let s = e.someProp("clipboardSerializer") || ce.fromSchema(e.state.schema),
            a = Cr(),
            l = a.createElement("div");
        l.appendChild(s.serializeFragment(r, {
            document: a
        }));
        let c, u = l.firstChild,
            d = 0;
        for (; u && 1 == u.nodeType && (c = xr[u.nodeName.toLowerCase()]);) {
            for (let e = c.length - 1; e >= 0; e--) {
                let t = a.createElement(c[e]);
                for (; l.firstChild;) t.appendChild(l.firstChild);
                l.appendChild(t), d++
            }
            u = l.firstChild
        }
        return u && 1 == u.nodeType && u.setAttribute("data-pm-slice", `${o} ${i}${d?` -${d}`:""} ${JSON.stringify(n)}`), {
            dom: l,
            text: e.someProp("clipboardTextSerializer", n => n(t, e)) || t.content.textBetween(0, t.content.size, "\n\n"),
            slice: t
        }
    }

    function mr(e, t, n, r, o) {
        let i, s, a = o.parent.type.spec.code;
        if (!n && !t) return null;
        let c = !!t && (r || a || !n);
        if (c) {
            if (e.someProp("transformPastedText", n => {
                    t = n(t, a || r, e)
                }), a) return s = new f(l.from(e.state.schema.text(t.replace(/\r\n?/g, "\n"))), 0, 0), e.someProp("transformPasted", t => {
                s = t(s, e, !0)
            }), s;
            let n = e.someProp("clipboardTextParser", n => n(t, o, r, e));
            if (n) s = n;
            else {
                let n = o.marks(),
                    {
                        schema: r
                    } = e.state,
                    s = ce.fromSchema(r);
                i = document.createElement("div"), t.split(/(?:\r\n?|\n)+/).forEach(e => {
                    let t = i.appendChild(document.createElement("p"));
                    e && t.appendChild(s.serializeNode(r.text(e, n)))
                })
            }
        } else e.someProp("transformPastedHTML", t => {
            n = t(n, e)
        }), i = function(e) {
            let t = /^(\s*<meta [^>]*>)*/.exec(e);
            t && (e = e.slice(t[0].length));
            let n, r = Cr(),
                o = r.body,
                i = /<([a-z][^>\s]+)/i.exec(e);
            if ((n = i && xr[i[1].toLowerCase()]) && (e = n.map(e => "<" + e + ">").join("") + e + n.map(e => "</" + e + ">").reverse().join("")), o.innerHTML = function(e) {
                    let t = window.trustedTypes;
                    return t ? (Tr || (Tr = t.defaultPolicy || t.createPolicy("ProseMirrorClipboard", {
                        createHTML: e => e
                    })), Tr.createHTML(e)) : e
                }(e), n)
                for (let e = 0; e < n.length; e++) o = o.querySelector(n[e]) || o;
            for (let e = 0; e < r.styleSheets.length; e++) {
                let t = r.styleSheets[e];
                for (let e = 0; e < t.rules.length; e++) {
                    let n = t.rules[e];
                    if (n instanceof CSSStyleRule) {
                        let e = o.querySelectorAll(n.selectorText);
                        for (let t = 0; t < e.length; t++) e[t].style.cssText += n.style.cssText
                    }
                }
            }
            return o
        }(n), Qt && function(e) {
            let t = e.querySelectorAll(Ut ? "span:not([class]):not([style])" : "span.Apple-converted-space");
            for (let n = 0; n < t.length; n++) {
                let r = t[n];
                1 == r.childNodes.length && " " == r.textContent && r.parentNode && r.parentNode.replaceChild(e.ownerDocument.createTextNode(" "), r)
            }
        }(i);
        let u = i && i.querySelector("[data-pm-slice]"),
            d = u && /^(\d+) (\d+)(?: -(\d+))? (.*)/.exec(u.getAttribute("data-pm-slice") || "");
        if (d && d[3])
            for (let e = +d[3]; e > 0; e--) {
                let e = i.firstChild;
                for (; e && 1 != e.nodeType;) e = e.nextSibling;
                if (!e) break;
                i = e
            }
        if (!s) {
            let t = e.someProp("clipboardParser") || e.someProp("domParser") || Y.fromSchema(e.state.schema);
            s = t.parseSlice(i, {
                preserveWhitespace: !(!c && !d),
                context: o,
                ruleFromNode: e => "BR" != e.nodeName || e.nextSibling || !e.parentNode || gr.test(e.parentNode.nodeName) ? null : {
                    ignore: !0
                }
            })
        }
        if (d) s = function(e, t) {
            if (!e.size) return e;
            let n, r = e.content.firstChild.type.schema;
            try {
                n = JSON.parse(t)
            } catch (t) {
                return e
            }
            let {
                content: o,
                openStart: i,
                openEnd: s
            } = e;
            for (let e = n.length - 2; e >= 0; e -= 2) {
                let t = r.nodes[n[e]];
                if (!t || t.hasRequiredAttrs()) break;
                o = l.from(t.create(n[e + 1], o)), i++, s++
            }
            return new f(o, i, s)
        }(kr(s, +d[1], +d[2]), d[4]);
        else if (s = f.maxOpen(function(e, t) {
                if (e.childCount < 2) return e;
                for (let n = t.depth; n >= 0; n--) {
                    let r, o = t.node(n).contentMatchAt(t.index(n)),
                        i = [];
                    if (e.forEach(e => {
                            if (!i) return;
                            let t, n = o.findWrapping(e.type);
                            if (!n) return i = null;
                            if (t = i.length && r.length && yr(n, r, e, i[i.length - 1], 0)) i[i.length - 1] = t;
                            else {
                                i.length && (i[i.length - 1] = br(i[i.length - 1], r.length));
                                let t = vr(e, n);
                                i.push(t), o = o.matchType(t.type), r = n
                            }
                        }), i) return l.from(i)
                }
                return e
            }(s.content, o), !0), s.openStart || s.openEnd) {
            let e = 0,
                t = 0;
            for (let t = s.content.firstChild; e < s.openStart && !t.type.spec.isolating; e++, t = t.firstChild);
            for (let e = s.content.lastChild; t < s.openEnd && !e.type.spec.isolating; t++, e = e.lastChild);
            s = kr(s, e, t)
        }
        return e.someProp("transformPasted", t => {
            s = t(s, e, c)
        }), s
    }
    const gr = /^(a|abbr|acronym|b|cite|code|del|em|i|ins|kbd|label|output|q|ruby|s|samp|span|strong|sub|sup|time|u|tt|var)$/i;

    function vr(e, t, n = 0) {
        for (let r = t.length - 1; r >= n; r--) e = t[r].create(null, l.from(e));
        return e
    }

    function yr(e, t, n, r, o) {
        if (o < e.length && o < t.length && e[o] == t[o]) {
            let i = yr(e, t, n, r.lastChild, o + 1);
            if (i) return r.copy(r.content.replaceChild(r.childCount - 1, i));
            if (r.contentMatchAt(r.childCount).matchType(o == e.length - 1 ? n.type : e[o + 1])) return r.copy(r.content.append(l.from(vr(n, e, o + 1))))
        }
    }

    function br(e, t) {
        if (0 == t) return e;
        let n = e.content.replaceChild(e.childCount - 1, br(e.lastChild, t - 1)),
            r = e.contentMatchAt(e.childCount).fillBefore(l.empty, !0);
        return e.copy(n.append(r))
    }

    function wr(e, t, n, r, o, i) {
        let s = t < 0 ? e.firstChild : e.lastChild,
            a = s.content;
        return e.childCount > 1 && (i = 0), o < r - 1 && (a = wr(a, t, n, r, o + 1, i)), o >= n && (a = t < 0 ? s.contentMatchAt(0).fillBefore(a, i <= o).append(a) : a.append(s.contentMatchAt(s.childCount).fillBefore(l.empty, !0))), e.replaceChild(t < 0 ? 0 : e.childCount - 1, s.copy(a))
    }

    function kr(e, t, n) {
        return t < e.openStart && (e = new f(wr(e.content, -1, t, e.openStart, 0, e.openEnd), t, e.openEnd)), n < e.openEnd && (e = new f(wr(e.content, 1, n, e.openEnd, 0, 0), e.openStart, n)), e
    }
    const xr = {
        thead: ["table"],
        tbody: ["table"],
        tfoot: ["table"],
        caption: ["table"],
        colgroup: ["table"],
        col: ["table", "colgroup"],
        tr: ["table", "tbody"],
        td: ["table", "tbody", "tr"],
        th: ["table", "tbody", "tr"]
    };

    function Cr() {
        return document.implementation.createHTMLDocument("title")
    }
    let Tr = null;
    const Mr = {},
        Sr = {},
        Er = {
            touchstart: !0,
            touchmove: !0
        };
    class Nr {
        constructor() {
            this.shiftKey = !1, this.mouseDown = null, this.lastKeyCode = null, this.lastKeyCodeTime = 0, this.lastClick = {
                time: 0,
                x: 0,
                y: 0,
                type: "",
                button: 0
            }, this.lastSelectionOrigin = null, this.lastSelectionTime = 0, this.lastIOSEnter = 0, this.lastIOSEnterFallbackTimeout = -1, this.lastFocus = 0, this.lastTouch = 0, this.lastChromeDelete = 0, this.composing = !1, this.compositionNode = null, this.composingTimeout = -1, this.compositionNodes = [], this.compositionEndedAt = -2e8, this.compositionID = 1, this.badSafariComposition = !1, this.compositionPendingChanges = 0, this.domChangeCount = 0, this.eventHandlers = Object.create(null), this.hideSelectionGuard = null
        }
    }

    function Or(e, t) {
        e.input.lastSelectionOrigin = t, e.input.lastSelectionTime = Date.now()
    }

    function Dr(e) {
        e.someProp("handleDOMEvents", t => {
            for (let n in t) e.input.eventHandlers[n] || e.dom.addEventListener(n, e.input.eventHandlers[n] = t => Ar(e, t))
        })
    }

    function Ar(e, t) {
        return e.someProp("handleDOMEvents", n => {
            let r = n[t.type];
            return !!r && (r(e, t) || t.defaultPrevented)
        })
    }

    function Lr(e, t) {
        if (!t.bubbles) return !0;
        if (t.defaultPrevented) return !1;
        for (let n = t.target; n != e.dom; n = n.parentNode)
            if (!n || 11 == n.nodeType || n.pmViewDesc && n.pmViewDesc.stopEvent(t)) return !1;
        return !0
    }

    function Ir(e) {
        return {
            left: e.clientX,
            top: e.clientY
        }
    }

    function Rr(e, t, n, r, o) {
        if (-1 == r) return !1;
        let i = e.state.doc.resolve(r);
        for (let r = i.depth + 1; r > 0; r--)
            if (e.someProp(t, t => r > i.depth ? t(e, n, i.nodeAfter, i.before(r), o, !0) : t(e, n, i.node(r), i.before(r), o, !1))) return !0;
        return !1
    }

    function Pr(e, t, n) {
        if (e.focused || e.focus(), e.state.selection.eq(t)) return;
        let r = e.state.tr.setSelection(t);
        "pointer" == n && r.setMeta("pointer", !0), e.dispatch(r)
    }

    function Br(e, t, n, r) {
        return Rr(e, "handleDoubleClickOn", t, n, r) || e.someProp("handleDoubleClick", n => n(e, t, r))
    }

    function Fr(e, t, n, r) {
        return Rr(e, "handleTripleClickOn", t, n, r) || e.someProp("handleTripleClick", n => n(e, t, r)) || function(e, t, n) {
            if (0 != n.button) return !1;
            let r = Hr(e, t, !0),
                o = e.state.doc;
            return !!r && (Pr(e, r, "pointer"), r instanceof it && o.eq(e.state.doc) && (e.input.mouseDown = new $r(e, r)), !0)
        }(e, n, r)
    }

    function Hr(e, t, n) {
        let r = e.state.doc;
        if (-1 == t) return r.inlineContent ? it.create(r, 0, r.content.size) : null;
        let o = r.resolve(t);
        for (let e = o.depth + 1; e > 0; e--) {
            let t = e > o.depth ? o.nodeAfter : o.node(e),
                i = o.before(e);
            if (t.inlineContent) return it.create(r, i + 1, i + 1 + t.content.size);
            if (n && at.isSelectable(t)) return at.create(r, i)
        }
        return null
    }

    function zr(e) {
        return Kr(e)
    }
    Sr.keydown = (e, t) => {
        let n = t;
        if (e.input.shiftKey = 16 == n.keyCode || n.shiftKey, !_r(e) && (e.input.lastKeyCode = n.keyCode, e.input.lastKeyCodeTime = Date.now(), !Zt || !Ut || 13 != n.keyCode))
            if (229 != n.keyCode && e.domObserver.forceFlush(), !Kt || 13 != n.keyCode || n.ctrlKey || n.altKey || n.metaKey) e.someProp("handleKeyDown", t => t(e, n)) || function(e, t) {
                let n = t.keyCode,
                    r = function(e) {
                        let t = "";
                        return e.ctrlKey && (t += "c"), e.metaKey && (t += "m"), e.altKey && (t += "a"), e.shiftKey && (t += "s"), t
                    }(t);
                if (8 == n || Gt && 72 == n && "c" == r) return pr(e, -1) || ar(e, -1);
                if (46 == n && !t.shiftKey || Gt && 68 == n && "c" == r) return pr(e, 1) || ar(e, 1);
                if (13 == n || 27 == n) return !0;
                if (37 == n || Gt && 66 == n && "c" == r) {
                    let t = 37 == n ? "ltr" == ur(e, e.state.selection.from) ? -1 : 1 : -1;
                    return or(e, t, r) || ar(e, t)
                }
                if (39 == n || Gt && 70 == n && "c" == r) {
                    let t = 39 == n ? "ltr" == ur(e, e.state.selection.from) ? 1 : -1 : 1;
                    return or(e, t, r) || ar(e, t)
                }
                return 38 == n || Gt && 80 == n && "c" == r ? dr(e, -1, r) || ar(e, -1) : 40 == n || Gt && 78 == n && "c" == r ? function(e) {
                    if (!Jt || e.state.selection.$head.parentOffset > 0) return !1;
                    let {
                        focusNode: t,
                        focusOffset: n
                    } = e.domSelectionRange();
                    if (t && 1 == t.nodeType && 0 == n && t.firstChild && "false" == t.firstChild.contentEditable) {
                        let n = t.firstChild;
                        hr(e, n, "true"), setTimeout(() => hr(e, n, "false"), 20)
                    }
                    return !1
                }(e) || dr(e, 1, r) || ar(e, 1) : r == (Gt ? "m" : "c") && (66 == n || 73 == n || 89 == n || 90 == n)
            }(e, n) ? n.preventDefault() : Or(e, "key");
            else {
                let t = Date.now();
                e.input.lastIOSEnter = t, e.input.lastIOSEnterFallbackTimeout = setTimeout(() => {
                    e.input.lastIOSEnter == t && (e.someProp("handleKeyDown", t => t(e, Rt(13, "Enter"))), e.input.lastIOSEnter = 0)
                }, 200)
            }
    }, Sr.keyup = (e, t) => {
        16 == t.keyCode && (e.input.shiftKey = !1)
    }, Sr.keypress = (e, t) => {
        let n = t;
        if (_r(e) || !n.charCode || n.ctrlKey && !n.altKey || Gt && n.metaKey) return;
        if (e.someProp("handleKeyPress", t => t(e, n))) return void n.preventDefault();
        let r = e.state.selection;
        if (!(r instanceof it && r.$from.sameParent(r.$to))) {
            let t = String.fromCharCode(n.charCode),
                o = () => e.state.tr.insertText(t).scrollIntoView();
            /[\r\n]/.test(t) || e.someProp("handleTextInput", n => n(e, r.$from.pos, r.$to.pos, t, o)) || e.dispatch(o()), n.preventDefault()
        }
    };
    const qr = Gt ? "metaKey" : "ctrlKey";
    Mr.mousedown = (e, t) => {
        let n = t;
        e.input.shiftKey = n.shiftKey;
        let r = zr(e),
            o = Date.now(),
            i = "singleClick";
        o - e.input.lastClick.time < 500 && function(e, t) {
            let n = t.x - e.clientX,
                r = t.y - e.clientY;
            return n * n + r * r < 100
        }(n, e.input.lastClick) && !n[qr] && e.input.lastClick.button == n.button && ("singleClick" == e.input.lastClick.type ? i = "doubleClick" : "doubleClick" == e.input.lastClick.type && (i = "tripleClick")), e.input.lastClick = {
            time: o,
            x: n.clientX,
            y: n.clientY,
            type: i,
            button: n.button
        }, e.input.mouseDown && e.input.mouseDown.done();
        let s = e.posAtCoords(Ir(n));
        s && ("singleClick" == i ? e.input.mouseDown = new jr(e, s, n, !!r) : ("doubleClick" == i ? Br : Fr)(e, s.pos, s.inside, n) ? n.preventDefault() : Or(e, "pointer"))
    };
    class Vr {
        constructor(e) {
            this.view = e, this.mightDrag = null, e.root.addEventListener("mouseup", this.up = this.up.bind(this)), e.root.addEventListener("mousemove", this.move = this.move.bind(this))
        }
        up(e) {
            this.done()
        }
        move(e) {
            0 == e.buttons && this.done()
        }
        done() {
            this.view.root.removeEventListener("mouseup", this.up), this.view.root.removeEventListener("mousemove", this.move), this.view.input.mouseDown == this && (this.view.input.mouseDown = null)
        }
        delaySelUpdate() {
            return !1
        }
    }
    class jr extends Vr {
        constructor(e, t, n, r) {
            let o, i;
            if (super(e), this.pos = t, this.event = n, this.flushed = r, this.delayedSelectionSync = !1, this.startDoc = e.state.doc, this.selectNode = !!n[qr], this.allowDefault = n.shiftKey, t.inside > -1) o = e.state.doc.nodeAt(t.inside), i = t.inside;
            else {
                let n = e.state.doc.resolve(t.pos);
                o = n.parent, i = n.depth ? n.before() : 0
            }
            const s = r ? null : n.target,
                a = s ? e.docView.nearestDesc(s, !0) : null;
            this.target = a && 1 == a.nodeDOM.nodeType ? a.nodeDOM : null;
            let {
                selection: l
            } = e.state;
            0 == n.button && (o.type.spec.draggable && !1 !== o.type.spec.selectable || l instanceof at && l.from <= i && l.to > i) && (this.mightDrag = {
                node: o,
                pos: i,
                addAttr: !(!this.target || this.target.draggable),
                setUneditable: !(!this.target || !$t || this.target.hasAttribute("contentEditable"))
            }), this.target && this.mightDrag && (this.mightDrag.addAttr || this.mightDrag.setUneditable) && (this.view.domObserver.stop(), this.mightDrag.addAttr && (this.target.draggable = !0), this.mightDrag.setUneditable && setTimeout(() => {
                this.view.input.mouseDown == this && this.target.setAttribute("contentEditable", "false")
            }, 20), this.view.domObserver.start()), Or(e, "pointer")
        }
        done() {
            super.done(), this.mightDrag && this.target && (this.view.domObserver.stop(), this.mightDrag.addAttr && this.target.removeAttribute("draggable"), this.mightDrag.setUneditable && this.target.removeAttribute("contentEditable"), this.view.domObserver.start()), this.delayedSelectionSync && setTimeout(() => {
                this.view.isDestroyed || Wn(this.view)
            })
        }
        up(e) {
            if (this.done(), !this.view.dom.contains(e.target)) return;
            let t = this.pos;
            this.view.state.doc != this.startDoc && (t = this.view.posAtCoords(Ir(e))), this.updateAllowDefault(e), this.allowDefault || !t ? Or(this.view, "pointer") : function(e, t, n, r, o) {
                return Rr(e, "handleClickOn", t, n, r) || e.someProp("handleClick", n => n(e, t, r)) || (o ? function(e, t) {
                    if (-1 == t) return !1;
                    let n, r, o = e.state.selection;
                    o instanceof at && (n = o.node);
                    let i = e.state.doc.resolve(t);
                    for (let e = i.depth + 1; e > 0; e--) {
                        let t = e > i.depth ? i.nodeAfter : i.node(e);
                        if (at.isSelectable(t)) {
                            r = n && o.$from.depth > 0 && e >= o.$from.depth && i.before(o.$from.depth + 1) == o.$from.pos ? i.before(o.$from.depth) : i.before(e);
                            break
                        }
                    }
                    return null != r && (Pr(e, at.create(e.state.doc, r), "pointer"), !0)
                }(e, n) : function(e, t) {
                    if (-1 == t) return !1;
                    let n = e.state.doc.resolve(t),
                        r = n.nodeAfter;
                    return !!(r && r.isAtom && at.isSelectable(r)) && (Pr(e, new at(n), "pointer"), !0)
                }(e, n))
            }(this.view, t.pos, t.inside, e, this.selectNode) ? e.preventDefault() : 0 == e.button && (this.flushed || Jt && this.mightDrag && !this.mightDrag.node.isAtom || Ut && !this.view.state.selection.visible && Math.min(Math.abs(t.pos - this.view.state.selection.from), Math.abs(t.pos - this.view.state.selection.to)) <= 2) ? (Pr(this.view, tt.near(this.view.state.doc.resolve(t.pos)), "pointer"), e.preventDefault()) : Or(this.view, "pointer")
        }
        move(e) {
            this.updateAllowDefault(e), Or(this.view, "pointer"), super.move(e)
        }
        updateAllowDefault(e) {
            !this.allowDefault && (Math.abs(this.event.x - e.clientX) > 4 || Math.abs(this.event.y - e.clientY) > 4) && (this.allowDefault = !0)
        }
        delaySelUpdate() {
            return !!this.allowDefault && (this.delayedSelectionSync = !0, !0)
        }
    }
    class $r extends Vr {
        constructor(e, t) {
            super(e), this.startSelection = t, this.startDoc = e.state.doc
        }
        move(e) {
            if (0 == e.buttons || this.view.isDestroyed || !this.view.state.doc.eq(this.startDoc)) return void this.done();
            e.preventDefault(), Or(this.view, "pointer");
            let t = this.view.posAtCoords(Ir(e)),
                n = t && Hr(this.view, t.inside, !1);
            if (!n) return;
            let {
                doc: r
            } = this.view.state, o = this.startSelection, [i, s] = n.from < o.from ? [o.to, n.from] : [o.from, n.to];
            Pr(this.view, it.create(r, i, s), "pointer")
        }
    }

    function _r(e, t) {
        return !!e.composing || !!(Jt && Math.abs(Date.now() - e.input.compositionEndedAt) < 500) && (e.input.compositionEndedAt = -2e8, !0)
    }
    Mr.touchstart = e => {
        e.input.lastTouch = Date.now(), zr(e), Or(e, "pointer")
    }, Mr.touchmove = e => {
        e.input.lastTouch = Date.now(), Or(e, "pointer")
    }, Mr.contextmenu = e => zr(e);
    const Ur = Zt ? 5e3 : -1;

    function Wr(e, t) {
        clearTimeout(e.input.composingTimeout), t > -1 && (e.input.composingTimeout = setTimeout(() => Kr(e), t))
    }

    function Jr(e) {
        for (e.composing && (e.input.composing = !1, e.input.compositionEndedAt = Date.now()); e.input.compositionNodes.length > 0;) e.input.compositionNodes.pop().markParentsDirty()
    }

    function Kr(e, t = !1) {
        if (!(Zt && e.domObserver.flushingSoon >= 0)) {
            if (e.domObserver.forceFlush(), Jr(e), t || e.docView && e.docView.dirty) {
                let n = _n(e),
                    r = e.state.selection;
                return n && !n.eq(r) ? e.dispatch(e.state.tr.setSelection(n)) : !e.markCursor && !t || r.$from.node(r.$from.sharedDepth(r.to)).inlineContent ? e.updateState(e.state) : e.dispatch(e.state.tr.deleteSelection()), !0
            }
            return !1
        }
    }
    Sr.compositionstart = Sr.compositionupdate = e => {
        if (!e.composing) {
            e.domObserver.flush();
            let {
                state: t
            } = e, n = t.selection.$to;
            if (t.selection instanceof it && (t.storedMarks || !n.textOffset && n.parentOffset && n.nodeBefore.marks.some(e => !1 === e.type.spec.inclusive) || Ut && Xt && function(e) {
                    let {
                        focusNode: t,
                        focusOffset: n
                    } = e.domSelectionRange();
                    if (!t || 1 != t.nodeType || n >= t.childNodes.length) return !1;
                    let r = t.childNodes[n];
                    return 1 == r.nodeType && "false" == r.contentEditable
                }(e))) e.markCursor = e.state.storedMarks || n.marks(), Kr(e, !0), e.markCursor = null;
            else if (Kr(e, !t.selection.empty), $t && t.selection.empty && n.parentOffset && !n.textOffset && n.nodeBefore.marks.length) {
                let t = e.domSelectionRange();
                for (let n = t.focusNode, r = t.focusOffset; n && 1 == n.nodeType && 0 != r;) {
                    let t = r < 0 ? n.lastChild : n.childNodes[r - 1];
                    if (!t) break;
                    if (3 == t.nodeType) {
                        let n = e.domSelection();
                        n && n.collapse(t, t.nodeValue.length);
                        break
                    }
                    n = t, r = -1
                }
            }
            e.input.composing = !0
        }
        Wr(e, Ur)
    }, Sr.compositionend = (e, t) => {
        e.composing && (e.input.composing = !1, e.input.compositionEndedAt = Date.now(), e.input.compositionPendingChanges = e.domObserver.pendingRecords().length ? e.input.compositionID : 0, e.input.compositionNode = null, e.input.badSafariComposition ? e.domObserver.forceFlush() : e.input.compositionPendingChanges && Promise.resolve().then(() => e.domObserver.flush()), e.input.compositionID++, Wr(e, 20))
    };
    const Gr = Vt && jt < 15 || Kt && Yt < 604;

    function Xr(e, t, n, r, o) {
        let i = mr(e, t, n, r, e.state.selection.$from);
        if (e.someProp("handlePaste", t => t(e, o, i || f.empty))) return !0;
        if (!i) return !1;
        let s = function(e) {
                return 0 == e.openStart && 0 == e.openEnd && 1 == e.content.childCount ? e.content.firstChild : null
            }(i),
            a = s ? e.state.tr.replaceSelectionWith(s, r) : e.state.tr.replaceSelection(i);
        return e.dispatch(a.scrollIntoView().setMeta("paste", !0).setMeta("uiEvent", "paste")), !0
    }

    function Zr(e) {
        let t = e.getData("text/plain") || e.getData("Text");
        if (t) return t;
        let n = e.getData("text/uri-list");
        return n ? n.replace(/\r?\n/g, " ") : ""
    }
    Mr.copy = Sr.cut = (e, t) => {
        let n = t,
            r = e.state.selection,
            o = "cut" == n.type;
        if (r.empty) return;
        let i = Gr ? null : n.clipboardData,
            s = r.content(),
            {
                dom: a,
                text: l
            } = fr(e, s);
        i ? (n.preventDefault(), i.clearData(), i.setData("text/html", a.innerHTML), i.setData("text/plain", l)) : function(e, t) {
            if (!e.dom.parentNode) return;
            let n = e.dom.parentNode.appendChild(document.createElement("div"));
            n.appendChild(t), n.style.cssText = "position: fixed; left: -10000px; top: 10px";
            let r = getSelection(),
                o = document.createRange();
            o.selectNodeContents(t), e.dom.blur(), r.removeAllRanges(), r.addRange(o), setTimeout(() => {
                n.parentNode && n.parentNode.removeChild(n), e.focus()
            }, 50)
        }(e, a), o && e.dispatch(e.state.tr.deleteSelection().scrollIntoView().setMeta("uiEvent", "cut"))
    }, Sr.paste = (e, t) => {
        let n = t;
        if (e.composing && !Zt) return;
        let r = Gr ? null : n.clipboardData,
            o = e.input.shiftKey && 45 != e.input.lastKeyCode;
        r && Xr(e, Zr(r), r.getData("text/html"), o, n) ? n.preventDefault() : function(e, t) {
            if (!e.dom.parentNode) return;
            let n = e.input.shiftKey || e.state.selection.$from.parent.type.spec.code,
                r = e.dom.parentNode.appendChild(document.createElement(n ? "textarea" : "div"));
            n || (r.contentEditable = "true"), r.style.cssText = "position: fixed; left: -10000px; top: 10px", r.focus();
            let o = e.input.shiftKey && 45 != e.input.lastKeyCode;
            setTimeout(() => {
                e.focus(), r.parentNode && r.parentNode.removeChild(r), n ? Xr(e, r.value, null, o, t) : Xr(e, r.textContent, r.innerHTML, o, t)
            }, 50)
        }(e, n)
    };
    class Qr {
        constructor(e, t, n) {
            this.slice = e, this.move = t, this.node = n
        }
    }
    const Yr = Gt ? "altKey" : "ctrlKey";

    function eo(e, t) {
        let n;
        return e.someProp("dragCopies", e => {
            n = n || e(t)
        }), null != n ? !n : !t[Yr]
    }
    Mr.dragstart = (e, t) => {
        let n = t,
            r = e.input.mouseDown;
        if (r && r.done(), !n.dataTransfer) return;
        let o, i = e.state.selection,
            s = i.empty ? null : e.posAtCoords(Ir(n));
        if (s && s.pos >= i.from && s.pos <= (i instanceof at ? i.to - 1 : i.to));
        else if (r && r.mightDrag) o = at.create(e.state.doc, r.mightDrag.pos);
        else if (n.target && 1 == n.target.nodeType) {
            let t = e.docView.nearestDesc(n.target, !0);
            t && t.node.type.spec.draggable && t != e.docView && (o = at.create(e.state.doc, t.posBefore))
        }
        let a = (o || e.state.selection).content(),
            {
                dom: l,
                text: c,
                slice: u
            } = fr(e, a);
        (!n.dataTransfer.files.length || !Ut || Wt > 120) && n.dataTransfer.clearData(), n.dataTransfer.setData(Gr ? "Text" : "text/html", l.innerHTML), n.dataTransfer.effectAllowed = "copyMove", Gr || n.dataTransfer.setData("text/plain", c), e.dragging = new Qr(u, eo(e, n), o)
    }, Mr.dragend = e => {
        let t = e.dragging;
        window.setTimeout(() => {
            e.dragging == t && (e.dragging = null)
        }, 50)
    }, Sr.dragover = Sr.dragenter = (e, t) => t.preventDefault(), Sr.drop = (e, t) => {
        try {
            ! function(e, t, n) {
                if (!t.dataTransfer) return;
                let r = e.posAtCoords(Ir(t));
                if (!r) return;
                let o = e.state.doc.resolve(r.pos),
                    i = n && n.slice;
                i ? e.someProp("transformPasted", t => {
                    i = t(i, e, !1)
                }) : i = mr(e, Zr(t.dataTransfer), Gr ? null : t.dataTransfer.getData("text/html"), !1, o);
                let s = !(!n || !eo(e, t));
                if (e.someProp("handleDrop", n => n(e, t, i || f.empty, s))) return void t.preventDefault();
                if (!i) return;
                t.preventDefault();
                let a = i ? function(e, t, n) {
                    let r = e.resolve(t);
                    if (!n.content.size) return t;
                    let o = n.content;
                    for (let e = 0; e < n.openStart; e++) o = o.firstChild.content;
                    for (let e = 1; e <= (0 == n.openStart && n.size ? 2 : 1); e++)
                        for (let t = r.depth; t >= 0; t--) {
                            let n = t == r.depth ? 0 : r.pos <= (r.start(t + 1) + r.end(t + 1)) / 2 ? -1 : 1,
                                i = r.index(t) + (n > 0 ? 1 : 0),
                                s = r.node(t),
                                a = !1;
                            if (1 == e) a = s.canReplace(i, i, o);
                            else {
                                let e = s.contentMatchAt(i).findWrapping(o.firstChild.type);
                                a = e && s.canReplaceWith(i, i, e[0])
                            }
                            if (a) return 0 == n ? r.pos : n < 0 ? r.before(t + 1) : r.after(t + 1)
                        }
                    return null
                }(e.state.doc, o.pos, i) : o.pos;
                null == a && (a = o.pos);
                let l = e.state.tr;
                if (s) {
                    let {
                        node: e
                    } = n;
                    e ? e.replace(l) : l.deleteSelection()
                }
                let c = l.mapping.map(a),
                    u = 0 == i.openStart && 0 == i.openEnd && 1 == i.content.childCount,
                    d = l.doc;
                if (u ? l.replaceRangeWith(c, c, i.content.firstChild) : l.replaceRange(c, c, i), l.doc.eq(d)) return;
                let p = l.doc.resolve(c);
                if (u && at.isSelectable(i.content.firstChild) && p.nodeAfter && p.nodeAfter.sameMarkup(i.content.firstChild)) l.setSelection(new at(p));
                else {
                    let t = l.mapping.map(a);
                    l.mapping.maps[l.mapping.maps.length - 1].forEach((e, n, r, o) => t = o), l.setSelection(Yn(e, p, l.doc.resolve(t)))
                }
                e.focus(), e.dispatch(l.setMeta("uiEvent", "drop"))
            }(e, t, e.dragging)
        } finally {
            e.dragging = null
        }
    }, Mr.focus = e => {
        e.input.lastFocus = Date.now(), e.focused || (e.domObserver.stop(), e.dom.classList.add("ProseMirror-focused"), e.domObserver.start(), e.focused = !0, setTimeout(() => {
            e.docView && e.hasFocus() && !e.domObserver.currentSelection.eq(e.domSelectionRange()) && Wn(e)
        }, 20))
    }, Mr.blur = (e, t) => {
        let n = t;
        e.focused && (e.domObserver.stop(), e.dom.classList.remove("ProseMirror-focused"), e.domObserver.start(), n.relatedTarget && e.dom.contains(n.relatedTarget) && e.domObserver.currentSelection.clear(), e.focused = !1)
    }, Mr.beforeinput = (e, t) => {
        if (Zt && "deleteContentBackward" == t.inputType) {
            e.domObserver.flushSoon();
            let {
                domChangeCount: t
            } = e.input;
            setTimeout(() => {
                if (e.input.domChangeCount != t) return;
                if (e.dom.blur(), e.focus(), e.someProp("handleKeyDown", t => t(e, Rt(8, "Backspace")))) return;
                let {
                    $cursor: n
                } = e.state.selection;
                n && n.pos > 0 && e.dispatch(e.state.tr.delete(n.pos - 1, n.pos).scrollIntoView())
            }, 50)
        }
    };
    for (let e in Sr) Mr[e] = Sr[e];

    function to(e, t) {
        if (e == t) return !0;
        for (let n in e)
            if (e[n] !== t[n]) return !1;
        for (let n in t)
            if (!(n in e)) return !1;
        return !0
    }
    class no {
        constructor(e, t) {
            this.toDOM = e, this.spec = t || ao, this.side = this.spec.side || 0
        }
        map(e, t, n, r) {
            let {
                pos: o,
                deleted: i
            } = e.mapResult(t.from + r, this.side < 0 ? -1 : 1);
            return i ? null : new io(o - n, o - n, this)
        }
        valid() {
            return !0
        }
        eq(e) {
            return this == e || e instanceof no && (this.spec.key && this.spec.key == e.spec.key || this.toDOM == e.toDOM && to(this.spec, e.spec))
        }
        destroy(e) {
            this.spec.destroy && this.spec.destroy(e)
        }
    }
    class ro {
        constructor(e, t) {
            this.attrs = e, this.spec = t || ao
        }
        map(e, t, n, r) {
            let o = e.map(t.from + r, this.spec.inclusiveStart ? -1 : 1) - n,
                i = e.map(t.to + r, this.spec.inclusiveEnd ? 1 : -1) - n;
            return o >= i ? null : new io(o, i, this)
        }
        valid(e, t) {
            return t.from < t.to
        }
        eq(e) {
            return this == e || e instanceof ro && to(this.attrs, e.attrs) && to(this.spec, e.spec)
        }
        static is(e) {
            return e.type instanceof ro
        }
        destroy() {}
    }
    class oo {
        constructor(e, t) {
            this.attrs = e, this.spec = t || ao
        }
        map(e, t, n, r) {
            let o = e.mapResult(t.from + r, 1);
            if (o.deleted) return null;
            let i = e.mapResult(t.to + r, -1);
            return i.deleted || i.pos <= o.pos ? null : new io(o.pos - n, i.pos - n, this)
        }
        valid(e, t) {
            let n, {
                index: r,
                offset: o
            } = e.content.findIndex(t.from);
            return o == t.from && !(n = e.child(r)).isText && o + n.nodeSize == t.to
        }
        eq(e) {
            return this == e || e instanceof oo && to(this.attrs, e.attrs) && to(this.spec, e.spec)
        }
        destroy() {}
    }
    class io {
        constructor(e, t, n) {
            this.from = e, this.to = t, this.type = n
        }
        copy(e, t) {
            return new io(e, t, this.type)
        }
        eq(e, t = 0) {
            return this.type.eq(e.type) && this.from + t == e.from && this.to + t == e.to
        }
        map(e, t, n) {
            return this.type.map(e, this, t, n)
        }
        static widget(e, t, n) {
            return new io(e, e, new no(t, n))
        }
        static inline(e, t, n, r) {
            return new io(e, t, new ro(n, r))
        }
        static node(e, t, n, r) {
            return new io(e, t, new oo(n, r))
        }
        get spec() {
            return this.type.spec
        }
        get inline() {
            return this.type instanceof ro
        }
        get widget() {
            return this.type instanceof no
        }
    }
    const so = [],
        ao = {};
    class lo {
        constructor(e, t) {
            this.local = e.length ? e : so, this.children = t.length ? t : so
        }
        static create(e, t) {
            return t.length ? mo(t, e, 0, ao) : co
        }
        find(e, t, n) {
            let r = [];
            return this.findInner(e ?? 0, t ?? 1e9, r, 0, n), r
        }
        findInner(e, t, n, r, o) {
            for (let i = 0; i < this.local.length; i++) {
                let s = this.local[i];
                s.from <= t && s.to >= e && (!o || o(s.spec)) && n.push(s.copy(s.from + r, s.to + r))
            }
            for (let i = 0; i < this.children.length; i += 3)
                if (this.children[i] < t && this.children[i + 1] > e) {
                    let s = this.children[i] + 1;
                    this.children[i + 2].findInner(e - s, t - s, n, r + s, o)
                }
        }
        map(e, t, n) {
            return this == co || 0 == e.maps.length ? this : this.mapInner(e, t, 0, 0, n || ao)
        }
        mapInner(e, t, n, r, o) {
            let i;
            for (let s = 0; s < this.local.length; s++) {
                let a = this.local[s].map(e, n, r);
                a && a.type.valid(t, a) ? (i || (i = [])).push(a) : o.onRemove && o.onRemove(this.local[s].spec)
            }
            return this.children.length ? function(e, t, n, r, o, i, s) {
                let a = e.slice();
                for (let e = 0, t = i; e < n.maps.length; e++) {
                    let r = 0;
                    n.maps[e].forEach((e, n, o, i) => {
                        let s = i - o - (n - e);
                        for (let o = 0; o < a.length; o += 3) {
                            let i = a[o + 1];
                            if (i < 0 || e > i + t - r) continue;
                            let l = a[o] + t - r;
                            n >= l ? a[o + 1] = e <= l ? -2 : -1 : e >= t && s && (a[o] += s, a[o + 1] += s)
                        }
                        r += s
                    }), t = n.maps[e].map(t, -1)
                }
                let l = !1;
                for (let t = 0; t < a.length; t += 3)
                    if (a[t + 1] < 0) {
                        if (-2 == a[t + 1]) {
                            l = !0, a[t + 1] = -1;
                            continue
                        }
                        let c = n.map(e[t] + i),
                            u = c - o;
                        if (u < 0 || u >= r.content.size) {
                            l = !0;
                            continue
                        }
                        let d = n.map(e[t + 1] + i, -1) - o,
                            {
                                index: p,
                                offset: h
                            } = r.content.findIndex(u),
                            f = r.maybeChild(p);
                        if (f && h == u && h + f.nodeSize == d) {
                            let r = a[t + 2].mapInner(n, f, c + 1, e[t] + i + 1, s);
                            r != co ? (a[t] = u, a[t + 1] = d, a[t + 2] = r) : (a[t + 1] = -2, l = !0)
                        } else l = !0
                    } if (l) {
                    let l = function(e, t, n, r, o, i, s) {
                            function a(e, t) {
                                for (let i = 0; i < e.local.length; i++) {
                                    let a = e.local[i].map(r, o, t);
                                    a ? n.push(a) : s.onRemove && s.onRemove(e.local[i].spec)
                                }
                                for (let n = 0; n < e.children.length; n += 3) a(e.children[n + 2], e.children[n] + t + 1)
                            }
                            for (let n = 0; n < e.length; n += 3) - 1 == e[n + 1] && a(e[n + 2], t[n] + i + 1);
                            return n
                        }(a, e, t, n, o, i, s),
                        c = mo(l, r, 0, s);
                    t = c.local;
                    for (let e = 0; e < a.length; e += 3) a[e + 1] < 0 && (a.splice(e, 3), e -= 3);
                    for (let e = 0, t = 0; e < c.children.length; e += 3) {
                        let n = c.children[e];
                        for (; t < a.length && a[t] < n;) t += 3;
                        a.splice(t, 0, c.children[e], c.children[e + 1], c.children[e + 2])
                    }
                }
                return new lo(t.sort(go), a)
            }(this.children, i || [], e, t, n, r, o) : i ? new lo(i.sort(go), so) : co
        }
        add(e, t) {
            return t.length ? this == co ? lo.create(e, t) : this.addInner(e, t, 0) : this
        }
        addInner(e, t, n) {
            let r, o = 0;
            e.forEach((e, i) => {
                let s, a = i + n;
                if (s = ho(t, e, a)) {
                    for (r || (r = this.children.slice()); o < r.length && r[o] < i;) o += 3;
                    r[o] == i ? r[o + 2] = r[o + 2].addInner(e, s, a + 1) : r.splice(o, 0, i, i + e.nodeSize, mo(s, e, a + 1, ao)), o += 3
                }
            });
            let i = po(o ? fo(t) : t, -n);
            for (let t = 0; t < i.length; t++) i[t].type.valid(e, i[t]) || i.splice(t--, 1);
            return new lo(i.length ? this.local.concat(i).sort(go) : this.local, r || this.children)
        }
        remove(e) {
            return 0 == e.length || this == co ? this : this.removeInner(e, 0)
        }
        removeInner(e, t) {
            let n = this.children,
                r = this.local;
            for (let r = 0; r < n.length; r += 3) {
                let o, i = n[r] + t,
                    s = n[r + 1] + t;
                for (let t, n = 0; n < e.length; n++)(t = e[n]) && t.from > i && t.to < s && (e[n] = null, (o || (o = [])).push(t));
                if (!o) continue;
                n == this.children && (n = this.children.slice());
                let a = n[r + 2].removeInner(o, i + 1);
                a != co ? n[r + 2] = a : (n.splice(r, 3), r -= 3)
            }
            if (r.length)
                for (let n, o = 0; o < e.length; o++)
                    if (n = e[o])
                        for (let e = 0; e < r.length; e++) r[e].eq(n, t) && (r == this.local && (r = this.local.slice()), r.splice(e--, 1));
            return n == this.children && r == this.local ? this : r.length || n.length ? new lo(r, n) : co
        }
        forChild(e, t) {
            if (this == co) return this;
            if (t.isLeaf) return lo.empty;
            let n, r;
            for (let t = 0; t < this.children.length; t += 3)
                if (this.children[t] >= e) {
                    this.children[t] == e && (n = this.children[t + 2]);
                    break
                } let o = e + 1,
                i = o + t.content.size;
            for (let e = 0; e < this.local.length; e++) {
                let t = this.local[e];
                if (t.from < i && t.to > o && t.type instanceof ro) {
                    let e = Math.max(o, t.from) - o,
                        n = Math.min(i, t.to) - o;
                    e < n && (r || (r = [])).push(t.copy(e, n))
                }
            }
            if (r) {
                let e = new lo(r.sort(go), so);
                return n ? new uo([e, n]) : e
            }
            return n || co
        }
        eq(e) {
            if (this == e) return !0;
            if (!(e instanceof lo) || this.local.length != e.local.length || this.children.length != e.children.length) return !1;
            for (let t = 0; t < this.local.length; t++)
                if (!this.local[t].eq(e.local[t])) return !1;
            for (let t = 0; t < this.children.length; t += 3)
                if (this.children[t] != e.children[t] || this.children[t + 1] != e.children[t + 1] || !this.children[t + 2].eq(e.children[t + 2])) return !1;
            return !0
        }
        locals(e) {
            return vo(this.localsInner(e))
        }
        localsInner(e) {
            if (this == co) return so;
            if (e.inlineContent || !this.local.some(ro.is)) return this.local;
            let t = [];
            for (let e = 0; e < this.local.length; e++) this.local[e].type instanceof ro || t.push(this.local[e]);
            return t
        }
        forEachSet(e) {
            e(this)
        }
    }
    lo.empty = new lo([], []), lo.removeOverlap = vo;
    const co = lo.empty;
    class uo {
        constructor(e) {
            this.members = e
        }
        map(e, t) {
            const n = this.members.map(n => n.map(e, t, ao));
            return uo.from(n)
        }
        forChild(e, t) {
            if (t.isLeaf) return lo.empty;
            let n = [];
            for (let r = 0; r < this.members.length; r++) {
                let o = this.members[r].forChild(e, t);
                o != co && (o instanceof uo ? n = n.concat(o.members) : n.push(o))
            }
            return uo.from(n)
        }
        eq(e) {
            if (!(e instanceof uo) || e.members.length != this.members.length) return !1;
            for (let t = 0; t < this.members.length; t++)
                if (!this.members[t].eq(e.members[t])) return !1;
            return !0
        }
        locals(e) {
            let t, n = !0;
            for (let r = 0; r < this.members.length; r++) {
                let o = this.members[r].localsInner(e);
                if (o.length)
                    if (t) {
                        n && (t = t.slice(), n = !1);
                        for (let e = 0; e < o.length; e++) t.push(o[e])
                    } else t = o
            }
            return t ? vo(n ? t : t.sort(go)) : so
        }
        static from(e) {
            switch (e.length) {
                case 0:
                    return co;
                case 1:
                    return e[0];
                default:
                    return new uo(e.every(e => e instanceof lo) ? e : e.reduce((e, t) => e.concat(t instanceof lo ? t : t.members), []))
            }
        }
        forEachSet(e) {
            for (let t = 0; t < this.members.length; t++) this.members[t].forEachSet(e)
        }
    }

    function po(e, t) {
        if (!t || !e.length) return e;
        let n = [];
        for (let r = 0; r < e.length; r++) {
            let o = e[r];
            n.push(new io(o.from + t, o.to + t, o.type))
        }
        return n
    }

    function ho(e, t, n) {
        if (t.isLeaf) return null;
        let r = n + t.nodeSize,
            o = null;
        for (let t, i = 0; i < e.length; i++)(t = e[i]) && t.from > n && t.to < r && ((o || (o = [])).push(t), e[i] = null);
        return o
    }

    function fo(e) {
        let t = [];
        for (let n = 0; n < e.length; n++) null != e[n] && t.push(e[n]);
        return t
    }

    function mo(e, t, n, r) {
        let o = [],
            i = !1;
        t.forEach((t, s) => {
            let a = ho(e, t, s + n);
            if (a) {
                i = !0;
                let e = mo(a, t, n + s + 1, r);
                e != co && o.push(s, s + t.nodeSize, e)
            }
        });
        let s = po(i ? fo(e) : e, -n).sort(go);
        for (let e = 0; e < s.length; e++) s[e].type.valid(t, s[e]) || (r.onRemove && r.onRemove(s[e].spec), s.splice(e--, 1));
        return s.length || o.length ? new lo(s, o) : co
    }

    function go(e, t) {
        return e.from - t.from || e.to - t.to
    }

    function vo(e) {
        let t = e;
        for (let n = 0; n < t.length - 1; n++) {
            let r = t[n];
            if (r.from != r.to)
                for (let o = n + 1; o < t.length; o++) {
                    let i = t[o];
                    if (i.from != r.from) {
                        i.from < r.to && (t == e && (t = e.slice()), t[n] = r.copy(r.from, i.from), yo(t, o, r.copy(i.from, r.to)));
                        break
                    }
                    i.to != r.to && (t == e && (t = e.slice()), t[o] = i.copy(i.from, r.to), yo(t, o + 1, i.copy(r.to, i.to)))
                }
        }
        return t
    }

    function yo(e, t, n) {
        for (; t < e.length && go(n, e[t]) > 0;) t++;
        e.splice(t, 0, n)
    }

    function bo(e) {
        let t = [];
        return e.someProp("decorations", n => {
            let r = n(e.state);
            r && r != co && t.push(r)
        }), e.cursorWrapper && t.push(lo.create(e.state.doc, [e.cursorWrapper.deco])), uo.from(t)
    }
    const wo = {
            childList: !0,
            characterData: !0,
            characterDataOldValue: !0,
            attributes: !0,
            attributeOldValue: !0,
            subtree: !0
        },
        ko = Vt && jt <= 11;
    class xo {
        constructor() {
            this.anchorNode = null, this.anchorOffset = 0, this.focusNode = null, this.focusOffset = 0
        }
        set(e) {
            this.anchorNode = e.anchorNode, this.anchorOffset = e.anchorOffset, this.focusNode = e.focusNode, this.focusOffset = e.focusOffset
        }
        clear() {
            this.anchorNode = this.focusNode = null
        }
        eq(e) {
            return e.anchorNode == this.anchorNode && e.anchorOffset == this.anchorOffset && e.focusNode == this.focusNode && e.focusOffset == this.focusOffset
        }
    }
    class Co {
        constructor(e, t) {
            this.view = e, this.handleDOMChange = t, this.queue = [], this.flushingSoon = -1, this.observer = null, this.currentSelection = new xo, this.onCharData = null, this.suppressingSelectionUpdates = !1, this.lastChangedTextNode = null, this.observer = window.MutationObserver && new window.MutationObserver(t => {
                for (let e = 0; e < t.length; e++) this.queue.push(t[e]);
                Vt && jt <= 11 && t.some(e => "childList" == e.type && e.removedNodes.length || "characterData" == e.type && e.oldValue.length > e.target.nodeValue.length) ? this.flushSoon() : Jt && e.composing && t.some(e => "childList" == e.type && "TR" == e.target.nodeName) ? (e.input.badSafariComposition = !0, this.flushSoon()) : this.flush()
            }), ko && (this.onCharData = e => {
                this.queue.push({
                    target: e.target,
                    type: "characterData",
                    oldValue: e.prevValue
                }), this.flushSoon()
            }), this.onSelectionChange = this.onSelectionChange.bind(this)
        }
        flushSoon() {
            this.flushingSoon < 0 && (this.flushingSoon = window.setTimeout(() => {
                this.flushingSoon = -1, this.flush()
            }, 20))
        }
        forceFlush() {
            this.flushingSoon > -1 && (window.clearTimeout(this.flushingSoon), this.flushingSoon = -1, this.flush())
        }
        start() {
            this.observer && (this.observer.takeRecords(), this.observer.observe(this.view.dom, wo)), this.onCharData && this.view.dom.addEventListener("DOMCharacterDataModified", this.onCharData), this.connectSelection()
        }
        stop() {
            if (this.observer) {
                let e = this.observer.takeRecords();
                if (e.length) {
                    for (let t = 0; t < e.length; t++) this.queue.push(e[t]);
                    window.setTimeout(() => this.flush(), 20)
                }
                this.observer.disconnect()
            }
            this.onCharData && this.view.dom.removeEventListener("DOMCharacterDataModified", this.onCharData), this.disconnectSelection()
        }
        connectSelection() {
            this.view.dom.ownerDocument.addEventListener("selectionchange", this.onSelectionChange)
        }
        disconnectSelection() {
            this.view.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange)
        }
        suppressSelectionUpdates() {
            this.suppressingSelectionUpdates = !0, setTimeout(() => this.suppressingSelectionUpdates = !1, 50)
        }
        onSelectionChange() {
            if (er(this.view)) {
                if (this.suppressingSelectionUpdates) return Wn(this.view);
                if (Vt && jt <= 11 && !this.view.state.selection.empty) {
                    let e = this.view.domSelectionRange();
                    if (e.focusNode && Nt(e.focusNode, e.focusOffset, e.anchorNode, e.anchorOffset)) return this.flushSoon()
                }
                this.flush()
            }
        }
        setCurSelection() {
            this.currentSelection.set(this.view.domSelectionRange())
        }
        ignoreSelectionChange(e) {
            if (!e.focusNode) return !0;
            let t, n = new Set;
            for (let t = e.focusNode; t; t = Mt(t)) n.add(t);
            for (let r = e.anchorNode; r; r = Mt(r))
                if (n.has(r)) {
                    t = r;
                    break
                } let r = t && this.view.docView.nearestDesc(t);
            return r && r.ignoreMutation({
                type: "selection",
                target: 3 == t.nodeType ? t.parentNode : t
            }) ? (this.setCurSelection(), !0) : void 0
        }
        pendingRecords() {
            if (this.observer)
                for (let e of this.observer.takeRecords()) this.queue.push(e);
            return this.queue
        }
        flush() {
            let {
                view: e
            } = this;
            if (!e.docView || this.flushingSoon > -1) return;
            let t = this.pendingRecords();
            t.length && (this.queue = []);
            let n = e.domSelectionRange(),
                r = !this.suppressingSelectionUpdates && !this.currentSelection.eq(n) && er(e) && !this.ignoreSelectionChange(n),
                o = -1,
                i = -1,
                s = !1,
                a = [];
            if (e.editable)
                for (let e = 0; e < t.length; e++) {
                    let n = this.registerMutation(t[e], a);
                    n && (o = o < 0 ? n.from : Math.min(n.from, o), i = i < 0 ? n.to : Math.max(n.to, i), n.typeOver && (s = !0))
                }
            if (a.some(e => "BR" == e.nodeName) && (8 == e.input.lastKeyCode || 46 == e.input.lastKeyCode || Ut && (e.composing || e.input.compositionEndedAt > Date.now() - 50) && t.some(e => "childList" == e.type && e.removedNodes.length))) {
                for (let e of a)
                    if ("BR" == e.nodeName && e.parentNode) {
                        let t = e.nextSibling;
                        for (; t && 1 == t.nodeType;) {
                            if ("false" == t.contentEditable) {
                                e.parentNode.removeChild(e);
                                break
                            }
                            t = t.firstChild
                        }
                    }
            } else if ($t && a.length) {
                let t = a.filter(e => "BR" == e.nodeName);
                if (2 == t.length) {
                    let [e, n] = t;
                    e.parentNode && e.parentNode.parentNode == n.parentNode ? n.remove() : e.remove()
                } else {
                    let {
                        focusNode: n
                    } = this.currentSelection;
                    for (let r of t) {
                        let t = r.parentNode;
                        !t || "LI" != t.nodeName || n && Eo(e, n) == t || r.remove()
                    }
                }
            }
            let l = null;
            o < 0 && r && e.input.lastFocus > Date.now() - 200 && Math.max(e.input.lastTouch, e.input.lastClick.time) < Date.now() - 300 && It(n) && (l = _n(e)) && l.eq(tt.near(e.state.doc.resolve(0), 1)) ? (e.input.lastFocus = 0, Wn(e), this.currentSelection.set(n), e.scrollToSelection()) : (o > -1 || r) && (o > -1 && (e.docView.markDirty(o, i), function(e) {
                if (!To.has(e) && (To.set(e, null), -1 !== ["normal", "nowrap", "pre-line"].indexOf(getComputedStyle(e.dom).whiteSpace))) {
                    if (e.requiresGeckoHackNode = $t, Mo) return;
                    console.warn("ProseMirror expects the CSS white-space property to be set, preferably to 'pre-wrap'. It is recommended to load style/prosemirror.css from the prosemirror-view package."), Mo = !0
                }
            }(e)), e.input.badSafariComposition && (e.input.badSafariComposition = !1, function(e, t) {
                var n;
                let {
                    focusNode: r,
                    focusOffset: o
                } = e.domSelectionRange();
                for (let i of t)
                    if ("TR" == (null === (n = i.parentNode) || void 0 === n ? void 0 : n.nodeName)) {
                        let t = i.nextSibling;
                        for (; t && "TD" != t.nodeName && "TH" != t.nodeName;) t = t.nextSibling;
                        if (t) {
                            let n = t;
                            for (;;) {
                                let e = n.firstChild;
                                if (!e || 1 != e.nodeType || "false" == e.contentEditable || /^(BR|IMG)$/.test(e.nodeName)) break;
                                n = e
                            }
                            n.insertBefore(i, n.firstChild), r == i && e.domSelection().collapse(i, o)
                        } else i.parentNode.removeChild(i)
                    }
            }(e, a)), this.handleDOMChange(o, i, s, a), e.docView && e.docView.dirty ? e.updateState(e.state) : this.currentSelection.eq(n) || Wn(e), this.currentSelection.set(n))
        }
        registerMutation(e, t) {
            if (t.indexOf(e.target) > -1) return null;
            let n = this.view.docView.nearestDesc(e.target);
            if ("attributes" == e.type && (n == this.view.docView || "contenteditable" == e.attributeName || "style" == e.attributeName && !e.oldValue && !e.target.getAttribute("style"))) return null;
            if (!n || n.ignoreMutation(e)) return null;
            if ("childList" == e.type) {
                for (let n = 0; n < e.addedNodes.length; n++) {
                    let r = e.addedNodes[n];
                    t.push(r), 3 == r.nodeType && (this.lastChangedTextNode = r)
                }
                if (n.contentDOM && n.contentDOM != n.dom && !n.contentDOM.contains(e.target)) return {
                    from: n.posBefore,
                    to: n.posAfter
                };
                let r = e.previousSibling,
                    o = e.nextSibling;
                if (Vt && jt <= 11 && e.addedNodes.length)
                    for (let t = 0; t < e.addedNodes.length; t++) {
                        let {
                            previousSibling: n,
                            nextSibling: i
                        } = e.addedNodes[t];
                        (!n || Array.prototype.indexOf.call(e.addedNodes, n) < 0) && (r = n), (!i || Array.prototype.indexOf.call(e.addedNodes, i) < 0) && (o = i)
                    }
                let i = r && r.parentNode == e.target ? Tt(r) + 1 : 0,
                    s = n.localPosFromDOM(e.target, i, -1),
                    a = o && o.parentNode == e.target ? Tt(o) : e.target.childNodes.length;
                return {
                    from: s,
                    to: n.localPosFromDOM(e.target, a, 1)
                }
            }
            return "attributes" == e.type ? {
                from: n.posAtStart - n.border,
                to: n.posAtEnd + n.border
            } : (this.lastChangedTextNode = e.target, {
                from: n.posAtStart,
                to: n.posAtEnd,
                typeOver: e.target.nodeValue == e.oldValue
            })
        }
    }
    let To = new WeakMap,
        Mo = !1;

    function So(e, t) {
        let n = t.startContainer,
            r = t.startOffset,
            o = t.endContainer,
            i = t.endOffset,
            s = e.domAtPos(e.state.selection.anchor);
        return Nt(s.node, s.offset, o, i) && ([n, r, o, i] = [o, i, n, r]), {
            anchorNode: n,
            anchorOffset: r,
            focusNode: o,
            focusOffset: i
        }
    }

    function Eo(e, t) {
        for (let n = t.parentNode; n && n != e.dom; n = n.parentNode) {
            let t = e.docView.nearestDesc(n, !0);
            if (t && t.node.isBlock) return n
        }
        return null
    }
    const No = /^(a|abbr|acronym|b|bd[io]|big|br|button|cite|code|data(list)?|del|dfn|em|i|img|ins|kbd|label|map|mark|meter|output|q|ruby|s|samp|small|span|strong|su[bp]|time|u|tt|var)$/i;

    function Oo(e, t, n) {
        return Math.max(n.anchor, n.head) > t.content.size ? null : Yn(e, t.resolve(n.anchor), t.resolve(n.head))
    }

    function Do(e, t, n) {
        let r = e.depth,
            o = t ? e.end() : e.pos;
        for (; r > 0 && (t || e.indexAfter(r) == e.node(r).childCount);) r--, o++, t = !1;
        if (n) {
            let t = e.node(r).maybeChild(e.indexAfter(r));
            for (; t && !t.isLeaf;) t = t.firstChild, o++
        }
        return o
    }
    class Ao {
        constructor(e, t) {
            this._root = null, this.focused = !1, this.trackWrites = null, this.mounted = !1, this.markCursor = null, this.cursorWrapper = null, this.lastSelectedViewDesc = void 0, this.input = new Nr, this.prevDirectPlugins = [], this.pluginViews = [], this.requiresGeckoHackNode = !1, this.dragging = null, this._props = t, this.state = t.state, this.directPlugins = t.plugins || [], this.directPlugins.forEach(Bo), this.dispatch = this.dispatch.bind(this), this.dom = e && e.mount || document.createElement("div"), e && (e.appendChild ? e.appendChild(this.dom) : "function" == typeof e ? e(this.dom) : e.mount && (this.mounted = !0)), this.editable = Ro(this), Io(this), this.nodeViews = Po(this), this.docView = Nn(this.state.doc, Lo(this), bo(this), this.dom, this), this.domObserver = new Co(this, (e, t, n, r) => function(e, t, n, r, o) {
                    let i = e.input.compositionPendingChanges || (e.composing ? e.input.compositionID : 0);
                    if (e.input.compositionPendingChanges = 0, t < 0) {
                        let t = e.input.lastSelectionTime > Date.now() - 50 ? e.input.lastSelectionOrigin : null,
                            n = _n(e, t);
                        if (n && !e.state.selection.eq(n)) {
                            if (Ut && Zt && 13 === e.input.lastKeyCode && Date.now() - 100 < e.input.lastKeyCodeTime && e.someProp("handleKeyDown", t => t(e, Rt(13, "Enter")))) return;
                            let r = e.state.tr.setSelection(n);
                            "pointer" == t ? r.setMeta("pointer", !0) : "key" == t && r.scrollIntoView(), i && r.setMeta("composition", i), e.dispatch(r)
                        }
                        return
                    }
                    let s = e.state.doc.resolve(t),
                        a = s.sharedDepth(n);
                    t = s.before(a + 1), n = e.state.doc.resolve(n).after(a + 1);
                    let c, u, d = e.state.selection,
                        p = function(e, t, n, r) {
                            let o, {
                                    node: i,
                                    fromOffset: s,
                                    toOffset: a,
                                    from: l,
                                    to: c
                                } = e.docView.parseRange(t, n),
                                u = e.domSelectionRange(),
                                d = u.anchorNode;
                            if (d && e.dom.contains(1 == d.nodeType ? d : d.parentNode) && (o = [{
                                    node: d,
                                    offset: u.anchorOffset
                                }], It(u) || o.push({
                                    node: u.focusNode,
                                    offset: u.focusOffset
                                })), Ut && 8 === e.input.lastKeyCode)
                                for (let e = a; e > s; e--) {
                                    let t = i.childNodes[e - 1],
                                        n = t.pmViewDesc;
                                    if ("BR" == t.nodeName && !n) {
                                        a = e;
                                        break
                                    }
                                    if (!n || n.size) break
                                }
                            let p = e.state.doc,
                                h = e.someProp("domParser") || Y.fromSchema(e.state.schema),
                                f = p.resolve(l),
                                m = null,
                                g = h.parse(i, {
                                    topNode: f.parent,
                                    topMatch: f.parent.contentMatchAt(f.index()),
                                    topOpen: !0,
                                    from: s,
                                    to: a,
                                    preserveWhitespace: "pre" != f.parent.type.whitespace || "full",
                                    findPositions: o,
                                    ruleFromNode: (v = r, e => {
                                        let t = e.pmViewDesc;
                                        if (t) return t.parseRule(v);
                                        if ("BR" == e.nodeName && e.parentNode) {
                                            if (Jt && /^(ul|ol)$/i.test(e.parentNode.nodeName)) {
                                                let e = document.createElement("div");
                                                return e.appendChild(document.createElement("li")), {
                                                    skip: e
                                                }
                                            }
                                            if (e.parentNode.lastChild == e || Jt && /^(tr|table)$/i.test(e.parentNode.nodeName)) return {
                                                ignore: !0
                                            }
                                        } else if ("IMG" == e.nodeName && e.getAttribute("mark-placeholder")) return {
                                            ignore: !0
                                        };
                                        return null
                                    }),
                                    context: f
                                });
                            var v;
                            if (o && null != o[0].pos) {
                                let e = o[0].pos,
                                    t = o[1] && o[1].pos;
                                null == t && (t = e), m = {
                                    anchor: e + l,
                                    head: t + l
                                }
                            }
                            return {
                                doc: g,
                                sel: m,
                                from: l,
                                to: c
                            }
                        }(e, t, n, o),
                        h = e.state.doc,
                        f = h.slice(p.from, p.to);
                    8 === e.input.lastKeyCode && Date.now() - 100 < e.input.lastKeyCodeTime ? (c = e.state.selection.to, u = "end") : (c = e.state.selection.from, u = "start"), e.input.lastKeyCode = null;
                    let m = function(e, t, n, r, o) {
                        let i = e.findDiffStart(t, n),
                            s = n + e.size,
                            a = n + t.size;
                        if (null == i) return null;
                        let {
                            a: l,
                            b: c
                        } = e.findDiffEnd(t, s, a);
                        return "end" == o && (r -= l + Math.max(0, i - Math.min(l, c)) - i), l < i && s < a ? (i -= r <= i && r >= l ? i - r : 0, c = i + (c - l), l = i) : c < i && (i -= r <= i && r >= c ? i - r : 0, l = i + (l - c), c = i), {
                            start: i,
                            endA: l,
                            endB: c
                        }
                    }(f.content, p.doc.content, p.from, c, u);
                    if (m && e.input.domChangeCount++, (Kt && e.input.lastIOSEnter > Date.now() - 225 || Zt) && o.some(e => 1 == e.nodeType && !No.test(e.nodeName)) && (!m || m.endA >= m.endB) && e.someProp("handleKeyDown", t => t(e, Rt(13, "Enter")))) return void(e.input.lastIOSEnter = 0);
                    if (!m) {
                        if (!(r && d instanceof it && !d.empty && d.$head.sameParent(d.$anchor)) || e.composing || p.sel && p.sel.anchor != p.sel.head) {
                            if (p.sel) {
                                let t = Oo(e, e.state.doc, p.sel);
                                if (t && !t.eq(e.state.selection)) {
                                    let n = e.state.tr.setSelection(t);
                                    i && n.setMeta("composition", i), e.dispatch(n)
                                }
                            }
                            return
                        }
                        m = {
                            start: d.from,
                            endA: d.to,
                            endB: d.to
                        }
                    }
                    e.state.selection.from < e.state.selection.to && m.start == m.endB && e.state.selection instanceof it && (m.start > e.state.selection.from && m.start <= e.state.selection.from + 2 && e.state.selection.from >= p.from ? m.start = e.state.selection.from : m.endA < e.state.selection.to && m.endA >= e.state.selection.to - 2 && e.state.selection.to <= p.to && (m.endB += e.state.selection.to - m.endA, m.endA = e.state.selection.to)), Vt && jt <= 11 && m.endB == m.start + 1 && m.endA == m.start && m.start > p.from && "  " == p.doc.textBetween(m.start - p.from - 1, m.start - p.from + 1) && (m.start--, m.endA--, m.endB--);
                    let g = p.doc.resolveNoCache(m.start - p.from),
                        v = p.doc.resolveNoCache(m.endB - p.from),
                        y = h.resolve(m.start),
                        b = g.sameParent(v) && g.parent.inlineContent && y.end() >= m.endA;
                    if ((Kt && e.input.lastIOSEnter > Date.now() - 225 && (!b || o.some(e => "DIV" == e.nodeName || "P" == e.nodeName)) || !b && g.pos < p.doc.content.size && (!g.sameParent(v) || !g.parent.inlineContent) && g.pos < v.pos && !/\S/.test(p.doc.textBetween(g.pos, v.pos, "", ""))) && e.someProp("handleKeyDown", t => t(e, Rt(13, "Enter")))) return void(e.input.lastIOSEnter = 0);
                    if (e.state.selection.anchor > m.start && function(e, t, n, r, o) {
                            if (n - t <= o.pos - r.pos || Do(r, !0, !1) < o.pos) return !1;
                            let i = e.resolve(t);
                            if (!r.parent.isTextblock) {
                                let e = i.nodeAfter;
                                return null != e && n == t + e.nodeSize
                            }
                            if (i.parentOffset < i.parent.content.size || !i.parent.isTextblock) return !1;
                            let s = e.resolve(Do(i, !0, !0));
                            return !(!s.parent.isTextblock || s.pos > n || Do(s, !0, !1) < n) && r.parent.content.cut(r.parentOffset).eq(s.parent.content)
                        }(h, m.start, m.endA, g, v) && e.someProp("handleKeyDown", t => t(e, Rt(8, "Backspace")))) return void(Zt && Ut && e.domObserver.suppressSelectionUpdates());
                    Ut && m.endB == m.start && (e.input.lastChromeDelete = Date.now()), Zt && !b && g.start() != v.start() && 0 == v.parentOffset && g.depth == v.depth && p.sel && p.sel.anchor == p.sel.head && p.sel.head == m.endA && (m.endB -= 2, v = p.doc.resolveNoCache(m.endB - p.from), setTimeout(() => {
                        e.someProp("handleKeyDown", function(t) {
                            return t(e, Rt(13, "Enter"))
                        })
                    }, 20));
                    let w, k = m.start,
                        x = m.endA,
                        C = t => {
                            let n = t || e.state.tr.replace(k, x, p.doc.slice(m.start - p.from, m.endB - p.from));
                            if (p.sel) {
                                let t = Oo(e, n.doc, p.sel);
                                t && !(Ut && e.composing && t.empty && (m.start != m.endB || e.input.lastChromeDelete < Date.now() - 100) && (t.head == k || t.head == n.mapping.map(x) - 1) || Vt && t.empty && t.head == k) && n.setSelection(t)
                            }
                            return i && n.setMeta("composition", i), n.scrollIntoView()
                        };
                    if (b)
                        if (g.pos == v.pos) {
                            Vt && jt <= 11 && 0 == g.parentOffset && (e.domObserver.suppressSelectionUpdates(), setTimeout(() => Wn(e), 20));
                            let t = C(e.state.tr.delete(k, x)),
                                n = h.resolve(m.start).marksAcross(h.resolve(m.endA));
                            n && t.ensureMarks(n), e.dispatch(t)
                        } else if (m.endA == m.endB && (w = function(e, t) {
                            let n, r, o, i = e.firstChild.marks,
                                s = t.firstChild.marks,
                                a = i,
                                c = s;
                            for (let e = 0; e < s.length; e++) a = s[e].removeFromSet(a);
                            for (let e = 0; e < i.length; e++) c = i[e].removeFromSet(c);
                            if (1 == a.length && 0 == c.length) r = a[0], n = "add", o = e => e.mark(r.addToSet(e.marks));
                            else {
                                if (0 != a.length || 1 != c.length) return null;
                                r = c[0], n = "remove", o = e => e.mark(r.removeFromSet(e.marks))
                            }
                            let u = [];
                            for (let e = 0; e < t.childCount; e++) u.push(o(t.child(e)));
                            if (l.from(u).eq(e)) return {
                                mark: r,
                                type: n
                            }
                        }(g.parent.content.cut(g.parentOffset, v.parentOffset), y.parent.content.cut(y.parentOffset, m.endA - y.start())))) {
                        let t = C(e.state.tr);
                        "add" == w.type ? t.addMark(k, x, w.mark) : t.removeMark(k, x, w.mark), e.dispatch(t)
                    } else if (g.parent.child(g.index()).isText && g.index() == v.index() - (v.textOffset ? 0 : 1)) {
                        let t = g.parent.textBetween(g.parentOffset, v.parentOffset),
                            n = () => C(e.state.tr.insertText(t, k, x));
                        e.someProp("handleTextInput", r => r(e, k, x, t, n)) || e.dispatch(n())
                    } else e.dispatch(C());
                    else e.dispatch(C())
                }(this, e, t, n, r)), this.domObserver.start(),
                function(e) {
                    for (let t in Mr) {
                        let n = Mr[t];
                        e.dom.addEventListener(t, e.input.eventHandlers[t] = t => {
                            !Lr(e, t) || Ar(e, t) || !e.editable && t.type in Sr || n(e, t)
                        }, Er[t] ? {
                            passive: !0
                        } : void 0)
                    }
                    Jt && e.dom.addEventListener("input", () => null), Dr(e)
                }(this), this.updatePluginViews()
        }
        get composing() {
            return this.input.composing
        }
        get props() {
            if (this._props.state != this.state) {
                let e = this._props;
                this._props = {};
                for (let t in e) this._props[t] = e[t];
                this._props.state = this.state
            }
            return this._props
        }
        update(e) {
            e.handleDOMEvents != this._props.handleDOMEvents && Dr(this);
            let t = this._props;
            this._props = e, e.plugins && (e.plugins.forEach(Bo), this.directPlugins = e.plugins), this.updateStateInner(e.state, t)
        }
        setProps(e) {
            let t = {};
            for (let e in this._props) t[e] = this._props[e];
            t.state = this.state;
            for (let n in e) t[n] = e[n];
            this.update(t)
        }
        updateState(e) {
            this.updateStateInner(e, this._props)
        }
        updateStateInner(e, t) {
            var n;
            let r = this.state,
                o = !1,
                i = !1;
            e.storedMarks && this.composing && (Jr(this), i = !0), this.state = e;
            let s = r.plugins != e.plugins || this._props.plugins != t.plugins;
            if (s || this._props.plugins != t.plugins || this._props.nodeViews != t.nodeViews) {
                let e = Po(this);
                (function(e, t) {
                    let n = 0,
                        r = 0;
                    for (let r in e) {
                        if (e[r] != t[r]) return !0;
                        n++
                    }
                    for (let e in t) r++;
                    return n != r
                })(e, this.nodeViews) && (this.nodeViews = e, o = !0)
            }(s || t.handleDOMEvents != this._props.handleDOMEvents) && Dr(this), this.editable = Ro(this), Io(this);
            let a = bo(this),
                l = Lo(this),
                c = r.plugins == e.plugins || r.doc.eq(e.doc) ? e.scrollToSelection > r.scrollToSelection ? "to selection" : "preserve" : "reset",
                u = o || !this.docView.matchesNode(e.doc, l, a);
            !u && e.selection.eq(r.selection) || (i = !0);
            let d = "preserve" == c && i && null == this.dom.style.overflowAnchor && function(e) {
                let t, n, r = e.dom.getBoundingClientRect(),
                    o = Math.max(0, r.top);
                for (let i = (r.left + r.right) / 2, s = o + 1; s < Math.min(innerHeight, r.bottom); s += 5) {
                    let r = e.root.elementFromPoint(i, s);
                    if (!r || r == e.dom || !e.dom.contains(r)) continue;
                    let a = r.getBoundingClientRect();
                    if (a.top >= o - 20) {
                        t = r, n = a.top;
                        break
                    }
                }
                return {
                    refDOM: t,
                    refTop: n,
                    stack: on(e.dom)
                }
            }(this);
            if (i) {
                this.domObserver.stop();
                let t = u && (Vt || Ut) && !this.composing && !r.selection.empty && !e.selection.empty && function(e, t) {
                    let n = Math.min(e.$anchor.sharedDepth(e.head), t.$anchor.sharedDepth(t.head));
                    return e.$anchor.start(n) != t.$anchor.start(n)
                }(r.selection, e.selection);
                if (u) {
                    let n = Ut ? this.trackWrites = this.domSelectionRange().focusNode : null;
                    this.composing && (this.input.compositionNode = function(e) {
                        let t = e.domSelectionRange();
                        if (!t.focusNode) return null;
                        let n = function(e, t) {
                                for (;;) {
                                    if (3 == e.nodeType && t) return e;
                                    if (1 == e.nodeType && t > 0) {
                                        if ("false" == e.contentEditable) return null;
                                        t = At(e = e.childNodes[t - 1])
                                    } else {
                                        if (!e.parentNode || Lt(e)) return null;
                                        t = Tt(e), e = e.parentNode
                                    }
                                }
                            }(t.focusNode, t.focusOffset),
                            r = function(e, t) {
                                for (;;) {
                                    if (3 == e.nodeType && t < e.nodeValue.length) return e;
                                    if (1 == e.nodeType && t < e.childNodes.length) {
                                        if ("false" == e.contentEditable) return null;
                                        e = e.childNodes[t], t = 0
                                    } else {
                                        if (!e.parentNode || Lt(e)) return null;
                                        t = Tt(e) + 1, e = e.parentNode
                                    }
                                }
                            }(t.focusNode, t.focusOffset);
                        if (n && r && n != r) {
                            let t = r.pmViewDesc,
                                o = e.domObserver.lastChangedTextNode;
                            if (n == o || r == o) return o;
                            if (!t || !t.isText(r.nodeValue)) return r;
                            if (e.input.compositionNode == r) {
                                let e = n.pmViewDesc;
                                if (e && e.isText(n.nodeValue)) return r
                            }
                        }
                        return n || r
                    }(this)), !o && this.docView.update(e.doc, l, a, this) || (this.docView.updateOuterDeco(l), this.docView.destroy(), this.docView = Nn(e.doc, l, a, this.dom, this)), !n || this.trackWrites && this.dom.contains(this.trackWrites) || (t = !0)
                }
                let n = this.input.mouseDown;
                t || !(n && this.domObserver.currentSelection.eq(this.domSelectionRange()) && function(e) {
                    let t = e.docView.domFromPos(e.state.selection.anchor, 0),
                        n = e.domSelectionRange();
                    return Nt(t.node, t.offset, n.anchorNode, n.anchorOffset)
                }(this) && n.delaySelUpdate()) ? Wn(this, t) : (Zn(this, e.selection), this.domObserver.setCurSelection()), this.domObserver.start()
            }
            this.updatePluginViews(r), (null === (n = this.dragging) || void 0 === n ? void 0 : n.node) && !r.doc.eq(e.doc) && this.updateDraggedNode(this.dragging, r), "reset" == c ? this.dom.scrollTop = 0 : "to selection" == c ? this.scrollToSelection() : d && function({
                refDOM: e,
                refTop: t,
                stack: n
            }) {
                let r = e ? e.getBoundingClientRect().top : 0;
                sn(n, 0 == r ? 0 : r - t)
            }(d)
        }
        scrollToSelection() {
            let e = this.domSelectionRange().focusNode;
            if (e && this.dom.contains(1 == e.nodeType ? e : e.parentNode))
                if (this.someProp("handleScrollToSelection", e => e(this)));
                else if (this.state.selection instanceof at) {
                let t = this.docView.domAfterPos(this.state.selection.from);
                1 == t.nodeType && rn(this, t.getBoundingClientRect(), e)
            } else rn(this, this.coordsAtPos(this.state.selection.head, 1), e)
        }
        destroyPluginViews() {
            let e;
            for (; e = this.pluginViews.pop();) e.destroy && e.destroy()
        }
        updatePluginViews(e) {
            if (e && e.plugins == this.state.plugins && this.directPlugins == this.prevDirectPlugins)
                for (let t = 0; t < this.pluginViews.length; t++) {
                    let n = this.pluginViews[t];
                    n.update && n.update(this, e)
                } else {
                    this.prevDirectPlugins = this.directPlugins, this.destroyPluginViews();
                    for (let e = 0; e < this.directPlugins.length; e++) {
                        let t = this.directPlugins[e];
                        t.spec.view && this.pluginViews.push(t.spec.view(this))
                    }
                    for (let e = 0; e < this.state.plugins.length; e++) {
                        let t = this.state.plugins[e];
                        t.spec.view && this.pluginViews.push(t.spec.view(this))
                    }
                }
        }
        updateDraggedNode(e, t) {
            let n = e.node,
                r = -1;
            if (n.from < this.state.doc.content.size && this.state.doc.nodeAt(n.from) == n.node) r = n.from;
            else {
                let e = n.from + (this.state.doc.content.size - t.doc.content.size);
                (e > 0 && e < this.state.doc.content.size && this.state.doc.nodeAt(e)) == n.node && (r = e)
            }
            this.dragging = new Qr(e.slice, e.move, r < 0 ? void 0 : at.create(this.state.doc, r))
        }
        someProp(e, t) {
            let n, r = this._props && this._props[e];
            if (null != r && (n = t ? t(r) : r)) return n;
            for (let r = 0; r < this.directPlugins.length; r++) {
                let o = this.directPlugins[r].props[e];
                if (null != o && (n = t ? t(o) : o)) return n
            }
            let o = this.state.plugins;
            if (o)
                for (let r = 0; r < o.length; r++) {
                    let i = o[r].props[e];
                    if (null != i && (n = t ? t(i) : i)) return n
                }
        }
        hasFocus() {
            if (Vt) {
                let e = this.root.activeElement;
                if (e == this.dom) return !0;
                if (!e || !this.dom.contains(e)) return !1;
                for (; e && this.dom != e && this.dom.contains(e);) {
                    if ("false" == e.contentEditable) return !1;
                    e = e.parentElement
                }
                return !0
            }
            return this.root.activeElement == this.dom
        }
        focus() {
            this.domObserver.stop(), this.editable && function(e) {
                if (e.setActive) return e.setActive();
                if (an) return e.focus(an);
                let t = on(e);
                e.focus(null == an ? {
                    get preventScroll() {
                        return an = {
                            preventScroll: !0
                        }, !0
                    }
                } : void 0), an || (an = !1, sn(t, 0))
            }(this.dom), Wn(this), this.domObserver.start()
        }
        get root() {
            let e = this._root;
            if (null == e)
                for (let e = this.dom.parentNode; e; e = e.parentNode)
                    if (9 == e.nodeType || 11 == e.nodeType && e.host) return e.getSelection || (Object.getPrototypeOf(e).getSelection = () => e.ownerDocument.getSelection()), this._root = e;
            return e || document
        }
        updateRoot() {
            this._root = null
        }
        posAtCoords(e) {
            return dn(this, e)
        }
        coordsAtPos(e, t = 1) {
            return mn(this, e, t)
        }
        domAtPos(e, t = 0) {
            return this.docView.domFromPos(e, t)
        }
        nodeDOM(e) {
            let t = this.docView.descAt(e);
            return t ? t.nodeDOM : null
        }
        posAtDOM(e, t, n = -1) {
            let r = this.docView.posFromDOM(e, t, n);
            if (null == r) throw new RangeError("DOM position not inside the editor");
            return r
        }
        endOfTextblock(e, t) {
            return function(e, t, n) {
                return wn == t && kn == n ? xn : (wn = t, kn = n, xn = "up" == n || "down" == n ? function(e, t, n) {
                    let r = t.selection,
                        o = "up" == n ? r.$from : r.$to;
                    return yn(e, t, () => {
                        let {
                            node: t
                        } = e.docView.domFromPos(o.pos, "up" == n ? -1 : 1);
                        for (;;) {
                            let n = e.docView.nearestDesc(t, !0);
                            if (!n) break;
                            if (n.node.isBlock) {
                                t = n.contentDOM || n.dom;
                                break
                            }
                            t = n.dom.parentNode
                        }
                        let r = mn(e, o.pos, 1);
                        for (let e = t.firstChild; e; e = e.nextSibling) {
                            let t;
                            if (1 == e.nodeType) t = e.getClientRects();
                            else {
                                if (3 != e.nodeType) continue;
                                t = Et(e, 0, e.nodeValue.length).getClientRects()
                            }
                            for (let e = 0; e < t.length; e++) {
                                let o = t[e];
                                if (o.bottom > o.top + 1 && ("up" == n ? r.top - o.top > 2 * (o.bottom - r.top) : o.bottom - r.bottom > 2 * (r.bottom - o.top))) return !1
                            }
                        }
                        return !0
                    })
                }(e, t, n) : function(e, t, n) {
                    let {
                        $head: r
                    } = t.selection;
                    if (!r.parent.isTextblock) return !1;
                    let o = r.parentOffset,
                        i = !o,
                        s = o == r.parent.content.size,
                        a = e.domSelection();
                    return a ? bn.test(r.parent.textContent) && a.modify ? yn(e, t, () => {
                        let {
                            focusNode: t,
                            focusOffset: o,
                            anchorNode: i,
                            anchorOffset: s
                        } = e.domSelectionRange(), l = a.caretBidiLevel;
                        a.modify("move", n, "character");
                        let c = r.depth ? e.docView.domAfterPos(r.before()) : e.dom,
                            {
                                focusNode: u,
                                focusOffset: d
                            } = e.domSelectionRange(),
                            p = u && !c.contains(1 == u.nodeType ? u : u.parentNode) || t == u && o == d;
                        try {
                            a.collapse(i, s), t && (t != i || o != s) && a.extend && a.extend(t, o)
                        } catch (e) {}
                        return null != l && (a.caretBidiLevel = l), p
                    }) : "left" == n || "backward" == n ? i : s : r.pos == r.start() || r.pos == r.end()
                }(e, t, n))
            }(this, t || this.state, e)
        }
        pasteHTML(e, t) {
            return Xr(this, "", e, !1, t || new ClipboardEvent("paste"))
        }
        pasteText(e, t) {
            return Xr(this, e, null, !0, t || new ClipboardEvent("paste"))
        }
        serializeForClipboard(e) {
            return fr(this, e)
        }
        destroy() {
            this.docView && (function(e) {
                e.input.mouseDown && e.input.mouseDown.done(), e.domObserver.stop();
                for (let t in e.input.eventHandlers) e.dom.removeEventListener(t, e.input.eventHandlers[t]);
                clearTimeout(e.input.composingTimeout), clearTimeout(e.input.lastIOSEnterFallbackTimeout)
            }(this), this.destroyPluginViews(), this.mounted ? (this.docView.update(this.state.doc, [], bo(this), this), this.dom.textContent = "") : this.dom.parentNode && this.dom.parentNode.removeChild(this.dom), this.docView.destroy(), this.docView = null, St = null)
        }
        get isDestroyed() {
            return null == this.docView
        }
        dispatchEvent(e) {
            return function(e, t) {
                Ar(e, t) || !Mr[t.type] || !e.editable && t.type in Sr || Mr[t.type](e, t)
            }(this, e)
        }
        domSelectionRange() {
            let e = this.domSelection();
            return e ? Jt && 11 === this.root.nodeType && function(e) {
                let t = e.activeElement;
                for (; t && t.shadowRoot;) t = t.shadowRoot.activeElement;
                return t
            }(this.dom.ownerDocument) == this.dom && function(e, t) {
                if (t.getComposedRanges) {
                    let n = t.getComposedRanges(e.root)[0];
                    if (n) return So(e, n)
                }
                let n;

                function r(e) {
                    e.preventDefault(), e.stopImmediatePropagation(), n = e.getTargetRanges()[0]
                }
                return e.dom.addEventListener("beforeinput", r, !0), document.execCommand("indent"), e.dom.removeEventListener("beforeinput", r, !0), n ? So(e, n) : null
            }(this, e) || e : {
                focusNode: null,
                focusOffset: 0,
                anchorNode: null,
                anchorOffset: 0
            }
        }
        domSelection() {
            return this.root.getSelection()
        }
    }

    function Lo(e) {
        let t = Object.create(null);
        return t.class = "ProseMirror", t.contenteditable = String(e.editable), e.someProp("attributes", n => {
            if ("function" == typeof n && (n = n(e.state)), n)
                for (let e in n) "class" == e ? t.class += " " + n[e] : "style" == e ? t.style = (t.style ? t.style + ";" : "") + n[e] : t[e] || "contenteditable" == e || "nodeName" == e || (t[e] = String(n[e]))
        }), t.translate || (t.translate = "no"), [io.node(0, e.state.doc.content.size, t)]
    }

    function Io(e) {
        if (e.markCursor) {
            let t = document.createElement("img");
            t.className = "ProseMirror-separator", t.setAttribute("mark-placeholder", "true"), t.setAttribute("alt", ""), e.cursorWrapper = {
                dom: t,
                deco: io.widget(e.state.selection.from, t, {
                    raw: !0,
                    marks: e.markCursor
                })
            }
        } else e.cursorWrapper = null
    }

    function Ro(e) {
        return !e.someProp("editable", t => !1 === t(e.state))
    }

    function Po(e) {
        let t = Object.create(null);

        function n(e) {
            for (let n in e) Object.prototype.hasOwnProperty.call(t, n) || (t[n] = e[n])
        }
        return e.someProp("nodeViews", n), e.someProp("markViews", n), t
    }

    function Bo(e) {
        if (e.spec.state || e.spec.filterTransaction || e.spec.appendTransaction) throw new RangeError("Plugins passed directly to the view must not have a state component")
    }
    Ao.prototype.dispatch = function(e) {
        let t = this._props.dispatchTransaction;
        t ? t.call(this, e) : this.updateState(this.state.apply(e))
    };
    for (var Fo = {
            8: "Backspace",
            9: "Tab",
            10: "Enter",
            12: "NumLock",
            13: "Enter",
            16: "Shift",
            17: "Control",
            18: "Alt",
            20: "CapsLock",
            27: "Escape",
            32: " ",
            33: "PageUp",
            34: "PageDown",
            35: "End",
            36: "Home",
            37: "ArrowLeft",
            38: "ArrowUp",
            39: "ArrowRight",
            40: "ArrowDown",
            44: "PrintScreen",
            45: "Insert",
            46: "Delete",
            59: ";",
            61: "=",
            91: "Meta",
            92: "Meta",
            106: "*",
            107: "+",
            108: ",",
            109: "-",
            110: ".",
            111: "/",
            144: "NumLock",
            145: "ScrollLock",
            160: "Shift",
            161: "Shift",
            162: "Control",
            163: "Control",
            164: "Alt",
            165: "Alt",
            173: "-",
            186: ";",
            187: "=",
            188: ",",
            189: "-",
            190: ".",
            191: "/",
            192: "`",
            219: "[",
            220: "\\",
            221: "]",
            222: "'"
        }, Ho = {
            48: ")",
            49: "!",
            50: "@",
            51: "#",
            52: "$",
            53: "%",
            54: "^",
            55: "&",
            56: "*",
            57: "(",
            59: ":",
            61: "+",
            173: "_",
            186: ":",
            187: "+",
            188: "<",
            189: "_",
            190: ">",
            191: "?",
            192: "~",
            219: "{",
            220: "|",
            221: "}",
            222: '"'
        }, zo = "undefined" != typeof navigator && /Mac/.test(navigator.platform), qo = "undefined" != typeof navigator && /MSIE \d|Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent), Vo = 0; Vo < 10; Vo++) Fo[48 + Vo] = Fo[96 + Vo] = String(Vo);
    for (Vo = 1; Vo <= 24; Vo++) Fo[Vo + 111] = "F" + Vo;
    for (Vo = 65; Vo <= 90; Vo++) Fo[Vo] = String.fromCharCode(Vo + 32), Ho[Vo] = String.fromCharCode(Vo);
    for (var jo in Fo) Ho.hasOwnProperty(jo) || (Ho[jo] = Fo[jo]);
    const $o = "undefined" != typeof navigator && /Mac|iP(hone|[oa]d)/.test(navigator.platform),
        _o = "undefined" != typeof navigator && /Win/.test(navigator.platform);

    function Uo(e) {
        let t, n, r, o, i = e.split(/-(?!$)/),
            s = i[i.length - 1];
        "Space" == s && (s = " ");
        for (let e = 0; e < i.length - 1; e++) {
            let s = i[e];
            if (/^(cmd|meta|m)$/i.test(s)) o = !0;
            else if (/^a(lt)?$/i.test(s)) t = !0;
            else if (/^(c|ctrl|control)$/i.test(s)) n = !0;
            else if (/^s(hift)?$/i.test(s)) r = !0;
            else {
                if (!/^mod$/i.test(s)) throw new Error("Unrecognized modifier name: " + s);
                $o ? o = !0 : n = !0
            }
        }
        return t && (s = "Alt-" + s), n && (s = "Ctrl-" + s), o && (s = "Meta-" + s), r && (s = "Shift-" + s), s
    }

    function Wo(e, t, n = !0) {
        return t.altKey && (e = "Alt-" + e), t.ctrlKey && (e = "Ctrl-" + e), t.metaKey && (e = "Meta-" + e), n && t.shiftKey && (e = "Shift-" + e), e
    }

    function Jo(e) {
        return new wt({
            props: {
                handleKeyDown: Ko(e)
            }
        })
    }

    function Ko(e) {
        let t = function(e) {
            let t = Object.create(null);
            for (let n in e) t[Uo(n)] = e[n];
            return t
        }(e);
        return function(e, n) {
            let r, o = function(e) {
                    var t = !(zo && e.metaKey && e.shiftKey && !e.ctrlKey && !e.altKey || qo && e.shiftKey && e.key && 1 == e.key.length || "Unidentified" == e.key) && e.key || (e.shiftKey ? Ho : Fo)[e.keyCode] || e.key || "Unidentified";
                    return "Esc" == t && (t = "Escape"), "Del" == t && (t = "Delete"), "Left" == t && (t = "ArrowLeft"), "Up" == t && (t = "ArrowUp"), "Right" == t && (t = "ArrowRight"), "Down" == t && (t = "ArrowDown"), t
                }(n),
                i = t[Wo(o, n)];
            if (i && i(e.state, e.dispatch, e)) return !0;
            if (1 == o.length && " " != o) {
                if (n.shiftKey) {
                    let r = t[Wo(o, n, !1)];
                    if (r && r(e.state, e.dispatch, e)) return !0
                }
                if ((n.altKey || n.metaKey || n.ctrlKey) && !(_o && n.ctrlKey && n.altKey) && (r = Fo[n.keyCode]) && r != o) {
                    let o = t[Wo(r, n)];
                    if (o && o(e.state, e.dispatch, e)) return !0
                }
            }
            return !1
        }
    }
    const Go = (e, t) => !e.selection.empty && (t && t(e.tr.deleteSelection().scrollIntoView()), !0);

    function Xo(e, t, n = !1) {
        for (let r = e; r; r = "start" == t ? r.firstChild : r.lastChild) {
            if (r.isTextblock) return !0;
            if (n && 1 != r.childCount) return !1
        }
        return !1
    }

    function Zo(e) {
        if (!e.parent.type.spec.isolating)
            for (let t = e.depth - 1; t >= 0; t--) {
                if (e.index(t) > 0) return e.doc.resolve(e.before(t + 1));
                if (e.node(t).type.spec.isolating) break
            }
        return null
    }
    const Qo = (e, t, n) => {
        let r = function(e, t) {
            let {
                $cursor: n
            } = e.selection;
            return !n || (t ? !t.endOfTextblock("forward", e) : n.parentOffset < n.parent.content.size) ? null : n
        }(e, n);
        if (!r) return !1;
        let o = Yo(r);
        if (!o) return !1;
        let i = o.nodeAfter;
        if (ii(e, o, t, 1)) return !0;
        if (0 == r.parent.content.size && (Xo(i, "start") || at.isSelectable(i))) {
            let n = ze(e.doc, r.before(), r.after(), f.empty);
            if (n && n.slice.size < n.to - n.from) {
                if (t) {
                    let r = e.tr.step(n);
                    r.setSelection(Xo(i, "start") ? tt.findFrom(r.doc.resolve(r.mapping.map(o.pos)), 1) : at.create(r.doc, r.mapping.map(o.pos))), t(r.scrollIntoView())
                }
                return !0
            }
        }
        return !(!i.isAtom || o.depth != r.depth - 1 || (t && t(e.tr.delete(o.pos, o.pos + i.nodeSize).scrollIntoView()), 0))
    };

    function Yo(e) {
        if (!e.parent.type.spec.isolating)
            for (let t = e.depth - 1; t >= 0; t--) {
                let n = e.node(t);
                if (e.index(t) + 1 < n.childCount) return e.doc.resolve(e.after(t + 1));
                if (n.type.spec.isolating) break
            }
        return null
    }
    const ei = (e, t) => {
        let {
            $head: n,
            $anchor: r
        } = e.selection;
        return !(!n.parent.type.spec.code || !n.sameParent(r) || (t && t(e.tr.insertText("\n").scrollIntoView()), 0))
    };

    function ti(e) {
        for (let t = 0; t < e.edgeCount; t++) {
            let {
                type: n
            } = e.edge(t);
            if (n.isTextblock && !n.hasRequiredAttrs()) return n
        }
        return null
    }
    const ni = (e, t) => {
        let {
            $head: n,
            $anchor: r
        } = e.selection;
        if (!n.parent.type.spec.code || !n.sameParent(r)) return !1;
        let o = n.node(-1),
            i = n.indexAfter(-1),
            s = ti(o.contentMatchAt(i));
        if (!s || !o.canReplaceWith(i, i, s)) return !1;
        if (t) {
            let r = n.after(),
                o = e.tr.replaceWith(r, r, s.createAndFill());
            o.setSelection(tt.near(o.doc.resolve(r), 1)), t(o.scrollIntoView())
        }
        return !0
    };
    var ri;
    const oi = (e, t) => (t && t(e.tr.setSelection(new ct(e.doc))), !0);

    function ii(e, t, n, r) {
        let o, i, s = t.nodeBefore,
            a = t.nodeAfter,
            c = s.type.spec.isolating || a.type.spec.isolating;
        if (!c && function(e, t, n) {
                let r = t.nodeBefore,
                    o = t.nodeAfter,
                    i = t.index();
                return !(!(r && o && r.type.compatibleContent(o.type)) || (!r.content.size && t.parent.canReplace(i - 1, i) ? (n && n(e.tr.delete(t.pos - r.nodeSize, t.pos).scrollIntoView()), 0) : !t.parent.canReplace(i, i + 1) || !o.isTextblock && !He(e.doc, t.pos) || (n && n(e.tr.join(t.pos).scrollIntoView()), 0)))
            }(e, t, n)) return !0;
        let u = !c && t.parent.canReplace(t.index(), t.index() + 1);
        if (u && (o = (i = s.contentMatchAt(s.childCount)).findWrapping(a.type)) && i.matchType(o[0] || a.type).validEnd) {
            if (n) {
                let r = t.pos + a.nodeSize,
                    i = l.empty;
                for (let e = o.length - 1; e >= 0; e--) i = l.from(o[e].create(null, i));
                i = l.from(s.copy(i));
                let c = e.tr.step(new Oe(t.pos - 1, r, t.pos, r, new f(i, 1, 0), o.length, !0)),
                    u = c.doc.resolve(r + 2 * o.length);
                u.nodeAfter && u.nodeAfter.type == s.type && He(c.doc, u.pos) && c.join(u.pos), n(c.scrollIntoView())
            }
            return !0
        }
        let d = a.type.spec.isolating || r > 0 && c ? null : tt.findFrom(t, 1),
            p = d && d.$from.blockRange(d.$to),
            h = p && Ie(p);
        if (null != h && h >= t.depth) return n && n(e.tr.lift(p, h).scrollIntoView()), !0;
        if (u && Xo(a, "start", !0) && Xo(s, "end")) {
            let r = s,
                o = [];
            for (; o.push(r), !r.isTextblock;) r = r.lastChild;
            let i = a,
                c = 1;
            for (; !i.isTextblock; i = i.firstChild) c++;
            if (r.canReplace(r.childCount, r.childCount, i.content)) {
                if (n) {
                    let r = l.empty;
                    for (let e = o.length - 1; e >= 0; e--) r = l.from(o[e].copy(r));
                    n(e.tr.step(new Oe(t.pos - o.length, t.pos + a.nodeSize, t.pos + c, t.pos + a.nodeSize - c, new f(r, o.length, 0), 0, !0)).scrollIntoView())
                }
                return !0
            }
        }
        return !1
    }

    function si(e) {
        return function(t, n) {
            let r = t.selection,
                o = e < 0 ? r.$from : r.$to,
                i = o.depth;
            for (; o.node(i).isInline;) {
                if (!i) return !1;
                i--
            }
            return !!o.node(i).isTextblock && (n && n(t.tr.setSelection(it.create(t.doc, e < 0 ? o.start(i) : o.end(i)))), !0)
        }
    }
    const ai = si(-1),
        li = si(1);

    function ci(e, t = null) {
        return function(n, r) {
            let o = !1;
            for (let r = 0; r < n.selection.ranges.length && !o; r++) {
                let {
                    $from: {
                        pos: i
                    },
                    $to: {
                        pos: s
                    }
                } = n.selection.ranges[r];
                n.doc.nodesBetween(i, s, (r, i) => {
                    if (o) return !1;
                    if (r.isTextblock && !r.hasMarkup(e, t))
                        if (r.type == e) o = !0;
                        else {
                            let t = n.doc.resolve(i),
                                r = t.index();
                            o = t.parent.canReplaceWith(r, r + 1, e)
                        }
                })
            }
            if (!o) return !1;
            if (r) {
                let o = n.tr;
                for (let r = 0; r < n.selection.ranges.length; r++) {
                    let {
                        $from: {
                            pos: i
                        },
                        $to: {
                            pos: s
                        }
                    } = n.selection.ranges[r];
                    o.setBlockType(i, s, e, t)
                }
                r(o.scrollIntoView())
            }
            return !0
        }
    }

    function ui(e, t = null, n) {
        let r = !1 !== (n && n.removeWhenPresent),
            o = !1 !== (n && n.enterInlineAtoms),
            i = !(n && n.includeWhitespace);
        return function(n, s) {
            let {
                empty: a,
                $cursor: l,
                ranges: c
            } = n.selection;
            if (a && !l || ! function(e, t, n, r) {
                    for (let o = 0; o < t.length; o++) {
                        let {
                            $from: i,
                            $to: s
                        } = t[o], a = 0 == i.depth && e.inlineContent && e.type.allowsMarkType(n);
                        if (e.nodesBetween(i.pos, s.pos, (e, t) => {
                                if (a || !r && e.isAtom && e.isInline && t >= i.pos && t + e.nodeSize <= s.pos) return !1;
                                a = e.inlineContent && e.type.allowsMarkType(n)
                            }), a) return !0
                    }
                    return !1
                }(n.doc, c, e, o)) return !1;
            if (s)
                if (l) e.isInSet(n.storedMarks || l.marks()) ? s(n.tr.removeStoredMark(e)) : s(n.tr.addStoredMark(e.create(t)));
                else {
                    let a, l = n.tr;
                    o || (c = function(e) {
                        let t = [];
                        for (let n = 0; n < e.length; n++) {
                            let {
                                $from: r,
                                $to: o
                            } = e[n];
                            r.doc.nodesBetween(r.pos, o.pos, (e, n) => {
                                if (e.isAtom && e.content.size && e.isInline && n >= r.pos && n + e.nodeSize <= o.pos) return n + 1 > r.pos && t.push(new nt(r, r.doc.resolve(n + 1))), r = r.doc.resolve(n + 1 + e.content.size), !1
                            }), r.pos < o.pos && t.push(new nt(r, o))
                        }
                        return t
                    }(c)), a = r ? !c.some(t => n.doc.rangeHasMark(t.$from.pos, t.$to.pos, e)) : !c.every(t => {
                        let n = !1;
                        return l.doc.nodesBetween(t.$from.pos, t.$to.pos, (r, o, i) => {
                            if (n) return !1;
                            n = !e.isInSet(r.marks) && !!i && i.type.allowsMarkType(e) && !(r.isText && /^\s*$/.test(r.textBetween(Math.max(0, t.$from.pos - o), Math.min(r.nodeSize, t.$to.pos - o))))
                        }), !n
                    });
                    for (let n = 0; n < c.length; n++) {
                        let {
                            $from: r,
                            $to: o
                        } = c[n];
                        if (a) {
                            let n = r.pos,
                                s = o.pos,
                                a = r.nodeAfter,
                                c = o.nodeBefore,
                                u = i && a && a.isText ? /^\s*/.exec(a.text)[0].length : 0,
                                d = i && c && c.isText ? /\s*$/.exec(c.text)[0].length : 0;
                            n + u < s && (n += u, s -= d), l.addMark(n, s, e.create(t))
                        } else l.removeMark(r.pos, o.pos, e)
                    }
                    s(l.scrollIntoView())
                } return !0
        }
    }

    function di(...e) {
        return function(t, n, r) {
            for (let o = 0; o < e.length; o++)
                if (e[o](t, n, r)) return !0;
            return !1
        }
    }
    let pi = di(Go, (e, t, n) => {
            let r = function(e, t) {
                let {
                    $cursor: n
                } = e.selection;
                return !n || (t ? !t.endOfTextblock("backward", e) : n.parentOffset > 0) ? null : n
            }(e, n);
            if (!r) return !1;
            let o = Zo(r);
            if (!o) {
                let n = r.blockRange(),
                    o = n && Ie(n);
                return null != o && (t && t(e.tr.lift(n, o).scrollIntoView()), !0)
            }
            let i = o.nodeBefore;
            if (ii(e, o, t, -1)) return !0;
            if (0 == r.parent.content.size && (Xo(i, "end") || at.isSelectable(i)))
                for (let n = r.depth;; n--) {
                    let s = ze(e.doc, r.before(n), r.after(n), f.empty);
                    if (s && s.slice.size < s.to - s.from) {
                        if (t) {
                            let n = e.tr.step(s);
                            n.setSelection(Xo(i, "end") ? tt.findFrom(n.doc.resolve(n.mapping.map(o.pos, -1)), -1) : at.create(n.doc, o.pos - i.nodeSize)), t(n.scrollIntoView())
                        }
                        return !0
                    }
                    if (1 == n || r.node(n - 1).childCount > 1) break
                }
            return !(!i.isAtom || o.depth != r.depth - 1 || (t && t(e.tr.delete(o.pos - i.nodeSize, o.pos).scrollIntoView()), 0))
        }, (e, t, n) => {
            let {
                $head: r,
                empty: o
            } = e.selection, i = r;
            if (!o) return !1;
            if (r.parent.isTextblock) {
                if (n ? !n.endOfTextblock("backward", e) : r.parentOffset > 0) return !1;
                i = Zo(r)
            }
            let s = i && i.nodeBefore;
            return !(!s || !at.isSelectable(s) || (t && t(e.tr.setSelection(at.create(e.doc, i.pos - s.nodeSize)).scrollIntoView()), 0))
        }),
        hi = di(Go, Qo, (e, t, n) => {
            let {
                $head: r,
                empty: o
            } = e.selection, i = r;
            if (!o) return !1;
            if (r.parent.isTextblock) {
                if (n ? !n.endOfTextblock("forward", e) : r.parentOffset < r.parent.content.size) return !1;
                i = Yo(r)
            }
            let s = i && i.nodeAfter;
            return !(!s || !at.isSelectable(s) || (t && t(e.tr.setSelection(at.create(e.doc, i.pos)).scrollIntoView()), 0))
        });
    const fi = {
            Enter: di(ei, (e, t) => {
                let n = e.selection,
                    {
                        $from: r,
                        $to: o
                    } = n;
                if (n instanceof ct || r.parent.inlineContent || o.parent.inlineContent) return !1;
                let i = ti(o.parent.contentMatchAt(o.indexAfter()));
                if (!i || !i.isTextblock) return !1;
                if (t) {
                    let n = (!r.parentOffset && o.index() < o.parent.childCount ? r : o).pos,
                        s = e.tr.insert(n, i.createAndFill());
                    s.setSelection(it.create(s.doc, n + 1)), t(s.scrollIntoView())
                }
                return !0
            }, (e, t) => {
                let {
                    $cursor: n
                } = e.selection;
                if (!n || n.parent.content.size) return !1;
                if (n.depth > 1 && n.after() != n.end(-1)) {
                    let r = n.before();
                    if (Fe(e.doc, r)) return t && t(e.tr.split(r).scrollIntoView()), !0
                }
                let r = n.blockRange(),
                    o = r && Ie(r);
                return null != o && (t && t(e.tr.lift(r, o).scrollIntoView()), !0)
            }, (e, t) => {
                if (e.selection instanceof at && e.selection.node.isBlock) {
                    let {
                        $from: n
                    } = e.selection;
                    return !(!n.parentOffset || !Fe(e.doc, n.pos) || (t && t(e.tr.split(n.pos).scrollIntoView()), 0))
                }
                if (!e.selection.$from.depth) return !1;
                let n = e.tr;
                !e.selection.empty && (e.selection instanceof it || e.selection instanceof ct) && n.deleteSelection();
                let r, o, {
                        $from: i
                    } = n.selection,
                    s = n.steps.length,
                    a = [],
                    l = !1,
                    c = !1;
                for (let e = i.depth;; e--) {
                    if (i.node(e).isBlock) {
                        l = i.end(e) == i.pos + (i.depth - e), c = i.start(e) == i.pos - (i.depth - e), o = ti(i.node(e - 1).contentMatchAt(i.indexAfter(e - 1)));
                        let t = ri;
                        a.unshift(t || (l && o ? {
                            type: o
                        } : null)), r = e;
                        break
                    }
                    if (1 == e) return !1;
                    a.unshift(null)
                }
                let u = i.pos,
                    d = Fe(n.doc, u, a.length, a);
                if (d || (a[0] = o ? {
                        type: o
                    } : null, d = Fe(n.doc, u, a.length, a)), !d) return !1;
                if (n.split(u, a.length, a), !l && c && i.node(r).type != o) {
                    let e = n.mapping.slice(s),
                        t = e.map(i.before(r)),
                        a = n.doc.resolve(t);
                    o && i.node(r - 1).canReplaceWith(a.index(), a.index() + 1, o) && n.setNodeMarkup(e.map(i.before(r)), o)
                }
                return t && t(n.scrollIntoView()), !0
            }),
            "Mod-Enter": ni,
            Backspace: pi,
            "Mod-Backspace": pi,
            "Shift-Backspace": pi,
            Delete: hi,
            "Mod-Delete": hi,
            "Mod-a": oi
        },
        mi = {
            "Ctrl-h": fi.Backspace,
            "Alt-Backspace": fi["Mod-Backspace"],
            "Ctrl-d": fi.Delete,
            "Ctrl-Alt-Backspace": fi["Mod-Delete"],
            "Alt-Delete": fi["Mod-Delete"],
            "Alt-d": fi["Mod-Delete"],
            "Ctrl-a": ai,
            "Ctrl-e": li
        };
    for (let e in fi) mi[e] = fi[e];
    const gi = ("undefined" != typeof navigator ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) : "undefined" != typeof os && os.platform && "darwin" == os.platform()) ? mi : fi;
    class vi {
        constructor(e, t, n = {}) {
            var r;
            this.match = e, this.match = e, this.handler = "string" == typeof t ? (r = t, function(e, t, n, o) {
                let i = r;
                if (t[1]) {
                    let e = t[0].lastIndexOf(t[1]);
                    i += t[0].slice(e + t[1].length);
                    let r = (n += e) - o;
                    r > 0 && (i = t[0].slice(e - r, e) + i, n = o)
                }
                return e.tr.insertText(i, n, o)
            }) : t, this.undoable = !1 !== n.undoable, this.inCode = n.inCode || !1, this.inCodeMark = !1 !== n.inCodeMark
        }
    }

    function yi({
        rules: e
    }) {
        let t = new wt({
            state: {
                init: () => null,
                apply(e, t) {
                    return e.getMeta(this) || (e.selectionSet || e.docChanged ? null : t)
                }
            },
            props: {
                handleTextInput: (n, r, o, i) => bi(n, r, o, i, e, t),
                handleDOMEvents: {
                    compositionend: n => {
                        setTimeout(() => {
                            let {
                                $cursor: r
                            } = n.state.selection;
                            r && bi(n, r.pos, r.pos, "", e, t)
                        })
                    }
                }
            },
            isInputRules: !0
        });
        return t
    }

    function bi(e, t, n, r, o, i) {
        if (e.composing) return !1;
        let s = e.state,
            a = s.doc.resolve(t),
            l = a.parent.textBetween(Math.max(0, a.parentOffset - 500), a.parentOffset, null, "￼") + r;
        for (let c = 0; c < o.length; c++) {
            let u = o[c];
            if (!u.inCodeMark && a.marks().some(e => e.type.spec.code)) continue;
            if (a.parent.type.spec.code) {
                if (!u.inCode) continue
            } else if ("only" === u.inCode) continue;
            let d = u.match.exec(l);
            if (!d || d[0].length < r.length) continue;
            let p = t - (d[0].length - r.length);
            if (!u.inCodeMark) {
                let e = !1;
                if (s.doc.nodesBetween(p, a.pos, t => {
                        t.isInline && t.marks.some(e => e.type.spec.code) && (e = !0)
                    }), e) continue
            }
            let h = u.handler(s, d, p, n);
            if (h) return u.undoable && h.setMeta(i, {
                transform: h,
                from: t,
                to: n,
                text: r
            }), e.dispatch(h), !0
        }
        return !1
    }
    const wi = (e, t) => {
        let n = e.plugins;
        for (let r = 0; r < n.length; r++) {
            let o, i = n[r];
            if (i.spec.isInputRules && (o = i.getState(e))) {
                if (t) {
                    let n = e.tr,
                        r = o.transform;
                    for (let e = r.steps.length - 1; e >= 0; e--) n.step(r.steps[e].invert(r.docs[e]));
                    if (o.text) {
                        let t = n.doc.resolve(o.from).marks();
                        n.replaceWith(o.from, o.to, e.schema.text(o.text, t))
                    } else n.delete(o.from, o.to);
                    t(n)
                }
                return !0
            }
        }
        return !1
    };
    new vi(/--$/, "—", {
        inCodeMark: !1
    }), new vi(/\.\.\.$/, "…", {
        inCodeMark: !1
    }), new vi(/(?:^|[\s\{\[\(\<'"\u2018\u201C])(")$/, "“", {
        inCodeMark: !1
    }), new vi(/"$/, "”", {
        inCodeMark: !1
    }), new vi(/(?:^|[\s\{\[\(\<'"\u2018\u201C])(')$/, "‘", {
        inCodeMark: !1
    }), new vi(/'$/, "’", {
        inCodeMark: !1
    });
    var ki = 200,
        xi = function() {};
    xi.prototype.append = function(e) {
        return e.length ? (e = xi.from(e), !this.length && e || e.length < ki && this.leafAppend(e) || this.length < ki && e.leafPrepend(this) || this.appendInner(e)) : this
    }, xi.prototype.prepend = function(e) {
        return e.length ? xi.from(e).append(this) : this
    }, xi.prototype.appendInner = function(e) {
        return new Ti(this, e)
    }, xi.prototype.slice = function(e, t) {
        return void 0 === e && (e = 0), void 0 === t && (t = this.length), e >= t ? xi.empty : this.sliceInner(Math.max(0, e), Math.min(this.length, t))
    }, xi.prototype.get = function(e) {
        if (!(e < 0 || e >= this.length)) return this.getInner(e)
    }, xi.prototype.forEach = function(e, t, n) {
        void 0 === t && (t = 0), void 0 === n && (n = this.length), t <= n ? this.forEachInner(e, t, n, 0) : this.forEachInvertedInner(e, t, n, 0)
    }, xi.prototype.map = function(e, t, n) {
        void 0 === t && (t = 0), void 0 === n && (n = this.length);
        var r = [];
        return this.forEach(function(t, n) {
            return r.push(e(t, n))
        }, t, n), r
    }, xi.from = function(e) {
        return e instanceof xi ? e : e && e.length ? new Ci(e) : xi.empty
    };
    var Ci = function(e) {
        function t(t) {
            e.call(this), this.values = t
        }
        e && (t.__proto__ = e), t.prototype = Object.create(e && e.prototype), t.prototype.constructor = t;
        var n = {
            length: {
                configurable: !0
            },
            depth: {
                configurable: !0
            }
        };
        return t.prototype.flatten = function() {
            return this.values
        }, t.prototype.sliceInner = function(e, n) {
            return 0 == e && n == this.length ? this : new t(this.values.slice(e, n))
        }, t.prototype.getInner = function(e) {
            return this.values[e]
        }, t.prototype.forEachInner = function(e, t, n, r) {
            for (var o = t; o < n; o++)
                if (!1 === e(this.values[o], r + o)) return !1
        }, t.prototype.forEachInvertedInner = function(e, t, n, r) {
            for (var o = t - 1; o >= n; o--)
                if (!1 === e(this.values[o], r + o)) return !1
        }, t.prototype.leafAppend = function(e) {
            if (this.length + e.length <= ki) return new t(this.values.concat(e.flatten()))
        }, t.prototype.leafPrepend = function(e) {
            if (this.length + e.length <= ki) return new t(e.flatten().concat(this.values))
        }, n.length.get = function() {
            return this.values.length
        }, n.depth.get = function() {
            return 0
        }, Object.defineProperties(t.prototype, n), t
    }(xi);
    xi.empty = new Ci([]);
    var Ti = function(e) {
        function t(t, n) {
            e.call(this), this.left = t, this.right = n, this.length = t.length + n.length, this.depth = Math.max(t.depth, n.depth) + 1
        }
        return e && (t.__proto__ = e), t.prototype = Object.create(e && e.prototype), t.prototype.constructor = t, t.prototype.flatten = function() {
            return this.left.flatten().concat(this.right.flatten())
        }, t.prototype.getInner = function(e) {
            return e < this.left.length ? this.left.get(e) : this.right.get(e - this.left.length)
        }, t.prototype.forEachInner = function(e, t, n, r) {
            var o = this.left.length;
            return !(t < o && !1 === this.left.forEachInner(e, t, Math.min(n, o), r)) && !(n > o && !1 === this.right.forEachInner(e, Math.max(t - o, 0), Math.min(this.length, n) - o, r + o)) && void 0
        }, t.prototype.forEachInvertedInner = function(e, t, n, r) {
            var o = this.left.length;
            return !(t > o && !1 === this.right.forEachInvertedInner(e, t - o, Math.max(n, o) - o, r + o)) && !(n < o && !1 === this.left.forEachInvertedInner(e, Math.min(t, o), n, r)) && void 0
        }, t.prototype.sliceInner = function(e, t) {
            if (0 == e && t == this.length) return this;
            var n = this.left.length;
            return t <= n ? this.left.slice(e, t) : e >= n ? this.right.slice(e - n, t - n) : this.left.slice(e, n).append(this.right.slice(0, t - n))
        }, t.prototype.leafAppend = function(e) {
            var n = this.right.leafAppend(e);
            if (n) return new t(this.left, n)
        }, t.prototype.leafPrepend = function(e) {
            var n = this.left.leafPrepend(e);
            if (n) return new t(n, this.right)
        }, t.prototype.appendInner = function(e) {
            return this.left.depth >= Math.max(this.right.depth, e.depth) + 1 ? new t(this.left, new t(this.right, e)) : new t(this, e)
        }, t
    }(xi);
    const Mi = xi;
    class Si {
        constructor(e, t) {
            this.items = e, this.eventCount = t
        }
        popEvent(e, t) {
            if (0 == this.eventCount) return null;
            let n, r, o = this.items.length;
            for (;; o--)
                if (this.items.get(o - 1).selection) {
                    --o;
                    break
                } t && (n = this.remapping(o, this.items.length), r = n.maps.length);
            let i, s, a = e.tr,
                l = [],
                c = [];
            return this.items.forEach((e, t) => {
                if (!e.step) return n || (n = this.remapping(o, t + 1), r = n.maps.length), r--, void c.push(e);
                if (n) {
                    c.push(new Ei(e.map));
                    let t, o = e.step.map(n.slice(r));
                    o && a.maybeStep(o).doc && (t = a.mapping.maps[a.mapping.maps.length - 1], l.push(new Ei(t, void 0, void 0, l.length + c.length))), r--, t && n.appendMap(t, r)
                } else a.maybeStep(e.step);
                return e.selection ? (i = n ? e.selection.map(n.slice(r)) : e.selection, s = new Si(this.items.slice(0, o).append(c.reverse().concat(l)), this.eventCount - 1), !1) : void 0
            }, this.items.length, 0), {
                remaining: s,
                transform: a,
                selection: i
            }
        }
        addTransform(e, t, n, r) {
            let o = [],
                i = this.eventCount,
                s = this.items,
                a = !r && s.length ? s.get(s.length - 1) : null;
            for (let n = 0; n < e.steps.length; n++) {
                let l, c = e.steps[n].invert(e.docs[n]),
                    u = new Ei(e.mapping.maps[n], c, t);
                (l = a && a.merge(u)) && (u = l, n ? o.pop() : s = s.slice(0, s.length - 1)), o.push(u), t && (i++, t = void 0), r || (a = u)
            }
            let l = i - n.depth;
            return l > Oi && (s = function(e, t) {
                let n;
                return e.forEach((e, r) => {
                    if (e.selection && 0 == t--) return n = r, !1
                }), e.slice(n)
            }(s, l), i -= l), new Si(s.append(o), i)
        }
        remapping(e, t) {
            let n = new be;
            return this.items.forEach((t, r) => {
                let o = null != t.mirrorOffset && r - t.mirrorOffset >= e ? n.maps.length - t.mirrorOffset : void 0;
                n.appendMap(t.map, o)
            }, e, t), n
        }
        addMaps(e) {
            return 0 == this.eventCount ? this : new Si(this.items.append(e.map(e => new Ei(e))), this.eventCount)
        }
        rebased(e, t) {
            if (!this.eventCount) return this;
            let n = [],
                r = Math.max(0, this.items.length - t),
                o = e.mapping,
                i = e.steps.length,
                s = this.eventCount;
            this.items.forEach(e => {
                e.selection && s--
            }, r);
            let a = t;
            this.items.forEach(t => {
                let r = o.getMirror(--a);
                if (null == r) return;
                i = Math.min(i, r);
                let l = o.maps[r];
                if (t.step) {
                    let i = e.steps[r].invert(e.docs[r]),
                        c = t.selection && t.selection.map(o.slice(a + 1, r));
                    c && s++, n.push(new Ei(l, i, c))
                } else n.push(new Ei(l))
            }, r);
            let l = [];
            for (let e = t; e < i; e++) l.push(new Ei(o.maps[e]));
            let c = this.items.slice(0, r).append(l).append(n),
                u = new Si(c, s);
            return u.emptyItemCount() > 500 && (u = u.compress(this.items.length - n.length)), u
        }
        emptyItemCount() {
            let e = 0;
            return this.items.forEach(t => {
                t.step || e++
            }), e
        }
        compress(e = this.items.length) {
            let t = this.remapping(0, e),
                n = t.maps.length,
                r = [],
                o = 0;
            return this.items.forEach((i, s) => {
                if (s >= e) r.push(i), i.selection && o++;
                else if (i.step) {
                    let e = i.step.map(t.slice(n)),
                        s = e && e.getMap();
                    if (n--, s && t.appendMap(s, n), e) {
                        let a = i.selection && i.selection.map(t.slice(n));
                        a && o++;
                        let l, c = new Ei(s.invert(), e, a),
                            u = r.length - 1;
                        (l = r.length && r[u].merge(c)) ? r[u] = l: r.push(c)
                    }
                } else i.map && n--
            }, this.items.length, 0), new Si(Mi.from(r.reverse()), o)
        }
    }
    Si.empty = new Si(Mi.empty, 0);
    class Ei {
        constructor(e, t, n, r) {
            this.map = e, this.step = t, this.selection = n, this.mirrorOffset = r
        }
        merge(e) {
            if (this.step && e.step && !e.selection) {
                let t = e.step.merge(this.step);
                if (t) return new Ei(t.getMap().invert(), t, this.selection)
            }
        }
    }
    class Ni {
        constructor(e, t, n, r, o) {
            this.done = e, this.undone = t, this.prevRanges = n, this.prevTime = r, this.prevComposition = o
        }
    }
    const Oi = 20;

    function Di(e) {
        let t = [];
        for (let n = e.length - 1; n >= 0 && 0 == t.length; n--) e[n].forEach((e, n, r, o) => t.push(r, o));
        return t
    }

    function Ai(e, t) {
        if (!e) return null;
        let n = [];
        for (let r = 0; r < e.length; r += 2) {
            let o = t.map(e[r], 1),
                i = t.map(e[r + 1], -1);
            o <= i && n.push(o, i)
        }
        return n
    }
    let Li = !1,
        Ii = null;

    function Ri(e) {
        let t = e.plugins;
        if (Ii != t) {
            Li = !1, Ii = t;
            for (let e = 0; e < t.length; e++)
                if (t[e].spec.historyPreserveItems) {
                    Li = !0;
                    break
                }
        }
        return Li
    }
    const Pi = new Ct("history"),
        Bi = new Ct("closeHistory");

    function Fi(e = {}) {
        return e = {
            depth: e.depth || 100,
            newGroupDelay: e.newGroupDelay || 500
        }, new wt({
            key: Pi,
            state: {
                init: () => new Ni(Si.empty, Si.empty, null, 0, -1),
                apply: (t, n, r) => function(e, t, n, r) {
                    let o, i = n.getMeta(Pi);
                    if (i) return i.historyState;
                    n.getMeta(Bi) && (e = new Ni(e.done, e.undone, null, 0, -1));
                    let s = n.getMeta("appendedTransaction");
                    if (0 == n.steps.length) return e;
                    if (s && s.getMeta(Pi)) return s.getMeta(Pi).redo ? new Ni(e.done.addTransform(n, void 0, r, Ri(t)), e.undone, Di(n.mapping.maps), e.prevTime, e.prevComposition) : new Ni(e.done, e.undone.addTransform(n, void 0, r, Ri(t)), null, e.prevTime, e.prevComposition);
                    if (!1 === n.getMeta("addToHistory") || s && !1 === s.getMeta("addToHistory")) return (o = n.getMeta("rebased")) ? new Ni(e.done.rebased(n, o), e.undone.rebased(n, o), Ai(e.prevRanges, n.mapping), e.prevTime, e.prevComposition) : new Ni(e.done.addMaps(n.mapping.maps), e.undone.addMaps(n.mapping.maps), Ai(e.prevRanges, n.mapping), e.prevTime, e.prevComposition);
                    {
                        let o = n.getMeta("composition"),
                            i = 0 == e.prevTime || !s && e.prevComposition != o && (e.prevTime < (n.time || 0) - r.newGroupDelay || ! function(e, t) {
                                if (!t) return !1;
                                if (!e.docChanged) return !0;
                                let n = !1;
                                return e.mapping.maps[0].forEach((e, r) => {
                                    for (let o = 0; o < t.length; o += 2) e <= t[o + 1] && r >= t[o] && (n = !0)
                                }), n
                            }(n, e.prevRanges)),
                            a = s ? Ai(e.prevRanges, n.mapping) : Di(n.mapping.maps);
                        return new Ni(e.done.addTransform(n, i ? t.selection.getBookmark() : void 0, r, Ri(t)), Si.empty, a, n.time, o ?? e.prevComposition)
                    }
                }(n, r, t, e)
            },
            config: e,
            props: {
                handleDOMEvents: {
                    beforeinput(e, t) {
                        let n = t.inputType,
                            r = "historyUndo" == n ? zi : "historyRedo" == n ? qi : null;
                        return !(!r || !e.editable) && (t.preventDefault(), r(e.state, e.dispatch))
                    }
                }
            }
        })
    }

    function Hi(e, t) {
        return (n, r) => {
            let o = Pi.getState(n);
            if (!o || 0 == (e ? o.undone : o.done).eventCount) return !1;
            if (r) {
                let i = function(e, t, n) {
                    let r = Ri(t),
                        o = Pi.get(t).spec.config,
                        i = (n ? e.undone : e.done).popEvent(t, r);
                    if (!i) return null;
                    let s = i.selection.resolve(i.transform.doc),
                        a = (n ? e.done : e.undone).addTransform(i.transform, t.selection.getBookmark(), o, r),
                        l = new Ni(n ? a : i.remaining, n ? i.remaining : a, null, 0, -1);
                    return i.transform.setSelection(s).setMeta(Pi, {
                        redo: n,
                        historyState: l
                    })
                }(o, n, e);
                i && r(t ? i.scrollIntoView() : i)
            }
            return !0
        }
    }
    const zi = Hi(!1, !0),
        qi = Hi(!0, !0);
    Hi(!1, !1), Hi(!0, !1);
    var Vi = function(e, t) {
        return Vi = Object.setPrototypeOf || {
            __proto__: []
        }
        instanceof Array && function(e, t) {
            e.__proto__ = t
        } || function(e, t) {
            for (var n in t) Object.prototype.hasOwnProperty.call(t, n) && (e[n] = t[n])
        }, Vi(e, t)
    };

    function ji(e, t) {
        if ("function" != typeof t && null !== t) throw new TypeError("Class extends value " + String(t) + " is not a constructor or null");

        function n() {
            this.constructor = e
        }
        Vi(e, t), e.prototype = null === t ? Object.create(t) : (n.prototype = t.prototype, new n)
    }
    var $i = function() {
        return $i = Object.assign || function(e) {
            for (var t, n = 1, r = arguments.length; n < r; n++)
                for (var o in t = arguments[n]) Object.prototype.hasOwnProperty.call(t, o) && (e[o] = t[o]);
            return e
        }, $i.apply(this, arguments)
    };

    function _i(e, t, n) {
        if (n || 2 === arguments.length)
            for (var r, o = 0, i = t.length; o < i; o++) !r && o in t || (r || (r = Array.prototype.slice.call(t, 0, o)), r[o] = t[o]);
        return e.concat(r || Array.prototype.slice.call(t))
    }

    function Ui(e, t) {
        return Object.defineProperty ? Object.defineProperty(e, "raw", {
            value: t
        }) : e.raw = t, e
    }
    var Wi = function(e, t, n) {
            var r;
            for (r in n = n || null, e)
                if (e.hasOwnProperty(r) && !1 === t.call(n, e[r], r, e)) break
        },
        Ji = function(e, t) {
            var n, r, o, i, s = Object.prototype.hasOwnProperty;
            for (o = 1, i = arguments.length; o < i; o += 1)
                for (r in n = arguments[o]) s.call(n, r) && (e[r] = n[r]);
            return e
        },
        Ki = function(e) {
            return "string" == typeof e || e instanceof String
        },
        Gi = function(e) {
            return e instanceof Array
        },
        Xi = function(e, t, n) {
            var r = 0,
                o = e.length;
            for (n = n || null; r < o && !1 !== t.call(n, e[r], r, e); r += 1);
        },
        Zi = Gi,
        Qi = Xi,
        Yi = Wi,
        es = function(e, t, n) {
            Zi(e) ? Qi(e, t, n) : Yi(e, t, n)
        },
        ts = Ki,
        ns = es,
        rs = function(e, t, n) {
            var r = e.style;
            ts(t) ? r[t] = n : ns(t, function(e, t) {
                r[t] = e
            })
        },
        is = Gi,
        ss = function(e, t, n) {
            var r, o;
            if (n = n || 0, !is(t)) return -1;
            if (Array.prototype.indexOf) return Array.prototype.indexOf.call(t, e, n);
            for (o = t.length, r = n; n >= 0 && r < o; r += 1)
                if (t[r] === e) return r;
            return -1
        },
        as = function(e) {
            return void 0 === e
        },
        ls = as,
        cs = function(e) {
            return e && e.className ? ls(e.className.baseVal) ? e.className : e.className.baseVal : ""
        },
        us = Gi,
        ds = as,
        ps = function(e, t) {
            t = (t = us(t) ? t.join(" ") : t).replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ""), ds(e.className.baseVal) ? e.className = t : e.className.baseVal = t
        },
        hs = es,
        fs = ss,
        ms = cs,
        gs = ps,
        vs = function(e) {
            var t, n = Array.prototype.slice.call(arguments, 1),
                r = e.classList,
                o = [];
            r ? hs(n, function(t) {
                e.classList.add(t)
            }) : ((t = ms(e)) && (n = [].concat(t.split(/\s+/), n)), hs(n, function(e) {
                fs(e, o) < 0 && o.push(e)
            }), gs(e, o))
        },
        ys = Xi,
        bs = ss,
        ws = cs,
        ks = ps,
        xs = function(e) {
            var t, n, r = Array.prototype.slice.call(arguments, 1),
                o = e.classList;
            o ? ys(r, function(e) {
                o.remove(e)
            }) : (t = ws(e).split(/\s+/), n = [], ys(t, function(e) {
                bs(e, r) < 0 && n.push(e)
            }), ks(e, n))
        },
        Cs = function(e) {
            return "number" == typeof e || e instanceof Number
        },
        Ts = function(e) {
            return null === e
        },
        Ms = Wi,
        Ss = as,
        Es = function(e, t) {
            var n = location.hostname,
                r = "TOAST UI " + e + " for " + n + ": Statistics",
                o = window.localStorage.getItem(r);
            (Ss(window.tui) || !1 !== window.tui.usageStatistics) && (o && ! function(e) {
                return (new Date).getTime() - e > 6048e5
            }(o) || (window.localStorage.setItem(r, (new Date).getTime()), setTimeout(function() {
                var r, o, i, s;
                "interactive" !== document.readyState && "complete" !== document.readyState || (r = "https://www.google-analytics.com/collect", o = {
                    v: 1,
                    t: "event",
                    tid: t,
                    cid: n,
                    dp: n,
                    dh: e,
                    el: e,
                    ec: "use"
                }, i = document.createElement("img"), s = "", Ms(o, function(e, t) {
                    s += "&" + t + "=" + e
                }), s = s.substring(1), i.src = r + "?" + s, i.style.display = "none", document.body.appendChild(i), document.body.removeChild(i))
            }, 1e3)))
        };
    /Mac/.test(navigator.platform);
    var Ns = /[\u0020]+/g,
        Os = /[>(){}[\]+-.!#|]/g,
        Ds = /<([a-zA-Z_][a-zA-Z0-9\-._]*)(\s|[^\\>])*\/?>|<(\/)([a-zA-Z_][a-zA-Z0-9\-._]*)\s*\/?>|<!--[^-]+-->|<([a-zA-Z_][a-zA-Z0-9\-.:/]*)>/g,
        As = /\\[!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~\\]/g,
        Ls = /[*_~`]/g,
        Is = /!\[.*\]\(.*\)/g,
        Rs = /[[\]]/g,
        Ps = /(?:^|[^\\])\\(?!\\)/g,
        Bs = new RegExp('[&<>"]', "g");

    function Fs(e) {
        switch (e) {
            case "&":
                return "&amp;";
            case "<":
                return "&lt;";
            case ">":
                return "&gt;";
            case '"':
                return "&quot;";
            default:
                return e
        }
    }

    function Hs(e) {
        return Bs.test(e) ? e.replace(Bs, Fs) : e
    }

    function zs(e, t) {
        return -1 !== e.indexOf(t)
    }
    var qs = ["rel", "target", "hreflang", "type"],
        Vs = {
            codeblock: /(^ {4}[^\n]+\n*)+/,
            thematicBreak: /^ *((\* *){3,}|(- *){3,} *|(_ *){3,}) */,
            atxHeading: /^(#{1,6}) +[\s\S]+/,
            seTextheading: /^([^\n]+)\n *(=|-){2,} */,
            blockquote: /^( *>[^\n]+.*)+/,
            list: /^ *(\*+|-+|\d+\.) [\s\S]+/,
            def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? */,
            link: /!?\[.*\]\(.*\)/,
            reflink: /!?\[.*\]\s*\[([^\]]*)\]/,
            verticalBar: /\u007C/,
            fencedCodeblock: /^((`|~){3,})/
        };

    function js(e) {
        if (!e) return null;
        var t = {};
        return qs.forEach(function(n) {
            as(e[n]) || (t[n] = e[n])
        }), t
    }

    function $s(e, t) {
        for (var n = "", r = 0; r < t; r += 1) n += e;
        return n
    }

    function _s(e) {
        for (var t = [], n = Is.exec(e); n;) t.push([n.index, n.index + n[0].length]), n = Is.exec(e);
        return e.replace(Rs, function(e, n) {
            return t.some(function(e) {
                return n > e[0] && n < e[1]
            }) ? e : "\\" + e
        })
    }

    function Us(e) {
        var t = function(e) {
                return "\\" + e
            },
            n = e.replace(Ns, " ");
        return As.test(n) && (n = n.replace(As, t)), Ps.test(n) && (n = n.replace(Ps, function(e) {
                return e + "\\"
            })), n = n.replace(Ls, t), Ds.test(n) && (n = n.replace(Ds, t)),
            function(e) {
                var t = !1;
                return Wi(Vs, function(n) {
                    return n.test(e) && (t = !0), !t
                }), t
            }(n) && (n = n.replace(Os, t)), n
    }

    function Ws(e) {
        return Ts(e) || as(e)
    }

    function Js(e, t) {
        if (null === e && e === t) return !0;
        if ("object" != typeof e || "object" != typeof t || Ws(e) || Ws(t)) return e === t;
        for (var n in e)
            if (e[n] !== t[n]) return !1;
        for (var n in t)
            if (!(n in e)) return !1;
        return !0
    }

    function Ks(e) {
        return e[e.length - 1]
    }

    function Gs(e) {
        return "object" == typeof e && null !== e
    }

    function Xs(e, t) {
        var n = $i({}, e);
        return e && t && Object.keys(t).forEach(function(e) {
            Gs(n[e]) ? Array.isArray(t[e]) ? n[e] = Zs(t[e]) : n.hasOwnProperty(e) ? n[e] = Xs(n[e], t[e]) : n[e] = Qs(t[e]) : n[e] = t[e]
        }), n
    }

    function Zs(e) {
        return e.map(function(e) {
            return Gs(e) ? Array.isArray(e) ? Zs(e) : Qs(e) : e
        })
    }

    function Qs(e) {
        var t = Object.keys(e);
        return t.length ? t.reduce(function(t, n) {
            return Gs(e[n]) ? t[n] = Array.isArray(e[n]) ? Zs(e[n]) : Qs(e[n]) : t[n] = e[n], t
        }, {}) : e
    }

    function Ys(e, t) {
        return void 0 === t && (t = {}), Object.keys(t).forEach(function(n) {
            e.hasOwnProperty(n) && "object" == typeof e[n] ? Array.isArray(t[n]) ? e[n] = t[n] : Ys(e[n], t[n]) : e[n] = t[n]
        }), e
    }

    function ea(e, t) {
        return e > t ? [t, e] : [e, t]
    }
    var ta = Xi,
        na = function(e) {
            var t;
            try {
                t = Array.prototype.slice.call(e)
            } catch (n) {
                t = [], ta(e, function(e) {
                    t.push(e)
                })
            }
            return t
        };

    function ra(e, t) {
        var n = e.nodes.paragraph;
        return t ? n.create(null, Ki(t) ? e.text(t) : t) : n.createAndFill()
    }

    function oa(e, t, n) {
        return e.text(t, n)
    }

    function ia(e, t, n) {
        void 0 === n && (n = t);
        var r = e.doc.content.size,
            o = r > 0 ? r - 1 : 1;
        return it.create(e.doc, Math.min(t, o), Math.min(n, o))
    }

    function sa(e, t, n) {
        var r = t.pos;
        return e.replaceWith(r, r, ra(n)), e.setSelection(ia(e, r + 1))
    }

    function aa(e) {
        for (var t = e.state, n = e.from, r = e.startIndex, o = e.endIndex, i = e.createText, s = t.tr, a = t.doc, c = t.schema, u = r; u <= o; u += 1) {
            var d = a.child(u),
                p = d.nodeSize,
                h = d.textContent,
                f = d.content,
                m = i(h),
                g = m ? oa(c, m) : l.empty,
                v = s.mapping.map(n),
                y = v + f.size;
            s.replaceWith(v, y, g), n += p
        }
        return s
    }

    function la(e, t, n, r) {
        var o = n.length;
        e.split(t).delete(t - o, t).insert(e.mapping.map(t), r).setSelection(ia(e, e.mapping.map(t) - o))
    }

    function ca(e) {
        return e.sourcepos[0][0]
    }

    function ua(e) {
        return e.sourcepos[1][0]
    }

    function da(e) {
        return e.sourcepos[0][1]
    }

    function pa(e) {
        return e.sourcepos[1][1]
    }

    function ha(e) {
        var t = e.type;
        return "strike" === t || "strong" === t || "emph" === t || "code" === t || "link" === t || "image" === t
    }

    function fa(e) {
        return e && ("item" === e.type || "list" === e.type)
    }

    function ma(e) {
        return fa(e) && "ordered" === e.listData.type
    }

    function ga(e) {
        return fa(e) && "ordered" !== e.listData.type
    }

    function va(e) {
        return e && ("tableCell" === e.type || "tableDelimCell" === e.type)
    }

    function ya(e, t, n) {
        for (void 0 === n && (n = !0), e = n ? e : e.parent; e && "document" !== e.type;) {
            if (t(e)) return e;
            e = e.parent
        }
        return null
    }

    function ba(e, t) {
        return [e[0], e[1] + t]
    }

    function wa(e, t) {
        return [e[0], t]
    }

    function ka(e) {
        var t = e.firstChild.literal;
        switch (e.type) {
            case "emph":
                return "*" + t + "*";
            case "strong":
                return "**" + t + "**";
            case "strike":
                return "~~" + t + "~~";
            case "code":
                return "`" + t + "`";
            case "link":
            case "image":
                var n = e,
                    r = n.destination,
                    o = n.title;
                return ("link" === e.type ? "" : "!") + "[" + t + "](" + r + (o ? ' "' + o + '"' : "") + ")";
            default:
                return null
        }
    }

    function xa(e) {
        switch (e.type) {
            case "document":
            case "blockQuote":
            case "list":
            case "item":
            case "paragraph":
            case "heading":
            case "emph":
            case "strong":
            case "strike":
            case "link":
            case "image":
            case "table":
            case "tableHead":
            case "tableBody":
            case "tableRow":
            case "tableCell":
            case "tableDelimRow":
            case "customInline":
                return !0;
            default:
                return !1
        }
    }

    function Ca(e) {
        for (var t = [], n = e.walker(), r = null; r = n.next();) {
            var o = r.node;
            "text" === o.type && t.push(o.literal)
        }
        return t.join("")
    }
    var Ta = [],
        Ma = {},
        Sa = /\$\$widget\d+\s/;

    function Ea(e) {
        var t = e.search(Sa);
        if (-1 !== t) {
            var n = e.substring(t).replace(Sa, "").replace("$$", "");
            e = e.substring(0, t), e += Ea(n)
        }
        return e
    }

    function Na(e, t) {
        return "$$" + e + " " + t + "$$"
    }

    function Oa(e, t) {
        var n = Ma[e],
            r = n.rule,
            o = n.toDOM,
            i = Ea(t).match(r);
        return i && (t = i[0]), o(t)
    }

    function Da(e) {
        (Ta = e).forEach(function(e, t) {
            Ma["widget" + t] = e
        })
    }

    function Aa(e, t, n, r) {
        return e.concat(La(t, n, r))
    }

    function La(e, t, n) {
        void 0 === n && (n = 0);
        var r = [],
            o = (Ta[n] || {}).rule,
            i = n + 1;
        if (e = Ea(e), o && o.test(e)) {
            for (var s = void 0; - 1 !== (s = e.search(o));) {
                var a = e.substring(0, s);
                a && (r = Aa(r, a, t, i));
                var l = (e = e.substring(s)).match(o)[0],
                    c = "widget" + n;
                r.push(t.nodes.widget.create({
                    info: c
                }, t.text(Na(c, l)))), e = e.substring(l.length)
            }
            e && (r = Aa(r, e, t, i))
        } else e && (r = n < Ta.length - 1 ? Aa(r, e, t, i) : [t.text(e)]);
        return r
    }

    function Ia(e) {
        for (var t, n = "", r = e.walker(); t = r.next();) {
            var o = t.node;
            t.entering && (o !== e && "text" !== o.type ? (n += ka(o), r.resumeAt(e, !1), r.next()) : "text" === o.type && (n += o.literal))
        }
        return n
    }

    function Ra() {
        return {
            deleteSelection: function() {
                return Go
            },
            selectAll: function() {
                return oi
            },
            undo: function() {
                return zi
            },
            redo: function() {
                return qi
            }
        }
    }
    var Pa = ss,
        Ba = cs,
        Fa = function(e, t) {
            var n;
            return e.classList ? e.classList.contains(t) : (n = Ba(e).split(/\s+/), Pa(t, n) > -1)
        },
        Ha = ss,
        za = na,
        qa = Element.prototype,
        Va = qa.matches || qa.webkitMatchesSelector || qa.mozMatchesSelector || qa.msMatchesSelector || function(e) {
            var t = this.document || this.ownerDocument;
            return Ha(this, za(t.querySelectorAll(e))) > -1
        },
        ja = "[A-Za-z][A-Za-z0-9-]*",
        $a = "(?:\\s+[a-zA-Z_:][a-zA-Z0-9:._-]*(?:\\s*=\\s*(?:[^\"'=<>`\\x00-\\x20]+|'[^']*'|\"[^\"]*\"))?)",
        _a = "<(" + ja + ")(" + $a + ")*\\s*/?>",
        Ua = "(?:" + _a + "|</(" + ja + ")\\s*[>])",
        Wa = new RegExp("^" + Ua, "i"),
        Ja = /<br\s*\/*>/i,
        Ka = /<! ---->|<!--(?:-?[^>-])(?:-?[^-])*-->/,
        Ga = "</p><p>";

    function Xa(e, t, n) {
        var r = parseInt(e.left, 10),
            o = parseInt(e.top, 10),
            i = parseInt(e.width, 10) + parseInt(e.paddingLeft, 10) + parseInt(e.paddingRight, 10),
            s = parseInt(e.height, 10) + parseInt(e.paddingTop, 10) + parseInt(e.paddingBottom, 10);
        return t >= r && t <= r + i && n >= o && n <= o + s
    }
    var Za = "toastui-editor-";

    function Qa() {
        for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
        for (var n = [], r = 0, o = e; r < o.length; r++) {
            var i, s = o[r];
            (i = Array.isArray(s) ? s[0] ? s[1] : null : s) && n.push("" + Za + i)
        }
        return n.join(" ")
    }

    function Ya() {
        for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
        return e.map(function(e) {
            return Za + "md-" + e
        }).join(" ")
    }

    function el(e) {
        return e && e.nodeType === Node.ELEMENT_NODE
    }

    function tl(e) {
        e.parentNode && e.parentNode.removeChild(e)
    }

    function nl(e, t, n) {
        as(n) && (n = !Fa(e, t)), (n ? vs : xs)(e, t)
    }

    function rl(e, t) {
        var n = document.createElement("div");
        Ki(e) ? n.innerHTML = e : n.appendChild(e);
        var r = n.firstChild;
        return t && t.appendChild(r), r
    }

    function ol(e) {
        var t = window.getComputedStyle(e);
        return ["margin-left", "margin-right"].reduce(function(e, n) {
            return e + parseInt(t.getPropertyValue(n), 10)
        }, 0) + e.offsetWidth
    }

    function il(e, t) {
        var n;
        for (n = Ki(t) ? function(e) {
                return n = e, r = t, Va.call(n, r);
                var n, r
            } : function(e) {
                return e === t
            }; e && e !== document;) {
            if (el(e) && n(e)) return e;
            e = e.parentNode
        }
        return null
    }

    function sl(e, t) {
        for (var n = 0, r = 0; e && e !== t && (n += e.offsetTop, r += e.offsetLeft, e.offsetParent !== t.offsetParent);) e = e.offsetParent;
        return {
            offsetTop: n,
            offsetLeft: r
        }
    }

    function al(e, t) {
        Object.keys(e).forEach(function(n) {
            Ws(e[n]) ? t.removeAttribute(n) : t.setAttribute(n, e[n])
        })
    }

    function ll(e) {
        var t = e;
        return (t = t.replace(/<img class="ProseMirror-separator" alt="">/g, "")).replace(/ class="ProseMirror-trailingBreak"/g, "")
    }
    var cl = new Ct("widget"),
        ul = function() {
            function e(e, t) {
                var n = this;
                this.popup = null, this.removeWidget = function() {
                    n.popup && (n.rootEl.removeChild(n.popup), n.popup = null)
                }, this.rootEl = e.dom.parentElement, this.eventEmitter = t, this.eventEmitter.listen("blur", this.removeWidget), this.eventEmitter.listen("loadUI", function() {
                    n.rootEl = il(e.dom.parentElement, "." + Qa("defaultUI"))
                }), this.eventEmitter.listen("removePopupWidget", this.removeWidget)
            }
            return e.prototype.update = function(e) {
                var t = cl.getState(e.state);
                if (this.removeWidget(), t) {
                    var n = t.node,
                        r = t.style,
                        o = e.coordsAtPos(t.pos),
                        i = o.top,
                        s = o.left,
                        a = o.bottom - i,
                        l = this.rootEl.getBoundingClientRect(),
                        c = i - l.top;
                    rs(n, {
                        opacity: "0"
                    }), this.rootEl.appendChild(n), rs(n, {
                        position: "absolute",
                        left: s - l.left + 5 + "px",
                        top: ("bottom" === r ? c + a - 5 : c - a) + "px",
                        opacity: "1"
                    }), this.popup = n, e.focus()
                }
            }, e.prototype.destroy = function() {
                this.eventEmitter.removeEventHandler("blur", this.removeWidget)
            }, e
        }();

    function dl(e, t, n) {
        e.emit("addImageBlobHook", t, function(n, r) {
            e.emit("command", "addImage", {
                imageUrl: n,
                altText: r || t.name || "image"
            })
        }, n)
    }

    function pl(e) {
        var t = na(e).filter(function(e) {
            return -1 !== e.type.indexOf("image")
        });
        if (1 === t.length) {
            var n = t[0];
            if (n) return n.getAsFile()
        }
        return null
    }

    function hl(e) {
        var t = e.eventEmitter;
        return new wt({
            props: {
                handleDOMEvents: {
                    drop: function(e, n) {
                        var r, o = null === (r = n.dataTransfer) || void 0 === r ? void 0 : r.files;
                        return o && Xi(o, function(e) {
                            return -1 === e.type.indexOf("image") || (n.preventDefault(), n.stopPropagation(), dl(t, e, n.type), !1)
                        }), !0
                    }
                }
            }
        })
    }
    var fl = function() {
        function e() {}
        return Object.defineProperty(e.prototype, "type", {
            get: function() {
                return "node"
            },
            enumerable: !1,
            configurable: !0
        }), e.prototype.setContext = function(e) {
            this.context = e
        }, e
    }();

    function ml(e) {
        var t = document.createElement("span"),
            n = Oa(e.attrs.info, e.textContent);
        return t.className = "tui-widget", t.appendChild(n), {
            dom: t
        }
    }

    function gl(e) {
        return "widget" === e.type.name
    }
    var vl = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "widget"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        attrs: {
                            info: {
                                default: null
                            }
                        },
                        group: "inline",
                        inline: !0,
                        content: "text*",
                        selectable: !1,
                        atom: !0,
                        toDOM: function() {
                            return ["span", {
                                class: "tui-widget"
                            }, 0]
                        },
                        parseDOM: [{
                            tag: "span.tui-widget",
                            getAttrs: function(e) {
                                return {
                                    info: e.textContent.match(/\$\$(widget\d+)/)[1]
                                }
                            }
                        }]
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(fl),
        yl = function() {
            function e(e) {
                this.timer = null, this.el = document.createElement("div"), this.el.className = "toastui-editor", this.eventEmitter = e, this.placeholder = {
                    text: ""
                }
            }
            return e.prototype.createState = function() {
                return yt.create({
                    schema: this.schema,
                    plugins: this.createPlugins()
                })
            }, e.prototype.initEvent = function() {
                var e = this,
                    t = e.eventEmitter,
                    n = e.view,
                    r = e.editorType;
                n.dom.addEventListener("focus", function() {
                    return t.emit("focus", r)
                }), n.dom.addEventListener("blur", function() {
                    return t.emit("blur", r)
                })
            }, e.prototype.emitChangeEvent = function(e) {
                this.eventEmitter.emit("caretChange", this.editorType), e.docChanged && this.eventEmitter.emit("change", this.editorType)
            }, Object.defineProperty(e.prototype, "defaultPlugins", {
                get: function() {
                    var e, t, n = this.createInputRules(),
                        r = _i(_i([], this.keymaps), [Jo($i({
                            "Shift-Enter": gi.Enter
                        }, gi)), Fi(), (t = this.placeholder, new wt({
                            props: {
                                decorations: function(e) {
                                    var n = e.doc;
                                    if (t.text && 1 === n.childCount && n.firstChild.isTextblock && 0 === n.firstChild.content.size) {
                                        var r = document.createElement("span");
                                        return vs(r, "placeholder"), t.className && vs(r, t.className), r.textContent = t.text, lo.create(n, [io.widget(1, r)])
                                    }
                                    return null
                                }
                            }
                        })), (e = this.eventEmitter, new wt({
                            key: cl,
                            state: {
                                init: function() {
                                    return null
                                },
                                apply: function(e) {
                                    return e.getMeta("widget")
                                }
                            },
                            view: function(t) {
                                return new ul(t, e)
                            }
                        })), hl(this.context)]);
                    return n ? r.concat(n) : r
                },
                enumerable: !1,
                configurable: !0
            }), e.prototype.createInputRules = function() {
                var e = Ta.map(function(e) {
                    var t = e.rule;
                    return new vi(t, function(e, n, r, o) {
                        var i = e.schema,
                            s = e.tr,
                            a = e.doc,
                            l = n.input.match(new RegExp(t, "g")),
                            c = a.resolve(r),
                            u = c.parent,
                            d = 0;
                        if (gl(u) && (u = c.node(c.depth - 1)), u.forEach(function(e) {
                                return gl(e) && (d += 1)
                            }), l.length > d) {
                            var p = Ks(l),
                                h = La(p, i);
                            return s.replaceWith(o - p.length + 1, o, h)
                        }
                        return null
                    })
                });
                return e.length ? yi({
                    rules: e
                }) : null
            }, e.prototype.clearTimer = function() {
                this.timer && (clearTimeout(this.timer), this.timer = null)
            }, e.prototype.createSchema = function() {
                return new Z({
                    nodes: this.specs.nodes,
                    marks: this.specs.marks
                })
            }, e.prototype.createKeymaps = function(e) {
                var t = Ra(),
                    n = t.undo,
                    r = t.redo,
                    o = this.specs.keymaps(e),
                    i = {
                        "Mod-z": n(),
                        "Shift-Mod-z": r()
                    };
                return e ? o.concat(Jo(i)) : o
            }, e.prototype.createCommands = function() {
                return this.specs.commands(this.view)
            }, e.prototype.createPluginProps = function() {
                var e = this;
                return this.extraPlugins.map(function(t) {
                    return t(e.eventEmitter)
                })
            }, e.prototype.focus = function() {
                var e = this;
                this.clearTimer(), this.timer = setTimeout(function() {
                    e.view.focus(), e.view.dispatch(e.view.state.tr.scrollIntoView())
                })
            }, e.prototype.blur = function() {
                this.view.dom.blur()
            }, e.prototype.destroy = function() {
                var e = this;
                this.clearTimer(), this.view.destroy(), Object.keys(this).forEach(function(t) {
                    delete e[t]
                })
            }, e.prototype.moveCursorToStart = function(e) {
                var t = this.view.state.tr;
                this.view.dispatch(t.setSelection(ia(t, 1)).scrollIntoView()), e && this.focus()
            }, e.prototype.moveCursorToEnd = function(e) {
                var t = this.view.state.tr;
                this.view.dispatch(t.setSelection(ia(t, t.doc.content.size - 1)).scrollIntoView()), e && this.focus()
            }, e.prototype.setScrollTop = function(e) {
                this.view.dom.scrollTop = e
            }, e.prototype.getScrollTop = function() {
                return this.view.dom.scrollTop
            }, e.prototype.setPlaceholder = function(e) {
                this.placeholder.text = e, this.view.dispatch(this.view.state.tr.scrollIntoView())
            }, e.prototype.setHeight = function(e) {
                rs(this.el, {
                    height: e + "px"
                })
            }, e.prototype.setMinHeight = function(e) {
                rs(this.el, {
                    minHeight: e + "px"
                })
            }, e.prototype.getElement = function() {
                return this.el
            }, e
        }(),
        bl = function(e) {
            return e instanceof Function
        },
        wl = ["Enter", "Shift-Enter", "Mod-Enter", "Tab", "Shift-Tab", "Delete", "Backspace", "Mod-Delete", "Mod-Backspace", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Mod-d", "Mod-D", "Alt-ArrowUp", "Alt-ArrowDown"];

    function kl(e, t, n) {
        return e.focus(), t(n)(e.state, e.dispatch, e)
    }
    var xl = function() {
        function e(e) {
            this.specs = e
        }
        return Object.defineProperty(e.prototype, "nodes", {
            get: function() {
                return this.specs.filter(function(e) {
                    return "node" === e.type
                }).reduce(function(e, t) {
                    var n, r = t.name,
                        o = t.schema;
                    return $i($i({}, e), ((n = {})[r] = o, n))
                }, {})
            },
            enumerable: !1,
            configurable: !0
        }), Object.defineProperty(e.prototype, "marks", {
            get: function() {
                return this.specs.filter(function(e) {
                    return "mark" === e.type
                }).reduce(function(e, t) {
                    var n, r = t.name,
                        o = t.schema;
                    return $i($i({}, e), ((n = {})[r] = o, n))
                }, {})
            },
            enumerable: !1,
            configurable: !0
        }), e.prototype.commands = function(e, t) {
            var n = this.specs.filter(function(e) {
                    return e.commands
                }).reduce(function(t, n) {
                    var r = {},
                        o = n.commands();
                    return bl(o) ? r[n.name] = function(t) {
                        return kl(e, o, t)
                    } : Object.keys(o).forEach(function(t) {
                        r[t] = function(n) {
                            return kl(e, o[t], n)
                        }
                    }), $i($i({}, t), r)
                }, {}),
                r = Ra();
            return Object.keys(r).forEach(function(t) {
                n[t] = function(n) {
                    return kl(e, r[t], n)
                }
            }), t && Object.keys(t).forEach(function(r) {
                n[r] = function(n) {
                    return kl(e, t[r], n)
                }
            }), n
        }, e.prototype.keymaps = function(e) {
            return this.specs.filter(function(e) {
                return e.keymaps
            }).map(function(e) {
                return e.keymaps()
            }).map(function(t) {
                return e || Object.keys(t).forEach(function(e) {
                    zs(wl, e) || delete t[e]
                }), Jo(t)
            })
        }, e.prototype.setContext = function(e) {
            this.specs.forEach(function(t) {
                t.setContext(e)
            })
        }, e
    }();

    function Cl(e) {
        var t = e.from,
            n = e.to;
        return e instanceof ct ? [t + 1, n - 1] : [t, n]
    }

    function Tl(e) {
        return e.index(0) + 1
    }

    function Ml(e, t, n) {
        void 0 === n && (n = 1);
        var r = 0;
        return e.forEach(function(e, o) {
            gl(e) && o + 2 < t && (r += 2 * n)
        }), r
    }

    function Sl(e, t, n) {
        void 0 === n && (n = t);
        var r = t === n,
            o = e.resolve(t),
            i = Tl(o),
            s = i,
            a = o.start(1),
            l = a;
        if (!r) {
            var c = e.resolve(n === e.content.size ? n - 1 : n);
            l = c.start(1), s = Tl(c), c.pos === e.content.size && (n = e.content.size - 2)
        }
        var u = Math.max(t - a + 1, 1),
            d = Math.max(n - l + 1, 1);
        return [
            [i, u + Ml(e.child(i - 1), u, -1)],
            [s, d + Ml(e.child(s - 1), d, -1)]
        ]
    }

    function El(e, t) {
        for (var n = [], r = 0, o = 0; r < t; r += 1) {
            var i = e.child(r);
            n[r] = o, o += i.nodeSize
        }
        return n
    }

    function Nl(e, t, n) {
        var r = El(e, n[0]),
            o = t[0] - 1,
            i = n[0] - 1,
            s = e.child(o),
            a = e.child(i),
            l = r[o],
            c = r[i];
        return l += t[1] + Ml(s, t[1] - 1), c += n[1] + Ml(a, n[1] - 1), [l, Math.min(c, e.content.size)]
    }

    function Ol(e) {
        var t = e.$from,
            n = e.$to,
            r = e.from,
            o = e.to,
            i = t.doc;
        return e instanceof ct && (t = i.resolve(r + 1), n = i.resolve(o - 1)), 0 === t.depth && (n = t = i.resolve(r - 1)), {
            startFromOffset: t.start(1),
            endFromOffset: n.start(1),
            startToOffset: t.end(1),
            endToOffset: n.end(1),
            startIndex: t.index(0),
            endIndex: n.index(0),
            from: t.pos,
            to: n.pos
        }
    }

    function Dl(e, t) {
        for (var n = 1, r = 1, o = 0, i = 0; o < e.childCount; o += 1) {
            var s = e.child(o).nodeSize;
            if (n = i + 1, r = i + s - 1, o === t) break;
            i += s
        }
        return {
            startOffset: n,
            endOffset: r
        }
    }
    var Al = "heading",
        Ll = "link",
        Il = "code",
        Rl = "meta",
        Pl = "delimiter",
        Bl = "markedText",
        Fl = {
            strong: 2,
            emph: 1,
            strike: 2
        };

    function Hl(e, t, n, r) {
        return {
            start: e,
            end: t,
            spec: {
                type: n,
                attrs: r
            }
        }
    }

    function zl(e, t, n) {
        var r = e.type,
            o = ba(t, Fl[r]),
            i = ba(n, -Fl[r]);
        return [Hl(o, i, r), Hl(t, o, Pl), Hl(i, n, Pl)]
    }

    function ql(e, t, n, r) {
        return [Hl(e, t, Ll), Hl(wa(e, n[1] + 1), wa(t, r), Ll, {
            desc: !0
        }), Hl(wa(t, r + 2), ba(t, -1), Ll, {
            url: !0
        })]
    }

    function Vl(e, t, n, r) {
        var o = {
            start: t,
            end: n,
            spec: {
                attrs: {
                    className: r + "-line-background",
                    codeStart: t[0],
                    codeEnd: n[0]
                }
            },
            lineBackground: !0
        };
        return "item" !== e.type && "blockQuote" !== e.type ? [$i($i({}, o), {
            end: t,
            spec: {
                attrs: {
                    className: r + "-line-background start"
                }
            }
        }), $i($i({}, o), {
            start: [Math.min(t[0] + 1, n[0]), t[1]]
        })] : null
    }

    function jl(e, t) {
        for (var n = []; e;) {
            var r = e.type;
            "paragraph" !== r && "codeBlock" !== r || n.push(Hl([ca(e), da(e) - 1], [ua(e), pa(e) + 1], t)), e = e.next
        }
        return n
    }
    var $l = {
            heading: function(e, t, n) {
                var r = e.level,
                    o = e.headingType,
                    i = [Hl(t, n, Al, {
                        level: r
                    })];
                return "atx" === o ? i.push(Hl(t, ba(t, r), Pl)) : i.push(Hl(wa(n, 0), n, Al, {
                    seText: !0
                })), i
            },
            strong: zl,
            emph: zl,
            strike: zl,
            link: function(e, t, n) {
                var r = e.lastChild,
                    o = e.extendedAutolink,
                    i = r ? pa(r) + 1 : 2;
                return o ? [Hl(t, n, Ll, {
                    desc: !0
                })] : ql(t, n, t, i)
            },
            image: function(e, t, n) {
                var r = e.lastChild,
                    o = r ? pa(r) + 1 : 3,
                    i = ba(t, 1);
                return _i([Hl(t, i, Rl)], ql(t, n, i, o))
            },
            code: function(e, t, n) {
                var r = e.tickCount,
                    o = ba(t, r),
                    i = ba(n, -r);
                return [Hl(t, n, Il), Hl(t, o, Il, {
                    start: !0
                }), Hl(o, i, Il, {
                    marked: !0
                }), Hl(i, n, Il, {
                    end: !0
                })]
            },
            codeBlock: function(e, t, n, r) {
                var o = e.fenceOffset,
                    i = e.fenceLength,
                    s = e.fenceChar,
                    a = e.info,
                    l = e.infoPadding,
                    c = e.parent,
                    u = o + i,
                    d = [Hl(wa(t, 1), n, "codeBlock")];
                s && d.push(Hl(t, ba(t, u), Pl)), a && d.push(Hl(ba(t, i), ba(t, i + l + a.length), Rl)), new RegExp("^(\\s{0,4})(" + s + "{" + i + ",})").test(r) && d.push(Hl(wa(n, 1), n, Pl));
                var p = Vl(c, t, n, "code-block");
                return p ? d.concat(p) : d
            },
            blockQuote: function(e, t, n) {
                var r = e.parent && "blockQuote" !== e.parent.type ? [Hl(t, n, "blockQuote")] : [];
                if (e.firstChild) {
                    var o = [];
                    "paragraph" === e.firstChild.type ? o = function(e) {
                        for (var t = []; e;) t.push(Hl([ca(e), da(e)], [ua(e), pa(e) + 1], Bl)), e = e.next;
                        return t
                    }(e.firstChild.firstChild) : "list" === e.firstChild.type && (o = jl(e.firstChild, Bl)), r = _i(_i([], r), o)
                }
                return r
            },
            item: function(e, t) {
                var n = e.listData,
                    r = n.padding,
                    o = n.task,
                    i = function(e) {
                        for (var t = 0; e.parent.parent && "item" === e.parent.parent.type;) e = e.parent.parent, t += 1;
                        return ["listItem", $i($i({}, [{
                            odd: !0
                        }, {
                            even: !0
                        }][t % 2]), {
                            listStyle: !0
                        })]
                    }(e),
                    s = [Hl.apply(void 0, _i([t, ba(t, r)], i))];
                return o && (s.push(Hl(ba(t, r), ba(t, r + 3), "taskDelimiter")), s.push(Hl(ba(t, r + 1), ba(t, r + 2), Rl))), s.concat(jl(e.firstChild, Bl))
            },
            customBlock: function(e, t, n) {
                var r = e,
                    o = r.offset,
                    i = r.syntaxLength,
                    s = r.info,
                    a = r.parent,
                    l = o + i,
                    c = [Hl(wa(t, 1), n, "customBlock")];
                c.push(Hl(t, ba(t, l), Pl)), s && c.push(Hl(ba(t, l), ba(t, i + s.length), Rl)), c.push(Hl(wa(n, 1), n, Pl));
                var u = Vl(a, t, n, "custom-block");
                return u ? c.concat(u) : c
            }
        },
        _l = {
            thematicBreak: "thematicBreak",
            table: "table",
            tableCell: "tableCell",
            htmlInline: "html"
        };

    function Ul(e, t, n, r) {
        var o = e.type;
        return bl($l[o]) ? $l[o](e, t, n, r) : _l[o] ? [Hl(t, n, _l[o])] : null
    }
    var Wl = {};

    function Jl(e) {
        var t = e.schema,
            n = e.toastMark;
        return new wt({
            appendTransaction: function(e, r, o) {
                var i = e[0],
                    s = o.tr;
                if (i.docChanged) {
                    var a = [];
                    i.getMeta("editResult").forEach(function(e) {
                            var t = e.nodes,
                                r = e.removedNodeRange;
                            if (t.length) {
                                a = a.concat(function(e, t) {
                                    var n = e.doc,
                                        r = t[0].sourcepos[0],
                                        o = Ks(t).sourcepos[1],
                                        i = [r[0], r[1]],
                                        s = [o[0], o[1] + 1],
                                        a = [];
                                    return function(e, t, n) {
                                        var r = [];
                                        Wl = {};
                                        for (var o = t[0] - 1; o < n[0]; o += 1) {
                                            var i = e.child(o),
                                                s = i.attrs.codeEnd,
                                                a = i.attrs.codeStart;
                                            if (a && s && !zs(r, a)) {
                                                r.push(a), s = Math.min(s, e.childCount);
                                                for (var l = a - 1, c = n[0], u = l; u < c; u += 1) Wl[u] = !0
                                            }
                                        }
                                    }(n, r, o), a.push({
                                        start: i,
                                        end: s
                                    }), a
                                }(s, t));
                                for (var o = 0, i = t; o < i.length; o++)
                                    for (var l = i[o].walker(), c = l.next(); c;) {
                                        var u = c.node;
                                        c.entering && (a = a.concat(Gl(u, n))), c = l.next()
                                    }
                            } else if (r)
                                for (var d = s.doc.childCount - 1, p = r.line, h = p[0], f = p[1], m = Math.min(h, d), g = Math.min(f, d), v = m; v <= g; v += 1) Wl[v] = !0
                        }),
                        function(e, t, n) {
                            var r = e.doc,
                                o = t.nodes.paragraph,
                                i = El(r, r.childCount);
                            n.forEach(function(n) {
                                    var s = n.start,
                                        a = n.end,
                                        l = n.spec,
                                        c = n.lineBackground,
                                        u = Math.min(s[0], r.childCount) - 1,
                                        d = Math.min(a[0], r.childCount) - 1,
                                        p = r.child(u),
                                        h = r.child(d),
                                        f = i[u],
                                        m = i[d];
                                    f += s[1] + Ml(p, s[1] - 1), m += a[1] + Ml(h, a[1] - 1), l ? c ? function(e, t, n, r, o) {
                                        void 0 === o && (o = {});
                                        for (var i = r.endIndex, s = r.from, a = r.to, l = !1, c = r.startIndex; c <= i; c += 1) delete Wl[c], l = Kl(t, c, o);
                                        l && e.setBlockType(s, a, n, o)
                                    }(e, r, o, {
                                        from: f,
                                        to: m,
                                        startIndex: u,
                                        endIndex: d
                                    }, l.attrs) : e.addMark(f, m, t.mark(l.type, l.attrs)) : e.removeMark(f, m)
                                }),
                                function(e, t, n) {
                                    Object.keys(Wl).forEach(function(r) {
                                        var o = Number(r),
                                            i = Math.min(Number(r) + 1, e.doc.childCount - 1),
                                            s = t[o],
                                            a = t[i] - 1;
                                        o === i && (a += 2), e.setBlockType(s, a, n)
                                    })
                                }(e, i, o)
                        }(s, t, a)
                }
                return s.setMeta("widget", i.getMeta("widget"))
            }
        })
    }

    function Kl(e, t, n) {
        return Object.keys(n).some(function(r) {
            return n[r] !== e.child(t).attrs[r]
        })
    }

    function Gl(e, t) {
        var n = t.getLineTexts(),
            r = [ca(e), da(e)],
            o = [ua(e), pa(e) + 1],
            i = Ul(e, r, o, n[o[0] - 1]);
        return null != i ? i : []
    }
    var Xl = ["taskList", "orderedList", "bulletList", "table", "strong", "emph", "strike", "heading", "thematicBreak", "blockQuote", "code", "codeBlock", "indent", "outdent"];
    var Zl = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "doc"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "block+"
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(fl),
        Ql = function() {
            function e() {}
            return Object.defineProperty(e.prototype, "type", {
                get: function() {
                    return "mark"
                },
                enumerable: !1,
                configurable: !0
            }), e.prototype.setContext = function(e) {
                this.context = e
            }, e
        }();

    function Yl(e, t) {
        return ec(e, t - 1)
    }

    function ec(e, t) {
        return e.child(t).textContent
    }
    var tc = /^\s*> ?/,
        nc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "blockQuote"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("block-quote")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.createBlockQuoteText = function(e, t) {
                return t ? e.replace(tc, "").trim() : "> " + e.trim()
            }, t.prototype.extendBlockQuote = function() {
                var e = this;
                return function(t, n) {
                    var r = t.selection,
                        o = t.doc,
                        i = t.tr,
                        s = t.schema,
                        a = Ol(r),
                        l = a.endFromOffset,
                        c = a.endToOffset,
                        u = a.endIndex,
                        d = a.to,
                        p = ec(o, u);
                    if (tc.test(p) && d > l && r.empty) {
                        if (p.replace(tc, "").trim()) {
                            var h = p.slice(d - l).trim();
                            la(i, c, h, oa(s, e.createBlockQuoteText(h)))
                        } else i.deleteRange(l, c).split(i.mapping.map(c));
                        return n(i), !0
                    }
                    return !1
                }
            }, t.prototype.commands = function() {
                var e = this;
                return function() {
                    return function(t, n) {
                        var r = t.selection,
                            o = t.doc,
                            i = Ol(r),
                            s = i.startFromOffset,
                            a = i.endToOffset,
                            l = i.startIndex,
                            c = i.endIndex,
                            u = tc.test(ec(o, l)),
                            d = aa({
                                state: t,
                                startIndex: l,
                                endIndex: c,
                                from: s,
                                createText: function(t) {
                                    return e.createBlockQuoteText(t, u)
                                }
                            });
                        return n(d.setSelection(ia(d, d.mapping.map(a)))), !0
                    }
                }
            }, t.prototype.keymaps = function() {
                var e = this.commands()();
                return {
                    "alt-q": e,
                    "alt-Q": e,
                    Enter: this.extendBlockQuote()
                }
            }, t
        }(Ql),
        rc = /(^\s*)([-*+] |[\d]+\. )/,
        oc = /(^\s*)([\d])+\.( \[[ xX]])? /,
        ic = /^(\s*)((\d+)([.)]\s(?:\[(?:x|\s)\]\s)?))(.*)/,
        sc = /(^\s*)([-*+]|[\d]+\.)( \[[ xX]])? /,
        ac = /^(\s*)([-*+]+(\s(?:\[(?:x|\s)\]\s)?))(.*)/,
        lc = /(^\s*)([-*+] |[\d]+\. )(\[[ xX]] )/,
        cc = /(^\s*)([-*+])( \[[ xX]]) /;

    function uc(e) {
        return oc.test(e) ? "ordered" : "bullet"
    }

    function dc(e) {
        for (var t = 0; e && "document" !== e.type;) "list" === e.type && (t += 1), e = e.parent;
        return t
    }

    function pc(e, t, n, r) {
        for (var o = e.getLineTexts().length, i = [], s = t; r ? s < o : s > 1;) {
            s = r ? s + 1 : s - 1;
            var a = e.findFirstNodeAtLine(s),
                l = dc(a);
            if (l === n) i.push({
                line: s,
                depth: n,
                mdNode: a
            });
            else if (l < n) break
        }
        return i
    }

    function hc(e, t, n, r) {
        void 0 === r && (r = 0);
        var o = Number.MAX_VALUE,
            i = 0,
            s = t.map(function(t, s) {
                var a = t.line;
                o = Math.min(a - 1, o), i = Math.max(a - 1, i);
                var l = Yl(e, a);
                return l = "bullet" === n ? function(e) {
                    if (!rc.test(e)) return "* " + e;
                    var t = uc(e);
                    return "bullet" === t && sc.test(e) ? e = e.replace(cc, "$1$2 ") : "ordered" === t && (e = e.replace(oc, "$1* ")), e
                }(l) : function(e, t) {
                    if (!rc.test(e)) return t + ". " + e;
                    var n = uc(e);
                    if ("bullet" === n || "ordered" === n && sc.test(e)) e = e.replace(sc, "$1" + t + ". ");
                    else if ("ordered" === n) {
                        var r = ic.exec(e)[3];
                        Number(r) !== t && (e = e.replace(oc, "$1" + t + ". "))
                    }
                    return e
                }(l, s + 1 + r), {
                    text: l,
                    line: a
                }
            });
        return {
            changedResults: s,
            firstIndex: o,
            lastIndex: i
        }
    }

    function fc(e, t) {
        var n, r, o, i, s, a, l, c = (r = (n = t).toastMark, o = n.mdNode, a = pc(r, i = n.line, s = dc(o), !1).reverse(), l = pc(r, i, s, !0), a.concat([{
            line: i,
            depth: s,
            mdNode: o
        }]).concat(l));
        return hc(t.doc, c, e)
    }
    var mc = {
            bullet: function(e) {
                return fc("bullet", e)
            },
            ordered: function(e) {
                return fc("ordered", e)
            },
            task: function(e) {
                var t = e.mdNode,
                    n = e.doc,
                    r = e.line,
                    o = Yl(n, r);
                return t.listData.task ? o = o.replace(lc, "$1$2") : fa(t) && (o = o.replace(rc, "$1$2[ ] ")), {
                    changedResults: [{
                        text: o,
                        line: r
                    }]
                }
            }
        },
        gc = {
            bullet: function(e) {
                var t = e.doc,
                    n = e.line;
                return {
                    changedResults: [{
                        text: "* " + Yl(t, n),
                        line: n
                    }]
                }
            },
            ordered: function(e) {
                for (var t = e.toastMark, n = e.doc, r = e.line, o = e.startLine, i = Yl(n, r), s = 1, a = o, l = 0, c = o - 1; c > 0; c -= 1) {
                    var u = t.findFirstNodeAtLine(c),
                        d = Yl(n, c) && !!ya(u, function(e) {
                            return fa(e)
                        }),
                        p = ic.exec(Yl(n, c));
                    if (!p && !d) break;
                    if (p || !d) {
                        var h = p,
                            f = h[1],
                            m = h[3];
                        if (!f) {
                            s = Number(m), a = c;
                            break
                        }
                    } else l += 1
                }
                return {
                    changedResults: [{
                        text: s + r - a - l + ". " + i,
                        line: r
                    }]
                }
            },
            task: function(e) {
                var t = e.doc,
                    n = e.line;
                return {
                    changedResults: [{
                        text: "* [ ] " + Yl(t, n),
                        line: n
                    }]
                }
            }
        },
        vc = {
            bullet: function(e) {
                var t = e.line,
                    n = Yl(e.doc, t),
                    r = ac.exec(n);
                return {
                    listSyntax: "" + r[1] + r[2]
                }
            },
            ordered: function(e) {
                var t = e.toastMark,
                    n = e.line,
                    r = e.mdNode,
                    o = e.doc,
                    i = dc(r),
                    s = Yl(o, n),
                    a = ic.exec(s),
                    l = a[1],
                    c = a[3],
                    u = a[4],
                    d = Number(c) + 1,
                    p = "" + l + d + u,
                    h = pc(t, n, i, !0).filter(function(e) {
                        var t = ic.exec(Yl(o, e.line));
                        return t && t[1].length === l.length && !!ya(e.mdNode, function(e) {
                            return ma(e)
                        })
                    });
                return $i({
                    listSyntax: p
                }, hc(o, h, "ordered", d))
            }
        };

    function yc(e, t, n, r, o) {
        for (var i = [], s = Yl(e, n), a = ic.exec(s); a;) {
            var l = a[1],
                c = a[4],
                u = a[5],
                d = l.length;
            if (d === o) i.push(oa(t, "" + l + r + c + u)), r += 1, n += 1;
            else if (d > o) {
                var p = yc(e, t, n, 1, d);
                n = p.line, i = i.concat(p.nodes)
            }
            if (d < o || n > e.childCount) break;
            s = Yl(e, n), a = ic.exec(s)
        }
        return {
            nodes: i,
            line: n
        }
    }
    var bc = /(^\s{1,4})(.*)/;

    function wc(e, t, n) {
        return e < t || rc.test(n) || tc.test(n)
    }

    function kc(e, t, n) {
        var r = n.$from;
        0 === r.depth && (r = e.resolve(r.pos - 1));
        var o = r.node(1),
            i = r.start(1),
            s = o.content.size;
        return o.rangeHasMark(0, s, t.marks.table) && r.pos - i !== s && r.pos !== i
    }

    function xc(e, t) {
        var n = t.from,
            r = t.to;
        if ("indent" === t.type) n += 4, r += 4 * (t.lineLen + 1);
        else {
            var o = t.spaceLenList;
            n -= o[0];
            for (var i = 0; i < o.length; i += 1) r -= o[i]
        }
        return ia(e, n, r)
    }
    var Cc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "paragraph"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "inline*",
                        attrs: {
                            className: {
                                default: null
                            },
                            codeStart: {
                                default: null
                            },
                            codeEnd: {
                                default: null
                            }
                        },
                        selectable: !1,
                        group: "block",
                        parseDOM: [{
                            tag: "div"
                        }],
                        toDOM: function(e) {
                            var t = e.attrs;
                            return t.className ? ["div", {
                                class: Ya(t.className)
                            }, 0] : ["div", 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.reorderList = function(e, t) {
                for (var n = this.context, r = n.view, o = n.toastMark, i = n.schema, s = r.state, a = s.tr, l = s.selection, c = s.doc, u = o.findFirstNodeAtLine(e), d = u; u && !ga(u) && "document" !== u.parent.type;)
                    if (ma(u = u.parent)) {
                        d = u;
                        break
                    } d && (e = d.sourcepos[0][0]);
                var p = ic.exec(Yl(c, e)),
                    h = p[1],
                    f = p[3],
                    m = h.length,
                    g = yc(c, i, e, Number(f), m),
                    v = g.line,
                    y = g.nodes;
                t = Math.max(t, v - 1);
                for (var b = Dl(c, e - 1).startOffset, w = e - 1; w <= t - 1; w += 1) {
                    var k = c.child(w),
                        x = k.nodeSize,
                        C = k.content,
                        T = a.mapping.map(b),
                        M = T + C.size;
                    a.replaceWith(T, M, y[w - e + 1]), b += x
                }
                var S = ia(a, l.from, l.to);
                r.dispatch(a.setSelection(S))
            }, t.prototype.indent = function(e) {
                var t = this;
                return void 0 === e && (e = !1),
                    function() {
                        return function(n, r) {
                            var o = n.schema,
                                i = n.selection,
                                s = n.doc,
                                a = Ol(i),
                                l = a.from,
                                c = a.to,
                                u = a.startFromOffset,
                                d = a.startIndex,
                                p = a.endIndex;
                            if (e && kc(s, o, i)) return !1;
                            var h = ec(s, d);
                            if (e && wc(l, c, h) || !e && rc.test(h)) {
                                var f = aa({
                                        state: n,
                                        from: u,
                                        startIndex: d,
                                        endIndex: p,
                                        createText: function(e) {
                                            return "    " + e
                                        }
                                    }),
                                    m = {
                                        type: "indent",
                                        from: l,
                                        to: c,
                                        lineLen: p - d
                                    };
                                r(f.setSelection(xc(f, m))), ic.test(h) && t.reorderList(d + 1, p + 1)
                            } else e && r(n.tr.insert(c, oa(o, "    ")));
                            return !0
                        }
                    }
            }, t.prototype.outdent = function(e) {
                var t = this;
                return void 0 === e && (e = !1),
                    function() {
                        return function(n, r) {
                            var o = n.selection,
                                i = n.doc,
                                s = n.schema,
                                a = Ol(o),
                                l = a.from,
                                c = a.to,
                                u = a.startFromOffset,
                                d = a.startIndex,
                                p = a.endIndex;
                            if (e && kc(i, s, o)) return !1;
                            var h = ec(i, d);
                            if (e && wc(l, c, h) || !e && rc.test(h)) {
                                var f = [],
                                    m = aa({
                                        state: n,
                                        from: u,
                                        startIndex: d,
                                        endIndex: p,
                                        createText: function(e) {
                                            var t = bc.exec(e);
                                            return f.push(t ? t[1].length : 0), e.replace(bc, "$2")
                                        }
                                    }),
                                    g = {
                                        type: "outdent",
                                        from: l,
                                        to: c,
                                        spaceLenList: f
                                    };
                                r(m.setSelection(xc(m, g))), ic.test(h) && t.reorderList(d + 1, p + 1)
                            } else if (e) {
                                var v = h.slice(0, c - u),
                                    y = v.replace(/\s{1,4}$/, ""),
                                    b = c - (v.length - y.length);
                                r(n.tr.delete(b, c))
                            }
                            return !0
                        }
                    }
            }, t.prototype.deleteLines = function() {
                var e = this;
                return function(t, n) {
                    var r = e.context.view,
                        o = Ol(t.selection),
                        i = o.startFromOffset,
                        s = o.endToOffset;
                    return di(function() {
                        return n(t.tr.deleteRange(i, s)), !0
                    }, Qo)(t, n, r)
                }
            }, t.prototype.moveDown = function() {
                return function(e, t) {
                    var n = e.doc,
                        r = e.tr,
                        o = e.selection,
                        i = e.schema,
                        s = Ol(o),
                        a = s.startFromOffset,
                        l = s.endToOffset,
                        c = s.endIndex;
                    if (c < n.content.childCount - 1) {
                        var u = n.child(c + 1),
                            d = u.nodeSize,
                            p = u.textContent;
                        return r.delete(l, l + d).split(a).insert(r.mapping.map(a) - 2, oa(i, p)), t(r), !0
                    }
                    return !1
                }
            }, t.prototype.moveUp = function() {
                return function(e, t) {
                    var n = e.tr,
                        r = e.doc,
                        o = e.selection,
                        i = e.schema,
                        s = Ol(o),
                        a = s.startFromOffset,
                        l = s.endToOffset,
                        c = s.startIndex;
                    if (c > 0) {
                        var u = r.child(c - 1),
                            d = u.nodeSize,
                            p = u.textContent;
                        return n.delete(a - d, a).split(n.mapping.map(l)).insert(n.mapping.map(l), oa(i, p)), t(n), !0
                    }
                    return !1
                }
            }, t.prototype.commands = function() {
                return {
                    indent: this.indent(),
                    outdent: this.outdent()
                }
            }, t.prototype.keymaps = function() {
                return {
                    Tab: this.indent(!0)(),
                    "Shift-Tab": this.outdent(!0)(),
                    "Mod-d": this.deleteLines(),
                    "Mod-D": this.deleteLines(),
                    "Alt-ArrowUp": this.moveUp(),
                    "Alt-ArrowDown": this.moveDown()
                }
            }, t
        }(fl),
        Tc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "text"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        group: "inline"
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(fl),
        Mc = /^#{1,6}\s/,
        Sc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "heading"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        attrs: {
                            level: {
                                default: 1
                            },
                            seText: {
                                default: !1
                            }
                        },
                        toDOM: function(e) {
                            var t = e.attrs,
                                n = "heading|heading" + t.level;
                            return t.seText && (n += "|delimiter|setext"), ["span", {
                                class: Ya.apply(void 0, n.split("|"))
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.createHeadingText = function(e, t, n) {
                for (var r = t.replace(n, "").trim(), o = ""; e > 0;) o += "#", e -= 1;
                return o + " " + r
            }, t.prototype.commands = function() {
                var e = this;
                return function(t) {
                    return function(n, r) {
                        var o = t.level,
                            i = Ol(n.selection),
                            s = i.startFromOffset,
                            a = i.endToOffset,
                            l = aa({
                                state: n,
                                from: s,
                                startIndex: i.startIndex,
                                endIndex: i.endIndex,
                                createText: function(t) {
                                    var n = t.match(Mc),
                                        r = n ? n[0] : "";
                                    return e.createHeadingText(o, t, r)
                                }
                            });
                        return r(l.setSelection(ia(l, l.mapping.map(a)))), !0
                    }
                }
            }, t
        }(Ql),
        Ec = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "codeBlock"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("code-block")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function() {
                    return function(e, t) {
                        var n = e.selection,
                            r = e.schema,
                            o = e.tr,
                            i = Ol(n),
                            s = i.startFromOffset,
                            a = i.endToOffset,
                            l = oa(r, "```");
                        return o.insert(s, l).split(s + 3), o.split(o.mapping.map(a)).insert(o.mapping.map(a), l), t(o.setSelection(ia(o, o.mapping.map(a) - 5))), !0
                    }
                }
            }, t.prototype.keepIndentation = function() {
                var e = this;
                return function(t, n) {
                    var r, o = t.selection,
                        i = t.tr,
                        s = t.doc,
                        a = t.schema,
                        l = e.context.toastMark,
                        c = Ol(o),
                        u = c.startFromOffset,
                        d = c.endToOffset,
                        p = c.endIndex,
                        h = c.from,
                        f = c.to,
                        m = ec(s, p);
                    if (h === f && m.trim()) {
                        var g = m.match(/^\s+/);
                        if ((r = l.findFirstNodeAtLine(p + 1)) && "codeBlock" === r.type && g) {
                            var v = g[0],
                                y = m.slice(f - u);
                            return la(i, d, y, oa(a, v + y)), n(i), !0
                        }
                    }
                    return !1
                }
            }, t.prototype.keymaps = function() {
                var e = this.commands()();
                return {
                    "Shift-Mod-p": e,
                    "Shift-Mod-P": e,
                    Enter: this.keepIndentation()
                }
            }, t
        }(Ql),
        Nc = /\||\s/g;

    function Oc(e, t) {
        for (var n = "|", r = 0; r < e; r += 1) n += t ? " --- |" : "  |";
        return n
    }
    var Dc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "table"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("table")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.extendTable = function() {
                var e = this;
                return function(t, n) {
                    var r = t.selection,
                        o = t.doc,
                        i = t.tr,
                        s = t.schema;
                    if (!r.empty) return !1;
                    var a = Ol(r),
                        l = a.endFromOffset,
                        c = a.endToOffset,
                        u = a.endIndex,
                        d = a.to,
                        p = ec(o, u),
                        h = [u + 1, d - l + 1],
                        f = ya(e.context.toastMark.findNodeAtPosition(h), function(e) {
                            return va(e) && ("tableDelimRow" === e.parent.type || "tableBody" === e.parent.parent.type)
                        });
                    if (f) {
                        var m = !p.replace(Nc, "").trim(),
                            g = Oc(f.parent.parent.parent.columns.length);
                        return m ? i.deleteRange(l, c).split(i.mapping.map(c)) : i.split(c).insert(i.mapping.map(c), oa(s, g)).setSelection(ia(i, i.mapping.map(c) - 2)), n(i), !0
                    }
                    return !1
                }
            }, t.prototype.moveTableCell = function(e) {
                var t = this;
                return function(n, r) {
                    var o = n.selection,
                        i = n.tr,
                        s = Ol(o),
                        a = s.endFromOffset,
                        l = [s.endIndex + 1, s.to - a],
                        c = ya(t.context.toastMark.findNodeAtPosition(l), function(e) {
                            return va(e)
                        });
                    if (c) {
                        var u = c.parent,
                            d = function(e) {
                                return e ? {
                                    type: "next",
                                    parentType: "tableHead",
                                    childType: "firstChild"
                                } : {
                                    type: "prev",
                                    parentType: "tableBody",
                                    childType: "lastChild"
                                }
                            }(e),
                            p = d.type,
                            h = d.parentType,
                            f = d.childType,
                            m = pa(c);
                        if (c[p]) m = pa(c[p]) - 1;
                        else {
                            var g = u[p] || u.parent.type !== h ? u[p] : u.parent[p][f];
                            "next" === p ? m += (g ? pa(g[f]) : 0) + 2 : "prev" === p && (m = g ? -4 : 0)
                        }
                        return r(i.setSelection(ia(i, a + m))), !0
                    }
                    return !1
                }
            }, t.prototype.addTable = function() {
                return function(e) {
                    return function(t, n) {
                        var r = t.selection,
                            o = t.tr,
                            i = t.schema,
                            s = e,
                            a = s.columnCount,
                            l = s.rowCount,
                            c = Ol(r).endToOffset,
                            u = function(e) {
                                return [Oc(e), Oc(e, !0)]
                            }(a),
                            d = function(e, t) {
                                for (var n = [], r = 0; r < t; r += 1) n.push(Oc(e));
                                return n
                            }(a, l - 1);
                        return _i(_i([], u), d).forEach(function(e) {
                            o.split(o.mapping.map(c)).insert(o.mapping.map(c), oa(i, e))
                        }), n(o.setSelection(ia(o, c + 4))), !0
                    }
                }
            }, t.prototype.commands = function() {
                return {
                    addTable: this.addTable()
                }
            }, t.prototype.keymaps = function() {
                return {
                    Enter: this.extendTable(),
                    Tab: this.moveTableCell(!0),
                    "Shift-Tab": this.moveTableCell(!1)
                }
            }, t
        }(Ql),
        Ac = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "thematicBreak"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("thematic-break")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.hr = function() {
                return function() {
                    return function(e, t) {
                        var n = e.selection,
                            r = e.schema,
                            o = e.tr,
                            i = Ol(n),
                            s = i.from,
                            a = i.to,
                            l = i.endToOffset,
                            c = oa(r, "***");
                        return o.split(s).replaceWith(o.mapping.map(s), o.mapping.map(a), c).split(o.mapping.map(a)).setSelection(ia(o, o.mapping.map(l))), t(o), !0
                    }
                }
            }, t.prototype.commands = function() {
                return {
                    hr: this.hr()
                }
            }, t.prototype.keymaps = function() {
                var e = this.hr()();
                return {
                    "Mod-l": e,
                    "Mod-L": e
                }
            }, t
        }(Ql);

    function Lc(e, t) {
        var n = e.type;
        return t <= e.sourcepos[0][0] && ("codeBlock" === n || "heading" === n || n.match("table"))
    }
    var Ic = function(e) {
        function t() {
            return null !== e && e.apply(this, arguments) || this
        }
        return ji(t, e), Object.defineProperty(t.prototype, "name", {
            get: function() {
                return "listItem"
            },
            enumerable: !1,
            configurable: !0
        }), Object.defineProperty(t.prototype, "schema", {
            get: function() {
                return {
                    attrs: {
                        odd: {
                            default: !1
                        },
                        even: {
                            default: !1
                        },
                        listStyle: {
                            default: !1
                        }
                    },
                    toDOM: function(e) {
                        var t = e.attrs,
                            n = t.odd,
                            r = t.even,
                            o = "list-item";
                        return t.listStyle && (o += "|list-item-style"), n && (o += "|list-item-odd"), r && (o += "|list-item-even"), ["span", {
                            class: Ya.apply(void 0, o.split("|"))
                        }, 0]
                    }
                }
            },
            enumerable: !1,
            configurable: !0
        }), t.prototype.extendList = function() {
            var e = this;
            return function(t, n) {
                var r = t.selection,
                    o = t.doc,
                    i = t.schema,
                    s = t.tr,
                    a = e.context.toastMark,
                    l = Ol(r),
                    c = l.to,
                    u = l.startFromOffset,
                    d = l.endFromOffset,
                    p = l.endIndex,
                    h = l.endToOffset,
                    f = ec(o, p);
                if (!rc.test(f) || r.from === u || !r.empty) return !1;
                if (f.replace(sc, "").trim()) {
                    var m = uc(f),
                        g = a.findFirstNodeAtLine(p + 1),
                        v = f.slice(c - d),
                        y = {
                            toastMark: a,
                            mdNode: g,
                            doc: o,
                            line: p + 1
                        },
                        b = vc[m](y),
                        w = b.listSyntax,
                        k = b.changedResults;
                    if (null == k ? void 0 : k.length) {
                        s.split(c), k.unshift({
                            text: w + v,
                            line: p + 1
                        }), e.changeToListPerLine(s, k, {
                            from: c,
                            startLine: k[0].line,
                            endLine: Ks(k).line
                        });
                        var x = s.mapping.map(h) - v.length;
                        s.setSelection(ia(s, x))
                    } else la(s, h, v, oa(i, w + v))
                } else s.deleteRange(d, h).split(s.mapping.map(h));
                return n(s), !0
            }
        }, t.prototype.toList = function(e) {
            var t = this;
            return function() {
                return function(n, r) {
                    for (var o = n.doc, i = n.tr, s = n.selection, a = t.context.toastMark, l = Ol(s), c = l.startIndex + 1, u = l.endIndex + 1, d = l.endToOffset, p = [], h = c; h <= u; h += 1) {
                        var f = a.findFirstNodeAtLine(h);
                        if (f && Lc(f, h)) break;
                        if (-1 === p.indexOf(h)) {
                            var m = {
                                    toastMark: a,
                                    mdNode: f,
                                    doc: o,
                                    line: h,
                                    startLine: c
                                },
                                g = (fa(f) ? mc[e](m) : gc[e](m)).changedResults,
                                v = t.changeToListPerLine(i, g, {
                                    from: Dl(o, g[0].line - 1).startOffset,
                                    startLine: g[0].line,
                                    endLine: Ks(g).line,
                                    indexDiff: 1
                                });
                            d = Math.max(v, d), g && (p = p.concat(g.map(function(e) {
                                return e.line
                            })))
                        }
                    }
                    return r(i.setSelection(ia(i, i.mapping.map(d)))), !0
                }
            }
        }, t.prototype.changeToListPerLine = function(e, t, n) {
            for (var r = n.from, o = n.startLine, i = n.endLine, s = n.indexDiff, a = void 0 === s ? 0 : s, l = 0, c = function(n) {
                    var o = e.doc.child(n),
                        i = o.nodeSize,
                        s = o.content,
                        c = e.mapping.map(r),
                        d = c + s.size,
                        p = t.filter(function(e) {
                            return e.line - a === n
                        })[0];
                    p && (e.replaceWith(c, d, oa(u.context.schema, p.text)), l = Math.max(l, r + s.size)), r += i
                }, u = this, d = o - a; d <= i - a; d += 1) c(d);
            return l
        }, t.prototype.toggleTask = function() {
            var e = this;
            return function(t, n) {
                for (var r = t.selection, o = t.tr, i = t.doc, s = t.schema, a = e.context.toastMark, l = Ol(r), c = l.startIndex, u = l.endIndex, d = null, p = c; p <= u; p += 1) {
                    var h = a.findFirstNodeAtLine(p + 1);
                    if (fa(h) && h.listData.task) {
                        var f = h.listData,
                            m = f.checked,
                            g = f.padding,
                            v = m ? " " : "x",
                            y = h.sourcepos[0],
                            b = Dl(i, y[0] - 1).startOffset;
                        b += y[1] + g, d = o.replaceWith(b, b + 1, s.text(v))
                    }
                }
                return !!d && (n(d), !0)
            }
        }, t.prototype.commands = function() {
            return {
                bulletList: this.toList("bullet"),
                orderedList: this.toList("ordered"),
                taskList: this.toList("task")
            }
        }, t.prototype.keymaps = function() {
            var e = this.toList("bullet")(),
                t = this.toList("ordered")(),
                n = this.toList("task")(),
                r = this.toggleTask();
            return {
                "Mod-u": e,
                "Mod-U": e,
                "Mod-o": t,
                "Mod-O": t,
                "alt-t": n,
                "alt-T": n,
                "Shift-Ctrl-x": r,
                "Shift-Ctrl-X": r,
                Enter: this.extendList()
            }
        }, t
    }(Ql);

    function Rc(e, t) {
        return function() {
            return function(n, r) {
                var o = n.tr,
                    i = n.selection,
                    s = bl(e) ? e : function(t) {
                        return e.test(t)
                    },
                    a = t.length,
                    l = o.doc,
                    c = Cl(i),
                    u = c[0],
                    d = c[1],
                    p = Math.max(u - a, 1),
                    h = Math.min(d + a, l.content.size - 1),
                    f = i.content(),
                    m = f.content.textBetween(0, f.content.size, "\n"),
                    g = l.textBetween(p, u, "\n"),
                    v = l.textBetween(d, h, "\n");
                if (m = "" + g + m + v, g && v && s(m)) o.delete(h - a, h).delete(p, p + a);
                else {
                    o.insertText(t, d).insertText(t, u);
                    var y = i.empty ? ia(o, u + a) : ia(o, u + a, d + a);
                    o.setSelection(y)
                }
                return r(o), !0
            }
        }
    }
    var Pc = /^(\*{2}|_{2}).*([\s\S]*)\1$/m,
        Bc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "strong"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("strong")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.bold = function() {
                return Rc(Pc, "**")
            }, t.prototype.commands = function() {
                return {
                    bold: this.bold()
                }
            }, t.prototype.keymaps = function() {
                var e = this.bold()();
                return {
                    "Mod-b": e,
                    "Mod-B": e
                }
            }, t
        }(Ql),
        Fc = /^(~{2}).*([\s\S]*)\1$/m,
        Hc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "strike"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("strike")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return Rc(Fc, "~~")
            }, t.prototype.keymaps = function() {
                var e = this.commands()();
                return {
                    "Mod-s": e,
                    "Mod-S": e
                }
            }, t
        }(Ql),
        zc = /^(\*|_).*([\s\S]*)\1$/m,
        qc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "emph"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("emph")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.italic = function() {
                return Rc(zc, "*")
            }, t.prototype.commands = function() {
                return {
                    italic: this.italic()
                }
            }, t.prototype.keymaps = function() {
                var e = this.italic()();
                return {
                    "Mod-i": e,
                    "Mod-I": e
                }
            }, t
        }(Ql),
        Vc = /^(`).*([\s\S]*)\1$/m,
        jc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "code"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        attrs: {
                            start: {
                                default: !1
                            },
                            end: {
                                default: !1
                            },
                            marked: {
                                default: !1
                            }
                        },
                        toDOM: function(e) {
                            var t = e.attrs,
                                n = "code";
                            return t.start && (n += "|delimiter|start"), t.end && (n += "|delimiter|end"), t.marked && (n += "|marked-text"), ["span", {
                                class: Ya.apply(void 0, n.split("|"))
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return Rc(Vc, "`")
            }, t.prototype.keymaps = function() {
                var e = this.commands()();
                return {
                    "Shift-Mod-c": e,
                    "Shift-Mod-C": e
                }
            }, t
        }(Ql),
        $c = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "link"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        attrs: {
                            url: {
                                default: !1
                            },
                            desc: {
                                default: !1
                            }
                        },
                        toDOM: function(e) {
                            var t = e.attrs,
                                n = "link";
                            return t.url && (n += "|link-url|marked-text"), t.desc && (n += "|link-desc|marked-text"), ["span", {
                                class: Ya.apply(void 0, n.split("|"))
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.addLinkOrImage = function(e) {
                return function(t) {
                    return function(n, r) {
                        var o = n.selection,
                            i = n.tr,
                            s = n.schema,
                            a = Cl(o),
                            l = a[0],
                            c = a[1],
                            u = t,
                            d = u.linkText,
                            p = u.altText,
                            h = u.linkUrl,
                            f = u.imageUrl,
                            m = d,
                            g = h,
                            v = "";
                        return "image" === e && (m = p, g = f, v = "!"), v += "[" + (m = _s(m)) + "](" + g + ")", r(i.replaceWith(l, c, oa(s, v))), !0
                    }
                }
            }, t.prototype.commands = function() {
                return {
                    addImage: this.addLinkOrImage("image"),
                    addLink: this.addLinkOrImage("link")
                }
            }, t
        }(Ql),
        _c = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "taskDelimiter"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("delimiter", "list-item")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(Ql),
        Uc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "delimiter"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("delimiter")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(Ql),
        Wc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "meta"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("meta")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(Ql),
        Jc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "markedText"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("marked-text")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(Ql),
        Kc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "tableCell"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("table-cell")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(Ql),
        Gc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "html"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("html")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(Ql),
        Xc = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "customBlock"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        toDOM: function() {
                            return ["span", {
                                class: Ya("custom-block")
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function(e) {
                    return function(t, n) {
                        var r = t.selection,
                            o = t.schema,
                            i = t.tr,
                            s = Ol(r),
                            a = s.startFromOffset,
                            l = s.endToOffset;
                        if (!(null == e ? void 0 : e.info)) return !1;
                        var c = "$$" + e.info,
                            u = oa(o, c),
                            d = oa(o, "$$");
                        return i.insert(a, u).split(a + c.length), i.split(i.mapping.map(l)).insert(i.mapping.map(l), d), n(i.setSelection(ia(i, i.mapping.map(l) - 4))), !0
                    }
                }
            }, t
        }(Ql),
        Zc = /x|backspace/i,
        Qc = /^\[(\s*)(x?)(\s*)\](?:\s+)/i;

    function Yc(e) {
        var t = e.schema,
            n = e.toastMark;
        return new wt({
            props: {
                handleDOMEvents: {
                    keyup: function(e, r) {
                        var o, i = e.state,
                            s = i.doc,
                            a = i.tr,
                            l = i.selection;
                        if (l.empty && Zc.test(r.key)) {
                            var c = Ol(l),
                                u = c.startIndex,
                                d = c.startFromOffset,
                                p = [u + 1, c.from - d + 1],
                                h = ya(n.findNodeAtPosition(p), function(e) {
                                    var t;
                                    return "paragraph" === e.type && "item" === (null === (t = e.parent) || void 0 === t ? void 0 : t.type)
                                });
                            if (null === (o = null == h ? void 0 : h.firstChild) || void 0 === o ? void 0 : o.literal) {
                                var f = h.firstChild,
                                    m = f.literal.match(Qc);
                                if (m) {
                                    var g = f.sourcepos[0],
                                        v = m[1],
                                        y = m[2],
                                        b = m[3],
                                        w = v.length + b.length,
                                        k = Dl(s, g[0] - 1).startOffset,
                                        x = g[1] + k;
                                    if (y) {
                                        var C = w ? w + 1 : 0;
                                        a.replaceWith(x, C + x, t.text(y)), e.dispatch(a)
                                    } else w || (a.insertText(" ", x), e.dispatch(a))
                                }
                            }
                        }
                        return !1
                    }
                }
            }
        })
    }
    var eu = "cut",
        tu = /\r\n|\n|\r/,
        nu = function(e) {
            function t(t, n) {
                var r = e.call(this, t) || this,
                    o = n.toastMark,
                    i = n.useCommandShortcut,
                    s = void 0 === i || i,
                    a = n.mdPlugins,
                    l = void 0 === a ? [] : a;
                return r.editorType = "markdown", r.el.classList.add("md-mode"), r.toastMark = o, r.extraPlugins = l, r.specs = r.createSpecs(), r.schema = r.createSchema(), r.context = r.createContext(), r.keymaps = r.createKeymaps(s), r.view = r.createView(), r.commands = r.createCommands(), r.specs.setContext($i($i({}, r.context), {
                    view: r.view
                })), r.createClipboard(), r.eventEmitter.listen("changePreviewTabWrite", function(e) {
                    return r.toggleActive(!0, e)
                }), r.eventEmitter.listen("changePreviewTabPreview", function() {
                    return r.toggleActive(!1)
                }), r.initEvent(), r
            }
            return ji(t, e), t.prototype.toggleActive = function(e, t) {
                nl(this.el, "active", e), e ? t || this.focus() : this.blur()
            }, t.prototype.createClipboard = function() {
                var e = this;
                this.clipboard = document.createElement("textarea"), this.clipboard.className = Qa("pseudo-clipboard"), this.clipboard.addEventListener("paste", function(t) {
                    var n = t.clipboardData || window.clipboardData,
                        r = n && n.items;
                    if (r) {
                        var o = na(r).some(function(e) {
                            return "string" === e.kind && "text/rtf" === e.type
                        });
                        if (!o) {
                            var i = pl(r);
                            i && (t.preventDefault(), dl(e.eventEmitter, i, t.type))
                        }
                    }
                }), this.clipboard.addEventListener("input", function(t) {
                    var n = t.target.value;
                    e.replaceSelection(n), t.preventDefault(), t.target.value = ""
                }), this.el.insertBefore(this.clipboard, this.view.dom)
            }, t.prototype.createContext = function() {
                return {
                    toastMark: this.toastMark,
                    schema: this.schema,
                    eventEmitter: this.eventEmitter
                }
            }, t.prototype.createSpecs = function() {
                return new xl([new Zl, new Cc, new vl, new Tc, new Sc, new nc, new Ec, new Xc, new Dc, new Kc, new Ac, new Ic, new Bc, new Hc, new qc, new jc, new $c, new Uc, new _c, new Jc, new Wc, new Gc])
            }, t.prototype.createPlugins = function() {
                return _i([Jl(this.context), (e = this.context, t = e.toastMark, n = e.eventEmitter, new wt({
                    view: function() {
                        return {
                            update: function(e, r) {
                                var o = e.state,
                                    i = o.doc,
                                    s = o.selection;
                                if (!(r && r.doc.eq(i) && r.selection.eq(s))) {
                                    var a = s.from,
                                        l = o.doc.resolve(a).start(),
                                        c = a - l;
                                    a === l && (c += 1);
                                    var u = [o.doc.content.findIndex(a).index + 1, c],
                                        d = t.findNodeAtPosition(u),
                                        p = function(e) {
                                            var t = {
                                                    indent: {
                                                        active: !1,
                                                        disabled: !0
                                                    },
                                                    outdent: {
                                                        active: !1,
                                                        disabled: !0
                                                    }
                                                },
                                                n = !0;
                                            return function(e, t, n) {
                                                for (void 0 === n && (n = !0), e = n ? e : e.parent; e && "document" !== e.type;) t(e), e = e.parent
                                            }(e, function(e) {
                                                var r = function(e) {
                                                    var t = e.type;
                                                    return fa(e) ? e.listData.task ? "taskList" : "ordered" === e.listData.type ? "orderedList" : "bulletList" : -1 !== t.indexOf("table") ? "table" : zs(Xl, t) ? t : null
                                                }(e);
                                                r && ("bulletList" === r || "orderedList" === r ? n && (t[r] = {
                                                    active: !0
                                                }, t.indent.disabled = !1, t.outdent.disabled = !1, n = !1) : t[r] = {
                                                    active: !0
                                                })
                                            }), t
                                        }(d);
                                    n.emit("changeToolbarState", {
                                        cursorPos: u,
                                        mdNode: d,
                                        toolbarState: p
                                    }), n.emit("setFocusedNode", d)
                                }
                            }
                        }
                    }
                })), Yc(this.context)], this.createPluginProps()).concat(this.defaultPlugins);
                var e, t, n
            }, t.prototype.createView = function() {
                var e = this;
                return new Ao(this.el, {
                    state: this.createState(),
                    dispatchTransaction: function(t) {
                        e.updateMarkdown(t);
                        var n = e.view.state.applyTransaction(t).state;
                        e.view.updateState(n), e.emitChangeEvent(t)
                    },
                    handleKeyDown: function(t, n) {
                        return (n.metaKey || n.ctrlKey) && "V" === n.key.toUpperCase() && e.clipboard.focus(), e.eventEmitter.emit("keydown", e.editorType, n), !1
                    },
                    handleDOMEvents: {
                        copy: function(t, n) {
                            return e.captureCopy(n)
                        },
                        cut: function(t, n) {
                            return e.captureCopy(n, eu)
                        },
                        scroll: function() {
                            return e.eventEmitter.emit("scroll", "editor"), !0
                        },
                        keyup: function(t, n) {
                            return e.eventEmitter.emit("keyup", e.editorType, n), !1
                        }
                    },
                    nodeViews: {
                        widget: ml
                    }
                })
            }, t.prototype.createCommands = function() {
                return this.specs.commands(this.view)
            }, t.prototype.captureCopy = function(e, t) {
                e.preventDefault();
                var n = this.view.state,
                    r = n.selection,
                    o = n.tr;
                if (r.empty) return !0;
                var i = this.getChanged(r.content());
                return e.clipboardData ? e.clipboardData.setData("text/plain", i) : window.clipboardData.setData("Text", i), t === eu && this.view.dispatch(o.deleteSelection().scrollIntoView().setMeta("uiEvent", eu)), !0
            }, t.prototype.updateMarkdown = function(e) {
                var t = this;
                e.docChanged && e.steps.forEach(function(n, r) {
                    if (n.slice && !(n instanceof Oe)) {
                        var o = e.docs[r],
                            i = [n.from, n.to],
                            s = Sl(o, i[0], i[1]),
                            a = s[0],
                            l = s[1],
                            c = t.getChanged(n.slice);
                        a[0] === l[0] && a[1] === l[1] && "" === c && (c = "\n");
                        var u = t.toastMark.editMarkdown(a, l, c);
                        t.eventEmitter.emit("updatePreview", u), e.setMeta("editResult", u).scrollIntoView()
                    }
                })
            }, t.prototype.getChanged = function(e) {
                var t = "",
                    n = e.content.size;
                return e.content.nodesBetween(0, n, function(e, r) {
                    e.isText ? t += e.text.slice(Math.max(0, r) - r, n - r) : e.isBlock && r > 0 && (t += "\n")
                }), t
            }, t.prototype.setSelection = function(e, t) {
                void 0 === t && (t = e);
                var n = this.view.state.tr,
                    r = Nl(n.doc, e, t),
                    o = r[0],
                    i = r[1];
                this.view.dispatch(n.setSelection(ia(n, o, i)).scrollIntoView())
            }, t.prototype.replaceSelection = function(e, t, n) {
                var r, o = this.view.state,
                    i = o.tr,
                    s = o.schema,
                    a = o.doc,
                    c = e.split(tu).map(function(e) {
                        return ra(s, La(e, s))
                    }),
                    u = new f(l.from(c), 1, 1);
                if (this.focus(), t && n) {
                    var d = Nl(a, t, n),
                        p = d[0],
                        h = d[1];
                    r = i.replaceRange(p, h, u)
                } else r = i.replaceSelection(u);
                this.view.dispatch(r.scrollIntoView())
            }, t.prototype.deleteSelection = function(e, t) {
                var n, r = this.view.state,
                    o = r.tr,
                    i = r.doc;
                if (e && t) {
                    var s = Nl(i, e, t),
                        a = s[0],
                        l = s[1];
                    n = o.deleteRange(a, l)
                } else n = o.deleteSelection();
                this.view.dispatch(n.scrollIntoView())
            }, t.prototype.getSelectedText = function(e, t) {
                var n = this.view.state,
                    r = n.doc,
                    o = n.selection,
                    i = o.from,
                    s = o.to;
                if (e && t) {
                    var a = Nl(r, e, t);
                    i = a[0], s = a[1]
                }
                return r.textBetween(i, s, "\n")
            }, t.prototype.getSelection = function() {
                var e = this.view.state.selection,
                    t = e.from,
                    n = e.to;
                return Sl(this.view.state.tr.doc, t, n)
            }, t.prototype.setMarkdown = function(e, t) {
                void 0 === t && (t = !0);
                var n = e.split(tu),
                    r = this.view.state,
                    o = r.tr,
                    i = r.doc,
                    s = r.schema,
                    a = n.map(function(e) {
                        return ra(s, La(e, s))
                    });
                this.view.dispatch(o.replaceWith(0, i.content.size, a)), t && this.moveCursorToEnd(!0)
            }, t.prototype.addWidget = function(e, t, n) {
                var r = this.view.state,
                    o = r.tr,
                    i = r.doc,
                    s = r.selection,
                    a = n ? Nl(i, n, n)[0] : s.to;
                this.view.dispatch(o.setMeta("widget", {
                    pos: a,
                    node: e,
                    style: t
                }))
            }, t.prototype.replaceWithWidget = function(e, t, n) {
                var r = this.view.state,
                    o = r.tr,
                    i = r.schema,
                    s = Nl(r.doc, e, t),
                    a = La(n, i);
                this.view.dispatch(o.replaceWith(s[0], s[1], a))
            }, t.prototype.getRangeInfoOfNode = function(e) {
                var t = this.view.state,
                    n = t.doc,
                    r = t.selection,
                    o = e || Sl(n, r.from)[0],
                    i = this.toastMark.findNodeAtPosition(o);
                return "text" === i.type && "paragraph" !== i.parent.type && (i = i.parent), i.sourcepos[1][1] += 1, {
                    range: i.sourcepos,
                    type: i.type
                }
            }, t.prototype.getMarkdown = function() {
                return this.toastMark.getLineTexts().map(function(e) {
                    return Ea(e)
                }).join("\n")
            }, t.prototype.getToastMark = function() {
                return this.toastMark
            }, t
        }(yl),
        ru = "_feEventKey",
        ou = function(e, t) {
            var n, r = e[ru];
            return r || (r = e[ru] = {}), (n = r[t]) || (n = r[t] = []), n
        },
        iu = Ki,
        su = es,
        au = ou;

    function lu(e, t, n) {
        var r, o = au(e, t);
        n ? (su(o, function(o, i) {
            return n !== o.handler || (cu(e, t, o.wrappedHandler), r = i, !1)
        }), o.splice(r, 1)) : (su(o, function(n) {
            cu(e, t, n.wrappedHandler)
        }), o.splice(0, o.length))
    }

    function cu(e, t, n) {
        "removeEventListener" in e ? e.removeEventListener(t, n) : "detachEvent" in e && e.detachEvent("on" + t, n)
    }
    var uu = function(e, t, n) {
            iu(t) ? su(t.split(/\s+/g), function(t) {
                lu(e, t, n)
            }) : su(t, function(t, n) {
                lu(e, n, t)
            })
        },
        du = Ki,
        pu = es,
        hu = ou;

    function fu(e, t, n, r) {
        function o(t) {
            n.call(r || e, t || window.event)
        }
        "addEventListener" in e ? e.addEventListener(t, o) : "attachEvent" in e && e.attachEvent("on" + t, o),
            function(e, t, n, r) {
                var o = hu(e, t),
                    i = !1;
                pu(o, function(e) {
                    return e.handler !== n || (i = !0, !1)
                }), i || o.push({
                    handler: n,
                    wrappedHandler: r
                })
            }(e, t, n, o)
    }
    var mu = function(e, t, n, r) {
            du(t) ? pu(t.split(/\s+/g), function(t) {
                fu(e, t, n, r)
            }) : pu(t, function(t, r) {
                fu(e, r, t, n)
            })
        },
        gu = function(e, t) {
            return gu = Object.setPrototypeOf || {
                __proto__: []
            }
            instanceof Array && function(e, t) {
                e.__proto__ = t
            } || function(e, t) {
                for (var n in t) Object.prototype.hasOwnProperty.call(t, n) && (e[n] = t[n])
            }, gu(e, t)
        };

    function vu(e, t) {
        if ("function" != typeof t && null !== t) throw new TypeError("Class extends value " + String(t) + " is not a constructor or null");

        function n() {
            this.constructor = e
        }
        gu(e, t), e.prototype = null === t ? Object.create(t) : (n.prototype = t.prototype, new n)
    }
    var yu = function() {
        return yu = Object.assign || function(e) {
            for (var t, n = 1, r = arguments.length; n < r; n++)
                for (var o in t = arguments[n]) Object.prototype.hasOwnProperty.call(t, o) && (e[o] = t[o]);
            return e
        }, yu.apply(this, arguments)
    };

    function bu(e, t, n) {
        if (n || 2 === arguments.length)
            for (var r, o = 0, i = t.length; o < i; o++) !r && o in t || (r || (r = Array.prototype.slice.call(t, 0, o)), r[o] = t[o]);
        return e.concat(r || Array.prototype.slice.call(t))
    }
    var wu = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : void 0 !== e.g ? e.g : "undefined" != typeof self ? self : {},
        ku = {};

    function xu(e, t, n) {
        var r, o, i, s, a, l = "";
        for ("string" != typeof t && (n = t, t = xu.defaultChars), void 0 === n && (n = !0), a = function(e) {
                var t, n, r = ku[e];
                if (r) return r;
                for (r = ku[e] = [], t = 0; t < 128; t++) n = String.fromCharCode(t), /^[0-9a-z]$/i.test(n) ? r.push(n) : r.push("%" + ("0" + t.toString(16).toUpperCase()).slice(-2));
                for (t = 0; t < e.length; t++) r[e.charCodeAt(t)] = e[t];
                return r
            }(t), r = 0, o = e.length; r < o; r++)
            if (i = e.charCodeAt(r), n && 37 === i && r + 2 < o && /^[0-9a-f]{2}$/i.test(e.slice(r + 1, r + 3))) l += e.slice(r, r + 3), r += 2;
            else if (i < 128) l += a[i];
        else if (i >= 55296 && i <= 57343) {
            if (i >= 55296 && i <= 56319 && r + 1 < o && (s = e.charCodeAt(r + 1)) >= 56320 && s <= 57343) {
                l += encodeURIComponent(e[r] + e[r + 1]), r++;
                continue
            }
            l += "%EF%BF%BD"
        } else l += encodeURIComponent(e[r]);
        return l
    }
    xu.defaultChars = ";/?:@&=+$,-_.!~*'()#", xu.componentChars = "-_.!~*'()";
    var Cu = xu,
        Tu = {},
        Mu = {},
        Su = {
            Aacute: "Á",
            aacute: "á",
            Abreve: "Ă",
            abreve: "ă",
            ac: "∾",
            acd: "∿",
            acE: "∾̳",
            Acirc: "Â",
            acirc: "â",
            acute: "´",
            Acy: "А",
            acy: "а",
            AElig: "Æ",
            aelig: "æ",
            af: "⁡",
            Afr: "𝔄",
            afr: "𝔞",
            Agrave: "À",
            agrave: "à",
            alefsym: "ℵ",
            aleph: "ℵ",
            Alpha: "Α",
            alpha: "α",
            Amacr: "Ā",
            amacr: "ā",
            amalg: "⨿",
            amp: "&",
            AMP: "&",
            andand: "⩕",
            And: "⩓",
            and: "∧",
            andd: "⩜",
            andslope: "⩘",
            andv: "⩚",
            ang: "∠",
            ange: "⦤",
            angle: "∠",
            angmsdaa: "⦨",
            angmsdab: "⦩",
            angmsdac: "⦪",
            angmsdad: "⦫",
            angmsdae: "⦬",
            angmsdaf: "⦭",
            angmsdag: "⦮",
            angmsdah: "⦯",
            angmsd: "∡",
            angrt: "∟",
            angrtvb: "⊾",
            angrtvbd: "⦝",
            angsph: "∢",
            angst: "Å",
            angzarr: "⍼",
            Aogon: "Ą",
            aogon: "ą",
            Aopf: "𝔸",
            aopf: "𝕒",
            apacir: "⩯",
            ap: "≈",
            apE: "⩰",
            ape: "≊",
            apid: "≋",
            apos: "'",
            ApplyFunction: "⁡",
            approx: "≈",
            approxeq: "≊",
            Aring: "Å",
            aring: "å",
            Ascr: "𝒜",
            ascr: "𝒶",
            Assign: "≔",
            ast: "*",
            asymp: "≈",
            asympeq: "≍",
            Atilde: "Ã",
            atilde: "ã",
            Auml: "Ä",
            auml: "ä",
            awconint: "∳",
            awint: "⨑",
            backcong: "≌",
            backepsilon: "϶",
            backprime: "‵",
            backsim: "∽",
            backsimeq: "⋍",
            Backslash: "∖",
            Barv: "⫧",
            barvee: "⊽",
            barwed: "⌅",
            Barwed: "⌆",
            barwedge: "⌅",
            bbrk: "⎵",
            bbrktbrk: "⎶",
            bcong: "≌",
            Bcy: "Б",
            bcy: "б",
            bdquo: "„",
            becaus: "∵",
            because: "∵",
            Because: "∵",
            bemptyv: "⦰",
            bepsi: "϶",
            bernou: "ℬ",
            Bernoullis: "ℬ",
            Beta: "Β",
            beta: "β",
            beth: "ℶ",
            between: "≬",
            Bfr: "𝔅",
            bfr: "𝔟",
            bigcap: "⋂",
            bigcirc: "◯",
            bigcup: "⋃",
            bigodot: "⨀",
            bigoplus: "⨁",
            bigotimes: "⨂",
            bigsqcup: "⨆",
            bigstar: "★",
            bigtriangledown: "▽",
            bigtriangleup: "△",
            biguplus: "⨄",
            bigvee: "⋁",
            bigwedge: "⋀",
            bkarow: "⤍",
            blacklozenge: "⧫",
            blacksquare: "▪",
            blacktriangle: "▴",
            blacktriangledown: "▾",
            blacktriangleleft: "◂",
            blacktriangleright: "▸",
            blank: "␣",
            blk12: "▒",
            blk14: "░",
            blk34: "▓",
            block: "█",
            bne: "=⃥",
            bnequiv: "≡⃥",
            bNot: "⫭",
            bnot: "⌐",
            Bopf: "𝔹",
            bopf: "𝕓",
            bot: "⊥",
            bottom: "⊥",
            bowtie: "⋈",
            boxbox: "⧉",
            boxdl: "┐",
            boxdL: "╕",
            boxDl: "╖",
            boxDL: "╗",
            boxdr: "┌",
            boxdR: "╒",
            boxDr: "╓",
            boxDR: "╔",
            boxh: "─",
            boxH: "═",
            boxhd: "┬",
            boxHd: "╤",
            boxhD: "╥",
            boxHD: "╦",
            boxhu: "┴",
            boxHu: "╧",
            boxhU: "╨",
            boxHU: "╩",
            boxminus: "⊟",
            boxplus: "⊞",
            boxtimes: "⊠",
            boxul: "┘",
            boxuL: "╛",
            boxUl: "╜",
            boxUL: "╝",
            boxur: "└",
            boxuR: "╘",
            boxUr: "╙",
            boxUR: "╚",
            boxv: "│",
            boxV: "║",
            boxvh: "┼",
            boxvH: "╪",
            boxVh: "╫",
            boxVH: "╬",
            boxvl: "┤",
            boxvL: "╡",
            boxVl: "╢",
            boxVL: "╣",
            boxvr: "├",
            boxvR: "╞",
            boxVr: "╟",
            boxVR: "╠",
            bprime: "‵",
            breve: "˘",
            Breve: "˘",
            brvbar: "¦",
            bscr: "𝒷",
            Bscr: "ℬ",
            bsemi: "⁏",
            bsim: "∽",
            bsime: "⋍",
            bsolb: "⧅",
            bsol: "\\",
            bsolhsub: "⟈",
            bull: "•",
            bullet: "•",
            bump: "≎",
            bumpE: "⪮",
            bumpe: "≏",
            Bumpeq: "≎",
            bumpeq: "≏",
            Cacute: "Ć",
            cacute: "ć",
            capand: "⩄",
            capbrcup: "⩉",
            capcap: "⩋",
            cap: "∩",
            Cap: "⋒",
            capcup: "⩇",
            capdot: "⩀",
            CapitalDifferentialD: "ⅅ",
            caps: "∩︀",
            caret: "⁁",
            caron: "ˇ",
            Cayleys: "ℭ",
            ccaps: "⩍",
            Ccaron: "Č",
            ccaron: "č",
            Ccedil: "Ç",
            ccedil: "ç",
            Ccirc: "Ĉ",
            ccirc: "ĉ",
            Cconint: "∰",
            ccups: "⩌",
            ccupssm: "⩐",
            Cdot: "Ċ",
            cdot: "ċ",
            cedil: "¸",
            Cedilla: "¸",
            cemptyv: "⦲",
            cent: "¢",
            centerdot: "·",
            CenterDot: "·",
            cfr: "𝔠",
            Cfr: "ℭ",
            CHcy: "Ч",
            chcy: "ч",
            check: "✓",
            checkmark: "✓",
            Chi: "Χ",
            chi: "χ",
            circ: "ˆ",
            circeq: "≗",
            circlearrowleft: "↺",
            circlearrowright: "↻",
            circledast: "⊛",
            circledcirc: "⊚",
            circleddash: "⊝",
            CircleDot: "⊙",
            circledR: "®",
            circledS: "Ⓢ",
            CircleMinus: "⊖",
            CirclePlus: "⊕",
            CircleTimes: "⊗",
            cir: "○",
            cirE: "⧃",
            cire: "≗",
            cirfnint: "⨐",
            cirmid: "⫯",
            cirscir: "⧂",
            ClockwiseContourIntegral: "∲",
            CloseCurlyDoubleQuote: "”",
            CloseCurlyQuote: "’",
            clubs: "♣",
            clubsuit: "♣",
            colon: ":",
            Colon: "∷",
            Colone: "⩴",
            colone: "≔",
            coloneq: "≔",
            comma: ",",
            commat: "@",
            comp: "∁",
            compfn: "∘",
            complement: "∁",
            complexes: "ℂ",
            cong: "≅",
            congdot: "⩭",
            Congruent: "≡",
            conint: "∮",
            Conint: "∯",
            ContourIntegral: "∮",
            copf: "𝕔",
            Copf: "ℂ",
            coprod: "∐",
            Coproduct: "∐",
            copy: "©",
            COPY: "©",
            copysr: "℗",
            CounterClockwiseContourIntegral: "∳",
            crarr: "↵",
            cross: "✗",
            Cross: "⨯",
            Cscr: "𝒞",
            cscr: "𝒸",
            csub: "⫏",
            csube: "⫑",
            csup: "⫐",
            csupe: "⫒",
            ctdot: "⋯",
            cudarrl: "⤸",
            cudarrr: "⤵",
            cuepr: "⋞",
            cuesc: "⋟",
            cularr: "↶",
            cularrp: "⤽",
            cupbrcap: "⩈",
            cupcap: "⩆",
            CupCap: "≍",
            cup: "∪",
            Cup: "⋓",
            cupcup: "⩊",
            cupdot: "⊍",
            cupor: "⩅",
            cups: "∪︀",
            curarr: "↷",
            curarrm: "⤼",
            curlyeqprec: "⋞",
            curlyeqsucc: "⋟",
            curlyvee: "⋎",
            curlywedge: "⋏",
            curren: "¤",
            curvearrowleft: "↶",
            curvearrowright: "↷",
            cuvee: "⋎",
            cuwed: "⋏",
            cwconint: "∲",
            cwint: "∱",
            cylcty: "⌭",
            dagger: "†",
            Dagger: "‡",
            daleth: "ℸ",
            darr: "↓",
            Darr: "↡",
            dArr: "⇓",
            dash: "‐",
            Dashv: "⫤",
            dashv: "⊣",
            dbkarow: "⤏",
            dblac: "˝",
            Dcaron: "Ď",
            dcaron: "ď",
            Dcy: "Д",
            dcy: "д",
            ddagger: "‡",
            ddarr: "⇊",
            DD: "ⅅ",
            dd: "ⅆ",
            DDotrahd: "⤑",
            ddotseq: "⩷",
            deg: "°",
            Del: "∇",
            Delta: "Δ",
            delta: "δ",
            demptyv: "⦱",
            dfisht: "⥿",
            Dfr: "𝔇",
            dfr: "𝔡",
            dHar: "⥥",
            dharl: "⇃",
            dharr: "⇂",
            DiacriticalAcute: "´",
            DiacriticalDot: "˙",
            DiacriticalDoubleAcute: "˝",
            DiacriticalGrave: "`",
            DiacriticalTilde: "˜",
            diam: "⋄",
            diamond: "⋄",
            Diamond: "⋄",
            diamondsuit: "♦",
            diams: "♦",
            die: "¨",
            DifferentialD: "ⅆ",
            digamma: "ϝ",
            disin: "⋲",
            div: "÷",
            divide: "÷",
            divideontimes: "⋇",
            divonx: "⋇",
            DJcy: "Ђ",
            djcy: "ђ",
            dlcorn: "⌞",
            dlcrop: "⌍",
            dollar: "$",
            Dopf: "𝔻",
            dopf: "𝕕",
            Dot: "¨",
            dot: "˙",
            DotDot: "⃜",
            doteq: "≐",
            doteqdot: "≑",
            DotEqual: "≐",
            dotminus: "∸",
            dotplus: "∔",
            dotsquare: "⊡",
            doublebarwedge: "⌆",
            DoubleContourIntegral: "∯",
            DoubleDot: "¨",
            DoubleDownArrow: "⇓",
            DoubleLeftArrow: "⇐",
            DoubleLeftRightArrow: "⇔",
            DoubleLeftTee: "⫤",
            DoubleLongLeftArrow: "⟸",
            DoubleLongLeftRightArrow: "⟺",
            DoubleLongRightArrow: "⟹",
            DoubleRightArrow: "⇒",
            DoubleRightTee: "⊨",
            DoubleUpArrow: "⇑",
            DoubleUpDownArrow: "⇕",
            DoubleVerticalBar: "∥",
            DownArrowBar: "⤓",
            downarrow: "↓",
            DownArrow: "↓",
            Downarrow: "⇓",
            DownArrowUpArrow: "⇵",
            DownBreve: "̑",
            downdownarrows: "⇊",
            downharpoonleft: "⇃",
            downharpoonright: "⇂",
            DownLeftRightVector: "⥐",
            DownLeftTeeVector: "⥞",
            DownLeftVectorBar: "⥖",
            DownLeftVector: "↽",
            DownRightTeeVector: "⥟",
            DownRightVectorBar: "⥗",
            DownRightVector: "⇁",
            DownTeeArrow: "↧",
            DownTee: "⊤",
            drbkarow: "⤐",
            drcorn: "⌟",
            drcrop: "⌌",
            Dscr: "𝒟",
            dscr: "𝒹",
            DScy: "Ѕ",
            dscy: "ѕ",
            dsol: "⧶",
            Dstrok: "Đ",
            dstrok: "đ",
            dtdot: "⋱",
            dtri: "▿",
            dtrif: "▾",
            duarr: "⇵",
            duhar: "⥯",
            dwangle: "⦦",
            DZcy: "Џ",
            dzcy: "џ",
            dzigrarr: "⟿",
            Eacute: "É",
            eacute: "é",
            easter: "⩮",
            Ecaron: "Ě",
            ecaron: "ě",
            Ecirc: "Ê",
            ecirc: "ê",
            ecir: "≖",
            ecolon: "≕",
            Ecy: "Э",
            ecy: "э",
            eDDot: "⩷",
            Edot: "Ė",
            edot: "ė",
            eDot: "≑",
            ee: "ⅇ",
            efDot: "≒",
            Efr: "𝔈",
            efr: "𝔢",
            eg: "⪚",
            Egrave: "È",
            egrave: "è",
            egs: "⪖",
            egsdot: "⪘",
            el: "⪙",
            Element: "∈",
            elinters: "⏧",
            ell: "ℓ",
            els: "⪕",
            elsdot: "⪗",
            Emacr: "Ē",
            emacr: "ē",
            empty: "∅",
            emptyset: "∅",
            EmptySmallSquare: "◻",
            emptyv: "∅",
            EmptyVerySmallSquare: "▫",
            emsp13: " ",
            emsp14: " ",
            emsp: " ",
            ENG: "Ŋ",
            eng: "ŋ",
            ensp: " ",
            Eogon: "Ę",
            eogon: "ę",
            Eopf: "𝔼",
            eopf: "𝕖",
            epar: "⋕",
            eparsl: "⧣",
            eplus: "⩱",
            epsi: "ε",
            Epsilon: "Ε",
            epsilon: "ε",
            epsiv: "ϵ",
            eqcirc: "≖",
            eqcolon: "≕",
            eqsim: "≂",
            eqslantgtr: "⪖",
            eqslantless: "⪕",
            Equal: "⩵",
            equals: "=",
            EqualTilde: "≂",
            equest: "≟",
            Equilibrium: "⇌",
            equiv: "≡",
            equivDD: "⩸",
            eqvparsl: "⧥",
            erarr: "⥱",
            erDot: "≓",
            escr: "ℯ",
            Escr: "ℰ",
            esdot: "≐",
            Esim: "⩳",
            esim: "≂",
            Eta: "Η",
            eta: "η",
            ETH: "Ð",
            eth: "ð",
            Euml: "Ë",
            euml: "ë",
            euro: "€",
            excl: "!",
            exist: "∃",
            Exists: "∃",
            expectation: "ℰ",
            exponentiale: "ⅇ",
            ExponentialE: "ⅇ",
            fallingdotseq: "≒",
            Fcy: "Ф",
            fcy: "ф",
            female: "♀",
            ffilig: "ﬃ",
            fflig: "ﬀ",
            ffllig: "ﬄ",
            Ffr: "𝔉",
            ffr: "𝔣",
            filig: "ﬁ",
            FilledSmallSquare: "◼",
            FilledVerySmallSquare: "▪",
            fjlig: "fj",
            flat: "♭",
            fllig: "ﬂ",
            fltns: "▱",
            fnof: "ƒ",
            Fopf: "𝔽",
            fopf: "𝕗",
            forall: "∀",
            ForAll: "∀",
            fork: "⋔",
            forkv: "⫙",
            Fouriertrf: "ℱ",
            fpartint: "⨍",
            frac12: "½",
            frac13: "⅓",
            frac14: "¼",
            frac15: "⅕",
            frac16: "⅙",
            frac18: "⅛",
            frac23: "⅔",
            frac25: "⅖",
            frac34: "¾",
            frac35: "⅗",
            frac38: "⅜",
            frac45: "⅘",
            frac56: "⅚",
            frac58: "⅝",
            frac78: "⅞",
            frasl: "⁄",
            frown: "⌢",
            fscr: "𝒻",
            Fscr: "ℱ",
            gacute: "ǵ",
            Gamma: "Γ",
            gamma: "γ",
            Gammad: "Ϝ",
            gammad: "ϝ",
            gap: "⪆",
            Gbreve: "Ğ",
            gbreve: "ğ",
            Gcedil: "Ģ",
            Gcirc: "Ĝ",
            gcirc: "ĝ",
            Gcy: "Г",
            gcy: "г",
            Gdot: "Ġ",
            gdot: "ġ",
            ge: "≥",
            gE: "≧",
            gEl: "⪌",
            gel: "⋛",
            geq: "≥",
            geqq: "≧",
            geqslant: "⩾",
            gescc: "⪩",
            ges: "⩾",
            gesdot: "⪀",
            gesdoto: "⪂",
            gesdotol: "⪄",
            gesl: "⋛︀",
            gesles: "⪔",
            Gfr: "𝔊",
            gfr: "𝔤",
            gg: "≫",
            Gg: "⋙",
            ggg: "⋙",
            gimel: "ℷ",
            GJcy: "Ѓ",
            gjcy: "ѓ",
            gla: "⪥",
            gl: "≷",
            glE: "⪒",
            glj: "⪤",
            gnap: "⪊",
            gnapprox: "⪊",
            gne: "⪈",
            gnE: "≩",
            gneq: "⪈",
            gneqq: "≩",
            gnsim: "⋧",
            Gopf: "𝔾",
            gopf: "𝕘",
            grave: "`",
            GreaterEqual: "≥",
            GreaterEqualLess: "⋛",
            GreaterFullEqual: "≧",
            GreaterGreater: "⪢",
            GreaterLess: "≷",
            GreaterSlantEqual: "⩾",
            GreaterTilde: "≳",
            Gscr: "𝒢",
            gscr: "ℊ",
            gsim: "≳",
            gsime: "⪎",
            gsiml: "⪐",
            gtcc: "⪧",
            gtcir: "⩺",
            gt: ">",
            GT: ">",
            Gt: "≫",
            gtdot: "⋗",
            gtlPar: "⦕",
            gtquest: "⩼",
            gtrapprox: "⪆",
            gtrarr: "⥸",
            gtrdot: "⋗",
            gtreqless: "⋛",
            gtreqqless: "⪌",
            gtrless: "≷",
            gtrsim: "≳",
            gvertneqq: "≩︀",
            gvnE: "≩︀",
            Hacek: "ˇ",
            hairsp: " ",
            half: "½",
            hamilt: "ℋ",
            HARDcy: "Ъ",
            hardcy: "ъ",
            harrcir: "⥈",
            harr: "↔",
            hArr: "⇔",
            harrw: "↭",
            Hat: "^",
            hbar: "ℏ",
            Hcirc: "Ĥ",
            hcirc: "ĥ",
            hearts: "♥",
            heartsuit: "♥",
            hellip: "…",
            hercon: "⊹",
            hfr: "𝔥",
            Hfr: "ℌ",
            HilbertSpace: "ℋ",
            hksearow: "⤥",
            hkswarow: "⤦",
            hoarr: "⇿",
            homtht: "∻",
            hookleftarrow: "↩",
            hookrightarrow: "↪",
            hopf: "𝕙",
            Hopf: "ℍ",
            horbar: "―",
            HorizontalLine: "─",
            hscr: "𝒽",
            Hscr: "ℋ",
            hslash: "ℏ",
            Hstrok: "Ħ",
            hstrok: "ħ",
            HumpDownHump: "≎",
            HumpEqual: "≏",
            hybull: "⁃",
            hyphen: "‐",
            Iacute: "Í",
            iacute: "í",
            ic: "⁣",
            Icirc: "Î",
            icirc: "î",
            Icy: "И",
            icy: "и",
            Idot: "İ",
            IEcy: "Е",
            iecy: "е",
            iexcl: "¡",
            iff: "⇔",
            ifr: "𝔦",
            Ifr: "ℑ",
            Igrave: "Ì",
            igrave: "ì",
            ii: "ⅈ",
            iiiint: "⨌",
            iiint: "∭",
            iinfin: "⧜",
            iiota: "℩",
            IJlig: "Ĳ",
            ijlig: "ĳ",
            Imacr: "Ī",
            imacr: "ī",
            image: "ℑ",
            ImaginaryI: "ⅈ",
            imagline: "ℐ",
            imagpart: "ℑ",
            imath: "ı",
            Im: "ℑ",
            imof: "⊷",
            imped: "Ƶ",
            Implies: "⇒",
            incare: "℅",
            in: "∈",
            infin: "∞",
            infintie: "⧝",
            inodot: "ı",
            intcal: "⊺",
            int: "∫",
            Int: "∬",
            integers: "ℤ",
            Integral: "∫",
            intercal: "⊺",
            Intersection: "⋂",
            intlarhk: "⨗",
            intprod: "⨼",
            InvisibleComma: "⁣",
            InvisibleTimes: "⁢",
            IOcy: "Ё",
            iocy: "ё",
            Iogon: "Į",
            iogon: "į",
            Iopf: "𝕀",
            iopf: "𝕚",
            Iota: "Ι",
            iota: "ι",
            iprod: "⨼",
            iquest: "¿",
            iscr: "𝒾",
            Iscr: "ℐ",
            isin: "∈",
            isindot: "⋵",
            isinE: "⋹",
            isins: "⋴",
            isinsv: "⋳",
            isinv: "∈",
            it: "⁢",
            Itilde: "Ĩ",
            itilde: "ĩ",
            Iukcy: "І",
            iukcy: "і",
            Iuml: "Ï",
            iuml: "ï",
            Jcirc: "Ĵ",
            jcirc: "ĵ",
            Jcy: "Й",
            jcy: "й",
            Jfr: "𝔍",
            jfr: "𝔧",
            jmath: "ȷ",
            Jopf: "𝕁",
            jopf: "𝕛",
            Jscr: "𝒥",
            jscr: "𝒿",
            Jsercy: "Ј",
            jsercy: "ј",
            Jukcy: "Є",
            jukcy: "є",
            Kappa: "Κ",
            kappa: "κ",
            kappav: "ϰ",
            Kcedil: "Ķ",
            kcedil: "ķ",
            Kcy: "К",
            kcy: "к",
            Kfr: "𝔎",
            kfr: "𝔨",
            kgreen: "ĸ",
            KHcy: "Х",
            khcy: "х",
            KJcy: "Ќ",
            kjcy: "ќ",
            Kopf: "𝕂",
            kopf: "𝕜",
            Kscr: "𝒦",
            kscr: "𝓀",
            lAarr: "⇚",
            Lacute: "Ĺ",
            lacute: "ĺ",
            laemptyv: "⦴",
            lagran: "ℒ",
            Lambda: "Λ",
            lambda: "λ",
            lang: "⟨",
            Lang: "⟪",
            langd: "⦑",
            langle: "⟨",
            lap: "⪅",
            Laplacetrf: "ℒ",
            laquo: "«",
            larrb: "⇤",
            larrbfs: "⤟",
            larr: "←",
            Larr: "↞",
            lArr: "⇐",
            larrfs: "⤝",
            larrhk: "↩",
            larrlp: "↫",
            larrpl: "⤹",
            larrsim: "⥳",
            larrtl: "↢",
            latail: "⤙",
            lAtail: "⤛",
            lat: "⪫",
            late: "⪭",
            lates: "⪭︀",
            lbarr: "⤌",
            lBarr: "⤎",
            lbbrk: "❲",
            lbrace: "{",
            lbrack: "[",
            lbrke: "⦋",
            lbrksld: "⦏",
            lbrkslu: "⦍",
            Lcaron: "Ľ",
            lcaron: "ľ",
            Lcedil: "Ļ",
            lcedil: "ļ",
            lceil: "⌈",
            lcub: "{",
            Lcy: "Л",
            lcy: "л",
            ldca: "⤶",
            ldquo: "“",
            ldquor: "„",
            ldrdhar: "⥧",
            ldrushar: "⥋",
            ldsh: "↲",
            le: "≤",
            lE: "≦",
            LeftAngleBracket: "⟨",
            LeftArrowBar: "⇤",
            leftarrow: "←",
            LeftArrow: "←",
            Leftarrow: "⇐",
            LeftArrowRightArrow: "⇆",
            leftarrowtail: "↢",
            LeftCeiling: "⌈",
            LeftDoubleBracket: "⟦",
            LeftDownTeeVector: "⥡",
            LeftDownVectorBar: "⥙",
            LeftDownVector: "⇃",
            LeftFloor: "⌊",
            leftharpoondown: "↽",
            leftharpoonup: "↼",
            leftleftarrows: "⇇",
            leftrightarrow: "↔",
            LeftRightArrow: "↔",
            Leftrightarrow: "⇔",
            leftrightarrows: "⇆",
            leftrightharpoons: "⇋",
            leftrightsquigarrow: "↭",
            LeftRightVector: "⥎",
            LeftTeeArrow: "↤",
            LeftTee: "⊣",
            LeftTeeVector: "⥚",
            leftthreetimes: "⋋",
            LeftTriangleBar: "⧏",
            LeftTriangle: "⊲",
            LeftTriangleEqual: "⊴",
            LeftUpDownVector: "⥑",
            LeftUpTeeVector: "⥠",
            LeftUpVectorBar: "⥘",
            LeftUpVector: "↿",
            LeftVectorBar: "⥒",
            LeftVector: "↼",
            lEg: "⪋",
            leg: "⋚",
            leq: "≤",
            leqq: "≦",
            leqslant: "⩽",
            lescc: "⪨",
            les: "⩽",
            lesdot: "⩿",
            lesdoto: "⪁",
            lesdotor: "⪃",
            lesg: "⋚︀",
            lesges: "⪓",
            lessapprox: "⪅",
            lessdot: "⋖",
            lesseqgtr: "⋚",
            lesseqqgtr: "⪋",
            LessEqualGreater: "⋚",
            LessFullEqual: "≦",
            LessGreater: "≶",
            lessgtr: "≶",
            LessLess: "⪡",
            lesssim: "≲",
            LessSlantEqual: "⩽",
            LessTilde: "≲",
            lfisht: "⥼",
            lfloor: "⌊",
            Lfr: "𝔏",
            lfr: "𝔩",
            lg: "≶",
            lgE: "⪑",
            lHar: "⥢",
            lhard: "↽",
            lharu: "↼",
            lharul: "⥪",
            lhblk: "▄",
            LJcy: "Љ",
            ljcy: "љ",
            llarr: "⇇",
            ll: "≪",
            Ll: "⋘",
            llcorner: "⌞",
            Lleftarrow: "⇚",
            llhard: "⥫",
            lltri: "◺",
            Lmidot: "Ŀ",
            lmidot: "ŀ",
            lmoustache: "⎰",
            lmoust: "⎰",
            lnap: "⪉",
            lnapprox: "⪉",
            lne: "⪇",
            lnE: "≨",
            lneq: "⪇",
            lneqq: "≨",
            lnsim: "⋦",
            loang: "⟬",
            loarr: "⇽",
            lobrk: "⟦",
            longleftarrow: "⟵",
            LongLeftArrow: "⟵",
            Longleftarrow: "⟸",
            longleftrightarrow: "⟷",
            LongLeftRightArrow: "⟷",
            Longleftrightarrow: "⟺",
            longmapsto: "⟼",
            longrightarrow: "⟶",
            LongRightArrow: "⟶",
            Longrightarrow: "⟹",
            looparrowleft: "↫",
            looparrowright: "↬",
            lopar: "⦅",
            Lopf: "𝕃",
            lopf: "𝕝",
            loplus: "⨭",
            lotimes: "⨴",
            lowast: "∗",
            lowbar: "_",
            LowerLeftArrow: "↙",
            LowerRightArrow: "↘",
            loz: "◊",
            lozenge: "◊",
            lozf: "⧫",
            lpar: "(",
            lparlt: "⦓",
            lrarr: "⇆",
            lrcorner: "⌟",
            lrhar: "⇋",
            lrhard: "⥭",
            lrm: "‎",
            lrtri: "⊿",
            lsaquo: "‹",
            lscr: "𝓁",
            Lscr: "ℒ",
            lsh: "↰",
            Lsh: "↰",
            lsim: "≲",
            lsime: "⪍",
            lsimg: "⪏",
            lsqb: "[",
            lsquo: "‘",
            lsquor: "‚",
            Lstrok: "Ł",
            lstrok: "ł",
            ltcc: "⪦",
            ltcir: "⩹",
            lt: "<",
            LT: "<",
            Lt: "≪",
            ltdot: "⋖",
            lthree: "⋋",
            ltimes: "⋉",
            ltlarr: "⥶",
            ltquest: "⩻",
            ltri: "◃",
            ltrie: "⊴",
            ltrif: "◂",
            ltrPar: "⦖",
            lurdshar: "⥊",
            luruhar: "⥦",
            lvertneqq: "≨︀",
            lvnE: "≨︀",
            macr: "¯",
            male: "♂",
            malt: "✠",
            maltese: "✠",
            Map: "⤅",
            map: "↦",
            mapsto: "↦",
            mapstodown: "↧",
            mapstoleft: "↤",
            mapstoup: "↥",
            marker: "▮",
            mcomma: "⨩",
            Mcy: "М",
            mcy: "м",
            mdash: "—",
            mDDot: "∺",
            measuredangle: "∡",
            MediumSpace: " ",
            Mellintrf: "ℳ",
            Mfr: "𝔐",
            mfr: "𝔪",
            mho: "℧",
            micro: "µ",
            midast: "*",
            midcir: "⫰",
            mid: "∣",
            middot: "·",
            minusb: "⊟",
            minus: "−",
            minusd: "∸",
            minusdu: "⨪",
            MinusPlus: "∓",
            mlcp: "⫛",
            mldr: "…",
            mnplus: "∓",
            models: "⊧",
            Mopf: "𝕄",
            mopf: "𝕞",
            mp: "∓",
            mscr: "𝓂",
            Mscr: "ℳ",
            mstpos: "∾",
            Mu: "Μ",
            mu: "μ",
            multimap: "⊸",
            mumap: "⊸",
            nabla: "∇",
            Nacute: "Ń",
            nacute: "ń",
            nang: "∠⃒",
            nap: "≉",
            napE: "⩰̸",
            napid: "≋̸",
            napos: "ŉ",
            napprox: "≉",
            natural: "♮",
            naturals: "ℕ",
            natur: "♮",
            nbsp: " ",
            nbump: "≎̸",
            nbumpe: "≏̸",
            ncap: "⩃",
            Ncaron: "Ň",
            ncaron: "ň",
            Ncedil: "Ņ",
            ncedil: "ņ",
            ncong: "≇",
            ncongdot: "⩭̸",
            ncup: "⩂",
            Ncy: "Н",
            ncy: "н",
            ndash: "–",
            nearhk: "⤤",
            nearr: "↗",
            neArr: "⇗",
            nearrow: "↗",
            ne: "≠",
            nedot: "≐̸",
            NegativeMediumSpace: "​",
            NegativeThickSpace: "​",
            NegativeThinSpace: "​",
            NegativeVeryThinSpace: "​",
            nequiv: "≢",
            nesear: "⤨",
            nesim: "≂̸",
            NestedGreaterGreater: "≫",
            NestedLessLess: "≪",
            NewLine: "\n",
            nexist: "∄",
            nexists: "∄",
            Nfr: "𝔑",
            nfr: "𝔫",
            ngE: "≧̸",
            nge: "≱",
            ngeq: "≱",
            ngeqq: "≧̸",
            ngeqslant: "⩾̸",
            nges: "⩾̸",
            nGg: "⋙̸",
            ngsim: "≵",
            nGt: "≫⃒",
            ngt: "≯",
            ngtr: "≯",
            nGtv: "≫̸",
            nharr: "↮",
            nhArr: "⇎",
            nhpar: "⫲",
            ni: "∋",
            nis: "⋼",
            nisd: "⋺",
            niv: "∋",
            NJcy: "Њ",
            njcy: "њ",
            nlarr: "↚",
            nlArr: "⇍",
            nldr: "‥",
            nlE: "≦̸",
            nle: "≰",
            nleftarrow: "↚",
            nLeftarrow: "⇍",
            nleftrightarrow: "↮",
            nLeftrightarrow: "⇎",
            nleq: "≰",
            nleqq: "≦̸",
            nleqslant: "⩽̸",
            nles: "⩽̸",
            nless: "≮",
            nLl: "⋘̸",
            nlsim: "≴",
            nLt: "≪⃒",
            nlt: "≮",
            nltri: "⋪",
            nltrie: "⋬",
            nLtv: "≪̸",
            nmid: "∤",
            NoBreak: "⁠",
            NonBreakingSpace: " ",
            nopf: "𝕟",
            Nopf: "ℕ",
            Not: "⫬",
            not: "¬",
            NotCongruent: "≢",
            NotCupCap: "≭",
            NotDoubleVerticalBar: "∦",
            NotElement: "∉",
            NotEqual: "≠",
            NotEqualTilde: "≂̸",
            NotExists: "∄",
            NotGreater: "≯",
            NotGreaterEqual: "≱",
            NotGreaterFullEqual: "≧̸",
            NotGreaterGreater: "≫̸",
            NotGreaterLess: "≹",
            NotGreaterSlantEqual: "⩾̸",
            NotGreaterTilde: "≵",
            NotHumpDownHump: "≎̸",
            NotHumpEqual: "≏̸",
            notin: "∉",
            notindot: "⋵̸",
            notinE: "⋹̸",
            notinva: "∉",
            notinvb: "⋷",
            notinvc: "⋶",
            NotLeftTriangleBar: "⧏̸",
            NotLeftTriangle: "⋪",
            NotLeftTriangleEqual: "⋬",
            NotLess: "≮",
            NotLessEqual: "≰",
            NotLessGreater: "≸",
            NotLessLess: "≪̸",
            NotLessSlantEqual: "⩽̸",
            NotLessTilde: "≴",
            NotNestedGreaterGreater: "⪢̸",
            NotNestedLessLess: "⪡̸",
            notni: "∌",
            notniva: "∌",
            notnivb: "⋾",
            notnivc: "⋽",
            NotPrecedes: "⊀",
            NotPrecedesEqual: "⪯̸",
            NotPrecedesSlantEqual: "⋠",
            NotReverseElement: "∌",
            NotRightTriangleBar: "⧐̸",
            NotRightTriangle: "⋫",
            NotRightTriangleEqual: "⋭",
            NotSquareSubset: "⊏̸",
            NotSquareSubsetEqual: "⋢",
            NotSquareSuperset: "⊐̸",
            NotSquareSupersetEqual: "⋣",
            NotSubset: "⊂⃒",
            NotSubsetEqual: "⊈",
            NotSucceeds: "⊁",
            NotSucceedsEqual: "⪰̸",
            NotSucceedsSlantEqual: "⋡",
            NotSucceedsTilde: "≿̸",
            NotSuperset: "⊃⃒",
            NotSupersetEqual: "⊉",
            NotTilde: "≁",
            NotTildeEqual: "≄",
            NotTildeFullEqual: "≇",
            NotTildeTilde: "≉",
            NotVerticalBar: "∤",
            nparallel: "∦",
            npar: "∦",
            nparsl: "⫽⃥",
            npart: "∂̸",
            npolint: "⨔",
            npr: "⊀",
            nprcue: "⋠",
            nprec: "⊀",
            npreceq: "⪯̸",
            npre: "⪯̸",
            nrarrc: "⤳̸",
            nrarr: "↛",
            nrArr: "⇏",
            nrarrw: "↝̸",
            nrightarrow: "↛",
            nRightarrow: "⇏",
            nrtri: "⋫",
            nrtrie: "⋭",
            nsc: "⊁",
            nsccue: "⋡",
            nsce: "⪰̸",
            Nscr: "𝒩",
            nscr: "𝓃",
            nshortmid: "∤",
            nshortparallel: "∦",
            nsim: "≁",
            nsime: "≄",
            nsimeq: "≄",
            nsmid: "∤",
            nspar: "∦",
            nsqsube: "⋢",
            nsqsupe: "⋣",
            nsub: "⊄",
            nsubE: "⫅̸",
            nsube: "⊈",
            nsubset: "⊂⃒",
            nsubseteq: "⊈",
            nsubseteqq: "⫅̸",
            nsucc: "⊁",
            nsucceq: "⪰̸",
            nsup: "⊅",
            nsupE: "⫆̸",
            nsupe: "⊉",
            nsupset: "⊃⃒",
            nsupseteq: "⊉",
            nsupseteqq: "⫆̸",
            ntgl: "≹",
            Ntilde: "Ñ",
            ntilde: "ñ",
            ntlg: "≸",
            ntriangleleft: "⋪",
            ntrianglelefteq: "⋬",
            ntriangleright: "⋫",
            ntrianglerighteq: "⋭",
            Nu: "Ν",
            nu: "ν",
            num: "#",
            numero: "№",
            numsp: " ",
            nvap: "≍⃒",
            nvdash: "⊬",
            nvDash: "⊭",
            nVdash: "⊮",
            nVDash: "⊯",
            nvge: "≥⃒",
            nvgt: ">⃒",
            nvHarr: "⤄",
            nvinfin: "⧞",
            nvlArr: "⤂",
            nvle: "≤⃒",
            nvlt: "<⃒",
            nvltrie: "⊴⃒",
            nvrArr: "⤃",
            nvrtrie: "⊵⃒",
            nvsim: "∼⃒",
            nwarhk: "⤣",
            nwarr: "↖",
            nwArr: "⇖",
            nwarrow: "↖",
            nwnear: "⤧",
            Oacute: "Ó",
            oacute: "ó",
            oast: "⊛",
            Ocirc: "Ô",
            ocirc: "ô",
            ocir: "⊚",
            Ocy: "О",
            ocy: "о",
            odash: "⊝",
            Odblac: "Ő",
            odblac: "ő",
            odiv: "⨸",
            odot: "⊙",
            odsold: "⦼",
            OElig: "Œ",
            oelig: "œ",
            ofcir: "⦿",
            Ofr: "𝔒",
            ofr: "𝔬",
            ogon: "˛",
            Ograve: "Ò",
            ograve: "ò",
            ogt: "⧁",
            ohbar: "⦵",
            ohm: "Ω",
            oint: "∮",
            olarr: "↺",
            olcir: "⦾",
            olcross: "⦻",
            oline: "‾",
            olt: "⧀",
            Omacr: "Ō",
            omacr: "ō",
            Omega: "Ω",
            omega: "ω",
            Omicron: "Ο",
            omicron: "ο",
            omid: "⦶",
            ominus: "⊖",
            Oopf: "𝕆",
            oopf: "𝕠",
            opar: "⦷",
            OpenCurlyDoubleQuote: "“",
            OpenCurlyQuote: "‘",
            operp: "⦹",
            oplus: "⊕",
            orarr: "↻",
            Or: "⩔",
            or: "∨",
            ord: "⩝",
            order: "ℴ",
            orderof: "ℴ",
            ordf: "ª",
            ordm: "º",
            origof: "⊶",
            oror: "⩖",
            orslope: "⩗",
            orv: "⩛",
            oS: "Ⓢ",
            Oscr: "𝒪",
            oscr: "ℴ",
            Oslash: "Ø",
            oslash: "ø",
            osol: "⊘",
            Otilde: "Õ",
            otilde: "õ",
            otimesas: "⨶",
            Otimes: "⨷",
            otimes: "⊗",
            Ouml: "Ö",
            ouml: "ö",
            ovbar: "⌽",
            OverBar: "‾",
            OverBrace: "⏞",
            OverBracket: "⎴",
            OverParenthesis: "⏜",
            para: "¶",
            parallel: "∥",
            par: "∥",
            parsim: "⫳",
            parsl: "⫽",
            part: "∂",
            PartialD: "∂",
            Pcy: "П",
            pcy: "п",
            percnt: "%",
            period: ".",
            permil: "‰",
            perp: "⊥",
            pertenk: "‱",
            Pfr: "𝔓",
            pfr: "𝔭",
            Phi: "Φ",
            phi: "φ",
            phiv: "ϕ",
            phmmat: "ℳ",
            phone: "☎",
            Pi: "Π",
            pi: "π",
            pitchfork: "⋔",
            piv: "ϖ",
            planck: "ℏ",
            planckh: "ℎ",
            plankv: "ℏ",
            plusacir: "⨣",
            plusb: "⊞",
            pluscir: "⨢",
            plus: "+",
            plusdo: "∔",
            plusdu: "⨥",
            pluse: "⩲",
            PlusMinus: "±",
            plusmn: "±",
            plussim: "⨦",
            plustwo: "⨧",
            pm: "±",
            Poincareplane: "ℌ",
            pointint: "⨕",
            popf: "𝕡",
            Popf: "ℙ",
            pound: "£",
            prap: "⪷",
            Pr: "⪻",
            pr: "≺",
            prcue: "≼",
            precapprox: "⪷",
            prec: "≺",
            preccurlyeq: "≼",
            Precedes: "≺",
            PrecedesEqual: "⪯",
            PrecedesSlantEqual: "≼",
            PrecedesTilde: "≾",
            preceq: "⪯",
            precnapprox: "⪹",
            precneqq: "⪵",
            precnsim: "⋨",
            pre: "⪯",
            prE: "⪳",
            precsim: "≾",
            prime: "′",
            Prime: "″",
            primes: "ℙ",
            prnap: "⪹",
            prnE: "⪵",
            prnsim: "⋨",
            prod: "∏",
            Product: "∏",
            profalar: "⌮",
            profline: "⌒",
            profsurf: "⌓",
            prop: "∝",
            Proportional: "∝",
            Proportion: "∷",
            propto: "∝",
            prsim: "≾",
            prurel: "⊰",
            Pscr: "𝒫",
            pscr: "𝓅",
            Psi: "Ψ",
            psi: "ψ",
            puncsp: " ",
            Qfr: "𝔔",
            qfr: "𝔮",
            qint: "⨌",
            qopf: "𝕢",
            Qopf: "ℚ",
            qprime: "⁗",
            Qscr: "𝒬",
            qscr: "𝓆",
            quaternions: "ℍ",
            quatint: "⨖",
            quest: "?",
            questeq: "≟",
            quot: '"',
            QUOT: '"',
            rAarr: "⇛",
            race: "∽̱",
            Racute: "Ŕ",
            racute: "ŕ",
            radic: "√",
            raemptyv: "⦳",
            rang: "⟩",
            Rang: "⟫",
            rangd: "⦒",
            range: "⦥",
            rangle: "⟩",
            raquo: "»",
            rarrap: "⥵",
            rarrb: "⇥",
            rarrbfs: "⤠",
            rarrc: "⤳",
            rarr: "→",
            Rarr: "↠",
            rArr: "⇒",
            rarrfs: "⤞",
            rarrhk: "↪",
            rarrlp: "↬",
            rarrpl: "⥅",
            rarrsim: "⥴",
            Rarrtl: "⤖",
            rarrtl: "↣",
            rarrw: "↝",
            ratail: "⤚",
            rAtail: "⤜",
            ratio: "∶",
            rationals: "ℚ",
            rbarr: "⤍",
            rBarr: "⤏",
            RBarr: "⤐",
            rbbrk: "❳",
            rbrace: "}",
            rbrack: "]",
            rbrke: "⦌",
            rbrksld: "⦎",
            rbrkslu: "⦐",
            Rcaron: "Ř",
            rcaron: "ř",
            Rcedil: "Ŗ",
            rcedil: "ŗ",
            rceil: "⌉",
            rcub: "}",
            Rcy: "Р",
            rcy: "р",
            rdca: "⤷",
            rdldhar: "⥩",
            rdquo: "”",
            rdquor: "”",
            rdsh: "↳",
            real: "ℜ",
            realine: "ℛ",
            realpart: "ℜ",
            reals: "ℝ",
            Re: "ℜ",
            rect: "▭",
            reg: "®",
            REG: "®",
            ReverseElement: "∋",
            ReverseEquilibrium: "⇋",
            ReverseUpEquilibrium: "⥯",
            rfisht: "⥽",
            rfloor: "⌋",
            rfr: "𝔯",
            Rfr: "ℜ",
            rHar: "⥤",
            rhard: "⇁",
            rharu: "⇀",
            rharul: "⥬",
            Rho: "Ρ",
            rho: "ρ",
            rhov: "ϱ",
            RightAngleBracket: "⟩",
            RightArrowBar: "⇥",
            rightarrow: "→",
            RightArrow: "→",
            Rightarrow: "⇒",
            RightArrowLeftArrow: "⇄",
            rightarrowtail: "↣",
            RightCeiling: "⌉",
            RightDoubleBracket: "⟧",
            RightDownTeeVector: "⥝",
            RightDownVectorBar: "⥕",
            RightDownVector: "⇂",
            RightFloor: "⌋",
            rightharpoondown: "⇁",
            rightharpoonup: "⇀",
            rightleftarrows: "⇄",
            rightleftharpoons: "⇌",
            rightrightarrows: "⇉",
            rightsquigarrow: "↝",
            RightTeeArrow: "↦",
            RightTee: "⊢",
            RightTeeVector: "⥛",
            rightthreetimes: "⋌",
            RightTriangleBar: "⧐",
            RightTriangle: "⊳",
            RightTriangleEqual: "⊵",
            RightUpDownVector: "⥏",
            RightUpTeeVector: "⥜",
            RightUpVectorBar: "⥔",
            RightUpVector: "↾",
            RightVectorBar: "⥓",
            RightVector: "⇀",
            ring: "˚",
            risingdotseq: "≓",
            rlarr: "⇄",
            rlhar: "⇌",
            rlm: "‏",
            rmoustache: "⎱",
            rmoust: "⎱",
            rnmid: "⫮",
            roang: "⟭",
            roarr: "⇾",
            robrk: "⟧",
            ropar: "⦆",
            ropf: "𝕣",
            Ropf: "ℝ",
            roplus: "⨮",
            rotimes: "⨵",
            RoundImplies: "⥰",
            rpar: ")",
            rpargt: "⦔",
            rppolint: "⨒",
            rrarr: "⇉",
            Rrightarrow: "⇛",
            rsaquo: "›",
            rscr: "𝓇",
            Rscr: "ℛ",
            rsh: "↱",
            Rsh: "↱",
            rsqb: "]",
            rsquo: "’",
            rsquor: "’",
            rthree: "⋌",
            rtimes: "⋊",
            rtri: "▹",
            rtrie: "⊵",
            rtrif: "▸",
            rtriltri: "⧎",
            RuleDelayed: "⧴",
            ruluhar: "⥨",
            rx: "℞",
            Sacute: "Ś",
            sacute: "ś",
            sbquo: "‚",
            scap: "⪸",
            Scaron: "Š",
            scaron: "š",
            Sc: "⪼",
            sc: "≻",
            sccue: "≽",
            sce: "⪰",
            scE: "⪴",
            Scedil: "Ş",
            scedil: "ş",
            Scirc: "Ŝ",
            scirc: "ŝ",
            scnap: "⪺",
            scnE: "⪶",
            scnsim: "⋩",
            scpolint: "⨓",
            scsim: "≿",
            Scy: "С",
            scy: "с",
            sdotb: "⊡",
            sdot: "⋅",
            sdote: "⩦",
            searhk: "⤥",
            searr: "↘",
            seArr: "⇘",
            searrow: "↘",
            sect: "§",
            semi: ";",
            seswar: "⤩",
            setminus: "∖",
            setmn: "∖",
            sext: "✶",
            Sfr: "𝔖",
            sfr: "𝔰",
            sfrown: "⌢",
            sharp: "♯",
            SHCHcy: "Щ",
            shchcy: "щ",
            SHcy: "Ш",
            shcy: "ш",
            ShortDownArrow: "↓",
            ShortLeftArrow: "←",
            shortmid: "∣",
            shortparallel: "∥",
            ShortRightArrow: "→",
            ShortUpArrow: "↑",
            shy: "­",
            Sigma: "Σ",
            sigma: "σ",
            sigmaf: "ς",
            sigmav: "ς",
            sim: "∼",
            simdot: "⩪",
            sime: "≃",
            simeq: "≃",
            simg: "⪞",
            simgE: "⪠",
            siml: "⪝",
            simlE: "⪟",
            simne: "≆",
            simplus: "⨤",
            simrarr: "⥲",
            slarr: "←",
            SmallCircle: "∘",
            smallsetminus: "∖",
            smashp: "⨳",
            smeparsl: "⧤",
            smid: "∣",
            smile: "⌣",
            smt: "⪪",
            smte: "⪬",
            smtes: "⪬︀",
            SOFTcy: "Ь",
            softcy: "ь",
            solbar: "⌿",
            solb: "⧄",
            sol: "/",
            Sopf: "𝕊",
            sopf: "𝕤",
            spades: "♠",
            spadesuit: "♠",
            spar: "∥",
            sqcap: "⊓",
            sqcaps: "⊓︀",
            sqcup: "⊔",
            sqcups: "⊔︀",
            Sqrt: "√",
            sqsub: "⊏",
            sqsube: "⊑",
            sqsubset: "⊏",
            sqsubseteq: "⊑",
            sqsup: "⊐",
            sqsupe: "⊒",
            sqsupset: "⊐",
            sqsupseteq: "⊒",
            square: "□",
            Square: "□",
            SquareIntersection: "⊓",
            SquareSubset: "⊏",
            SquareSubsetEqual: "⊑",
            SquareSuperset: "⊐",
            SquareSupersetEqual: "⊒",
            SquareUnion: "⊔",
            squarf: "▪",
            squ: "□",
            squf: "▪",
            srarr: "→",
            Sscr: "𝒮",
            sscr: "𝓈",
            ssetmn: "∖",
            ssmile: "⌣",
            sstarf: "⋆",
            Star: "⋆",
            star: "☆",
            starf: "★",
            straightepsilon: "ϵ",
            straightphi: "ϕ",
            strns: "¯",
            sub: "⊂",
            Sub: "⋐",
            subdot: "⪽",
            subE: "⫅",
            sube: "⊆",
            subedot: "⫃",
            submult: "⫁",
            subnE: "⫋",
            subne: "⊊",
            subplus: "⪿",
            subrarr: "⥹",
            subset: "⊂",
            Subset: "⋐",
            subseteq: "⊆",
            subseteqq: "⫅",
            SubsetEqual: "⊆",
            subsetneq: "⊊",
            subsetneqq: "⫋",
            subsim: "⫇",
            subsub: "⫕",
            subsup: "⫓",
            succapprox: "⪸",
            succ: "≻",
            succcurlyeq: "≽",
            Succeeds: "≻",
            SucceedsEqual: "⪰",
            SucceedsSlantEqual: "≽",
            SucceedsTilde: "≿",
            succeq: "⪰",
            succnapprox: "⪺",
            succneqq: "⪶",
            succnsim: "⋩",
            succsim: "≿",
            SuchThat: "∋",
            sum: "∑",
            Sum: "∑",
            sung: "♪",
            sup1: "¹",
            sup2: "²",
            sup3: "³",
            sup: "⊃",
            Sup: "⋑",
            supdot: "⪾",
            supdsub: "⫘",
            supE: "⫆",
            supe: "⊇",
            supedot: "⫄",
            Superset: "⊃",
            SupersetEqual: "⊇",
            suphsol: "⟉",
            suphsub: "⫗",
            suplarr: "⥻",
            supmult: "⫂",
            supnE: "⫌",
            supne: "⊋",
            supplus: "⫀",
            supset: "⊃",
            Supset: "⋑",
            supseteq: "⊇",
            supseteqq: "⫆",
            supsetneq: "⊋",
            supsetneqq: "⫌",
            supsim: "⫈",
            supsub: "⫔",
            supsup: "⫖",
            swarhk: "⤦",
            swarr: "↙",
            swArr: "⇙",
            swarrow: "↙",
            swnwar: "⤪",
            szlig: "ß",
            Tab: "\t",
            target: "⌖",
            Tau: "Τ",
            tau: "τ",
            tbrk: "⎴",
            Tcaron: "Ť",
            tcaron: "ť",
            Tcedil: "Ţ",
            tcedil: "ţ",
            Tcy: "Т",
            tcy: "т",
            tdot: "⃛",
            telrec: "⌕",
            Tfr: "𝔗",
            tfr: "𝔱",
            there4: "∴",
            therefore: "∴",
            Therefore: "∴",
            Theta: "Θ",
            theta: "θ",
            thetasym: "ϑ",
            thetav: "ϑ",
            thickapprox: "≈",
            thicksim: "∼",
            ThickSpace: "  ",
            ThinSpace: " ",
            thinsp: " ",
            thkap: "≈",
            thksim: "∼",
            THORN: "Þ",
            thorn: "þ",
            tilde: "˜",
            Tilde: "∼",
            TildeEqual: "≃",
            TildeFullEqual: "≅",
            TildeTilde: "≈",
            timesbar: "⨱",
            timesb: "⊠",
            times: "×",
            timesd: "⨰",
            tint: "∭",
            toea: "⤨",
            topbot: "⌶",
            topcir: "⫱",
            top: "⊤",
            Topf: "𝕋",
            topf: "𝕥",
            topfork: "⫚",
            tosa: "⤩",
            tprime: "‴",
            trade: "™",
            TRADE: "™",
            triangle: "▵",
            triangledown: "▿",
            triangleleft: "◃",
            trianglelefteq: "⊴",
            triangleq: "≜",
            triangleright: "▹",
            trianglerighteq: "⊵",
            tridot: "◬",
            trie: "≜",
            triminus: "⨺",
            TripleDot: "⃛",
            triplus: "⨹",
            trisb: "⧍",
            tritime: "⨻",
            trpezium: "⏢",
            Tscr: "𝒯",
            tscr: "𝓉",
            TScy: "Ц",
            tscy: "ц",
            TSHcy: "Ћ",
            tshcy: "ћ",
            Tstrok: "Ŧ",
            tstrok: "ŧ",
            twixt: "≬",
            twoheadleftarrow: "↞",
            twoheadrightarrow: "↠",
            Uacute: "Ú",
            uacute: "ú",
            uarr: "↑",
            Uarr: "↟",
            uArr: "⇑",
            Uarrocir: "⥉",
            Ubrcy: "Ў",
            ubrcy: "ў",
            Ubreve: "Ŭ",
            ubreve: "ŭ",
            Ucirc: "Û",
            ucirc: "û",
            Ucy: "У",
            ucy: "у",
            udarr: "⇅",
            Udblac: "Ű",
            udblac: "ű",
            udhar: "⥮",
            ufisht: "⥾",
            Ufr: "𝔘",
            ufr: "𝔲",
            Ugrave: "Ù",
            ugrave: "ù",
            uHar: "⥣",
            uharl: "↿",
            uharr: "↾",
            uhblk: "▀",
            ulcorn: "⌜",
            ulcorner: "⌜",
            ulcrop: "⌏",
            ultri: "◸",
            Umacr: "Ū",
            umacr: "ū",
            uml: "¨",
            UnderBar: "_",
            UnderBrace: "⏟",
            UnderBracket: "⎵",
            UnderParenthesis: "⏝",
            Union: "⋃",
            UnionPlus: "⊎",
            Uogon: "Ų",
            uogon: "ų",
            Uopf: "𝕌",
            uopf: "𝕦",
            UpArrowBar: "⤒",
            uparrow: "↑",
            UpArrow: "↑",
            Uparrow: "⇑",
            UpArrowDownArrow: "⇅",
            updownarrow: "↕",
            UpDownArrow: "↕",
            Updownarrow: "⇕",
            UpEquilibrium: "⥮",
            upharpoonleft: "↿",
            upharpoonright: "↾",
            uplus: "⊎",
            UpperLeftArrow: "↖",
            UpperRightArrow: "↗",
            upsi: "υ",
            Upsi: "ϒ",
            upsih: "ϒ",
            Upsilon: "Υ",
            upsilon: "υ",
            UpTeeArrow: "↥",
            UpTee: "⊥",
            upuparrows: "⇈",
            urcorn: "⌝",
            urcorner: "⌝",
            urcrop: "⌎",
            Uring: "Ů",
            uring: "ů",
            urtri: "◹",
            Uscr: "𝒰",
            uscr: "𝓊",
            utdot: "⋰",
            Utilde: "Ũ",
            utilde: "ũ",
            utri: "▵",
            utrif: "▴",
            uuarr: "⇈",
            Uuml: "Ü",
            uuml: "ü",
            uwangle: "⦧",
            vangrt: "⦜",
            varepsilon: "ϵ",
            varkappa: "ϰ",
            varnothing: "∅",
            varphi: "ϕ",
            varpi: "ϖ",
            varpropto: "∝",
            varr: "↕",
            vArr: "⇕",
            varrho: "ϱ",
            varsigma: "ς",
            varsubsetneq: "⊊︀",
            varsubsetneqq: "⫋︀",
            varsupsetneq: "⊋︀",
            varsupsetneqq: "⫌︀",
            vartheta: "ϑ",
            vartriangleleft: "⊲",
            vartriangleright: "⊳",
            vBar: "⫨",
            Vbar: "⫫",
            vBarv: "⫩",
            Vcy: "В",
            vcy: "в",
            vdash: "⊢",
            vDash: "⊨",
            Vdash: "⊩",
            VDash: "⊫",
            Vdashl: "⫦",
            veebar: "⊻",
            vee: "∨",
            Vee: "⋁",
            veeeq: "≚",
            vellip: "⋮",
            verbar: "|",
            Verbar: "‖",
            vert: "|",
            Vert: "‖",
            VerticalBar: "∣",
            VerticalLine: "|",
            VerticalSeparator: "❘",
            VerticalTilde: "≀",
            VeryThinSpace: " ",
            Vfr: "𝔙",
            vfr: "𝔳",
            vltri: "⊲",
            vnsub: "⊂⃒",
            vnsup: "⊃⃒",
            Vopf: "𝕍",
            vopf: "𝕧",
            vprop: "∝",
            vrtri: "⊳",
            Vscr: "𝒱",
            vscr: "𝓋",
            vsubnE: "⫋︀",
            vsubne: "⊊︀",
            vsupnE: "⫌︀",
            vsupne: "⊋︀",
            Vvdash: "⊪",
            vzigzag: "⦚",
            Wcirc: "Ŵ",
            wcirc: "ŵ",
            wedbar: "⩟",
            wedge: "∧",
            Wedge: "⋀",
            wedgeq: "≙",
            weierp: "℘",
            Wfr: "𝔚",
            wfr: "𝔴",
            Wopf: "𝕎",
            wopf: "𝕨",
            wp: "℘",
            wr: "≀",
            wreath: "≀",
            Wscr: "𝒲",
            wscr: "𝓌",
            xcap: "⋂",
            xcirc: "◯",
            xcup: "⋃",
            xdtri: "▽",
            Xfr: "𝔛",
            xfr: "𝔵",
            xharr: "⟷",
            xhArr: "⟺",
            Xi: "Ξ",
            xi: "ξ",
            xlarr: "⟵",
            xlArr: "⟸",
            xmap: "⟼",
            xnis: "⋻",
            xodot: "⨀",
            Xopf: "𝕏",
            xopf: "𝕩",
            xoplus: "⨁",
            xotime: "⨂",
            xrarr: "⟶",
            xrArr: "⟹",
            Xscr: "𝒳",
            xscr: "𝓍",
            xsqcup: "⨆",
            xuplus: "⨄",
            xutri: "△",
            xvee: "⋁",
            xwedge: "⋀",
            Yacute: "Ý",
            yacute: "ý",
            YAcy: "Я",
            yacy: "я",
            Ycirc: "Ŷ",
            ycirc: "ŷ",
            Ycy: "Ы",
            ycy: "ы",
            yen: "¥",
            Yfr: "𝔜",
            yfr: "𝔶",
            YIcy: "Ї",
            yicy: "ї",
            Yopf: "𝕐",
            yopf: "𝕪",
            Yscr: "𝒴",
            yscr: "𝓎",
            YUcy: "Ю",
            yucy: "ю",
            yuml: "ÿ",
            Yuml: "Ÿ",
            Zacute: "Ź",
            zacute: "ź",
            Zcaron: "Ž",
            zcaron: "ž",
            Zcy: "З",
            zcy: "з",
            Zdot: "Ż",
            zdot: "ż",
            zeetrf: "ℨ",
            ZeroWidthSpace: "​",
            Zeta: "Ζ",
            zeta: "ζ",
            zfr: "𝔷",
            Zfr: "ℨ",
            ZHcy: "Ж",
            zhcy: "ж",
            zigrarr: "⇝",
            zopf: "𝕫",
            Zopf: "ℤ",
            Zscr: "𝒵",
            zscr: "𝓏",
            zwj: "‍",
            zwnj: "‌"
        },
        Eu = {
            amp: "&",
            apos: "'",
            gt: ">",
            lt: "<",
            quot: '"'
        },
        Nu = {},
        Ou = wu && wu.__importDefault || function(e) {
            return e && e.__esModule ? e : {
                default: e
            }
        };
    Object.defineProperty(Nu, "__esModule", {
        value: !0
    });
    var Du = Ou({
            0: 65533,
            128: 8364,
            130: 8218,
            131: 402,
            132: 8222,
            133: 8230,
            134: 8224,
            135: 8225,
            136: 710,
            137: 8240,
            138: 352,
            139: 8249,
            140: 338,
            142: 381,
            145: 8216,
            146: 8217,
            147: 8220,
            148: 8221,
            149: 8226,
            150: 8211,
            151: 8212,
            152: 732,
            153: 8482,
            154: 353,
            155: 8250,
            156: 339,
            158: 382,
            159: 376
        }),
        Au = String.fromCodePoint || function(e) {
            var t = "";
            return e > 65535 && (e -= 65536, t += String.fromCharCode(e >>> 10 & 1023 | 55296), e = 56320 | 1023 & e), t + String.fromCharCode(e)
        };
    Nu.default = function(e) {
        return e >= 55296 && e <= 57343 || e > 1114111 ? "�" : (e in Du.default && (e = Du.default[e]), Au(e))
    };
    var Lu = wu && wu.__importDefault || function(e) {
        return e && e.__esModule ? e : {
            default: e
        }
    };
    Object.defineProperty(Mu, "__esModule", {
        value: !0
    }), Mu.decodeHTML = Mu.decodeHTMLStrict = Mu.decodeXML = void 0;
    var Iu = Lu(Su),
        Ru = Lu({
            Aacute: "Á",
            aacute: "á",
            Acirc: "Â",
            acirc: "â",
            acute: "´",
            AElig: "Æ",
            aelig: "æ",
            Agrave: "À",
            agrave: "à",
            amp: "&",
            AMP: "&",
            Aring: "Å",
            aring: "å",
            Atilde: "Ã",
            atilde: "ã",
            Auml: "Ä",
            auml: "ä",
            brvbar: "¦",
            Ccedil: "Ç",
            ccedil: "ç",
            cedil: "¸",
            cent: "¢",
            copy: "©",
            COPY: "©",
            curren: "¤",
            deg: "°",
            divide: "÷",
            Eacute: "É",
            eacute: "é",
            Ecirc: "Ê",
            ecirc: "ê",
            Egrave: "È",
            egrave: "è",
            ETH: "Ð",
            eth: "ð",
            Euml: "Ë",
            euml: "ë",
            frac12: "½",
            frac14: "¼",
            frac34: "¾",
            gt: ">",
            GT: ">",
            Iacute: "Í",
            iacute: "í",
            Icirc: "Î",
            icirc: "î",
            iexcl: "¡",
            Igrave: "Ì",
            igrave: "ì",
            iquest: "¿",
            Iuml: "Ï",
            iuml: "ï",
            laquo: "«",
            lt: "<",
            LT: "<",
            macr: "¯",
            micro: "µ",
            middot: "·",
            nbsp: " ",
            not: "¬",
            Ntilde: "Ñ",
            ntilde: "ñ",
            Oacute: "Ó",
            oacute: "ó",
            Ocirc: "Ô",
            ocirc: "ô",
            Ograve: "Ò",
            ograve: "ò",
            ordf: "ª",
            ordm: "º",
            Oslash: "Ø",
            oslash: "ø",
            Otilde: "Õ",
            otilde: "õ",
            Ouml: "Ö",
            ouml: "ö",
            para: "¶",
            plusmn: "±",
            pound: "£",
            quot: '"',
            QUOT: '"',
            raquo: "»",
            reg: "®",
            REG: "®",
            sect: "§",
            shy: "­",
            sup1: "¹",
            sup2: "²",
            sup3: "³",
            szlig: "ß",
            THORN: "Þ",
            thorn: "þ",
            times: "×",
            Uacute: "Ú",
            uacute: "ú",
            Ucirc: "Û",
            ucirc: "û",
            Ugrave: "Ù",
            ugrave: "ù",
            uml: "¨",
            Uuml: "Ü",
            uuml: "ü",
            Yacute: "Ý",
            yacute: "ý",
            yen: "¥",
            yuml: "ÿ"
        }),
        Pu = Lu(Eu),
        Bu = Lu(Nu),
        Fu = /&(?:[a-zA-Z0-9]+|#[xX][\da-fA-F]+|#\d+);/g;

    function Hu(e) {
        var t = qu(e);
        return function(e) {
            return String(e).replace(Fu, t)
        }
    }
    Mu.decodeXML = Hu(Pu.default), Mu.decodeHTMLStrict = Hu(Iu.default);
    var zu = function(e, t) {
        return e < t ? 1 : -1
    };

    function qu(e) {
        return function(t) {
            if ("#" === t.charAt(1)) {
                var n = t.charAt(2);
                return "X" === n || "x" === n ? Bu.default(parseInt(t.substr(3), 16)) : Bu.default(parseInt(t.substr(2), 10))
            }
            return e[t.slice(1, -1)] || t
        }
    }
    Mu.decodeHTML = function() {
        for (var e = Object.keys(Ru.default).sort(zu), t = Object.keys(Iu.default).sort(zu), n = 0, r = 0; n < t.length; n++) e[r] === t[n] ? (t[n] += ";?", r++) : t[n] += ";";
        var o = new RegExp("&(?:" + t.join("|") + "|#[xX][\\da-fA-F]+;?|#\\d+;?)", "g"),
            i = qu(Iu.default);

        function s(e) {
            return ";" !== e.substr(-1) && (e += ";"), i(e)
        }
        return function(e) {
            return String(e).replace(o, s)
        }
    }();
    var Vu = {},
        ju = wu && wu.__importDefault || function(e) {
            return e && e.__esModule ? e : {
                default: e
            }
        };
    Object.defineProperty(Vu, "__esModule", {
        value: !0
    }), Vu.escapeUTF8 = Vu.escape = Vu.encodeNonAsciiHTML = Vu.encodeHTML = Vu.encodeXML = void 0;
    var $u = Gu(ju(Eu).default),
        _u = Xu($u);
    Vu.encodeXML = td($u);
    var Uu, Wu, Ju = Gu(ju(Su).default),
        Ku = Xu(Ju);

    function Gu(e) {
        return Object.keys(e).sort().reduce(function(t, n) {
            return t[e[n]] = "&" + n + ";", t
        }, {})
    }

    function Xu(e) {
        for (var t = [], n = [], r = 0, o = Object.keys(e); r < o.length; r++) {
            var i = o[r];
            1 === i.length ? t.push("\\" + i) : n.push(i)
        }
        t.sort();
        for (var s = 0; s < t.length - 1; s++) {
            for (var a = s; a < t.length - 1 && t[a].charCodeAt(1) + 1 === t[a + 1].charCodeAt(1);) a += 1;
            var l = 1 + a - s;
            l < 3 || t.splice(s, l, t[s] + "-" + t[a])
        }
        return n.unshift("[" + t.join("") + "]"), new RegExp(n.join("|"), "g")
    }
    Vu.encodeHTML = (Uu = Ju, Wu = Ku, function(e) {
        return e.replace(Wu, function(e) {
            return Uu[e]
        }).replace(Zu, Yu)
    }), Vu.encodeNonAsciiHTML = td(Ju);
    var Zu = /(?:[\x80-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF])/g,
        Qu = null != String.prototype.codePointAt ? function(e) {
            return e.codePointAt(0)
        } : function(e) {
            return 1024 * (e.charCodeAt(0) - 55296) + e.charCodeAt(1) - 56320 + 65536
        };

    function Yu(e) {
        return "&#x" + (e.length > 1 ? Qu(e) : e.charCodeAt(0)).toString(16).toUpperCase() + ";"
    }
    var ed = new RegExp(_u.source + "|" + Zu.source, "g");

    function td(e) {
        return function(t) {
            return t.replace(ed, function(t) {
                return e[t] || Yu(t)
            })
        }
    }
    Vu.escape = function(e) {
            return e.replace(ed, Yu)
        }, Vu.escapeUTF8 = function(e) {
            return e.replace(_u, Yu)
        },
        function(e) {
            Object.defineProperty(e, "__esModule", {
                value: !0
            }), e.decodeXMLStrict = e.decodeHTML5Strict = e.decodeHTML4Strict = e.decodeHTML5 = e.decodeHTML4 = e.decodeHTMLStrict = e.decodeHTML = e.decodeXML = e.encodeHTML5 = e.encodeHTML4 = e.escapeUTF8 = e.escape = e.encodeNonAsciiHTML = e.encodeHTML = e.encodeXML = e.encode = e.decodeStrict = e.decode = void 0;
            var t = Mu,
                n = Vu;
            e.decode = function(e, n) {
                return (!n || n <= 0 ? t.decodeXML : t.decodeHTML)(e)
            }, e.decodeStrict = function(e, n) {
                return (!n || n <= 0 ? t.decodeXML : t.decodeHTMLStrict)(e)
            }, e.encode = function(e, t) {
                return (!t || t <= 0 ? n.encodeXML : n.encodeHTML)(e)
            };
            var r = Vu;
            Object.defineProperty(e, "encodeXML", {
                enumerable: !0,
                get: function() {
                    return r.encodeXML
                }
            }), Object.defineProperty(e, "encodeHTML", {
                enumerable: !0,
                get: function() {
                    return r.encodeHTML
                }
            }), Object.defineProperty(e, "encodeNonAsciiHTML", {
                enumerable: !0,
                get: function() {
                    return r.encodeNonAsciiHTML
                }
            }), Object.defineProperty(e, "escape", {
                enumerable: !0,
                get: function() {
                    return r.escape
                }
            }), Object.defineProperty(e, "escapeUTF8", {
                enumerable: !0,
                get: function() {
                    return r.escapeUTF8
                }
            }), Object.defineProperty(e, "encodeHTML4", {
                enumerable: !0,
                get: function() {
                    return r.encodeHTML
                }
            }), Object.defineProperty(e, "encodeHTML5", {
                enumerable: !0,
                get: function() {
                    return r.encodeHTML
                }
            });
            var o = Mu;
            Object.defineProperty(e, "decodeXML", {
                enumerable: !0,
                get: function() {
                    return o.decodeXML
                }
            }), Object.defineProperty(e, "decodeHTML", {
                enumerable: !0,
                get: function() {
                    return o.decodeHTML
                }
            }), Object.defineProperty(e, "decodeHTMLStrict", {
                enumerable: !0,
                get: function() {
                    return o.decodeHTMLStrict
                }
            }), Object.defineProperty(e, "decodeHTML4", {
                enumerable: !0,
                get: function() {
                    return o.decodeHTML
                }
            }), Object.defineProperty(e, "decodeHTML5", {
                enumerable: !0,
                get: function() {
                    return o.decodeHTML
                }
            }), Object.defineProperty(e, "decodeHTML4Strict", {
                enumerable: !0,
                get: function() {
                    return o.decodeHTMLStrict
                }
            }), Object.defineProperty(e, "decodeHTML5Strict", {
                enumerable: !0,
                get: function() {
                    return o.decodeHTMLStrict
                }
            }), Object.defineProperty(e, "decodeXMLStrict", {
                enumerable: !0,
                get: function() {
                    return o.decodeXML
                }
            })
        }(Tu);
    var nd = "&(?:#x[a-f0-9]{1,6}|#[0-9]{1,7}|[a-z][a-z0-9]{1,31});",
        rd = /[\\&]/,
        od = "[!\"#$%&'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]",
        id = new RegExp("\\\\" + od + "|" + nd, "gi"),
        sd = new RegExp('[&<>"]', "g"),
        ad = function(e) {
            return 92 === e.charCodeAt(0) ? e.charAt(1) : Tu.decodeHTML(e)
        };

    function ld(e) {
        return rd.test(e) ? e.replace(id, ad) : e
    }

    function cd(e) {
        try {
            return Cu(e)
        } catch (t) {
            return e
        }
    }

    function ud(e) {
        switch (e) {
            case "&":
                return "&amp;";
            case "<":
                return "&lt;";
            case ">":
                return "&gt;";
            case '"':
                return "&quot;";
            default:
                return e
        }
    }

    function dd(e) {
        return sd.test(e) ? e.replace(sd, ud) : e
    }

    function pd(e, t) {
        for (var n = [], r = 0; r < t; r++) n.push(e);
        return n.join("")
    }

    function hd(e) {
        return !e || !/[^ \t]+/.test(e)
    }
    var fd = function() {
        function e(e) {
            this.current = e, this.root = e, this.entering = !0
        }
        return e.prototype.next = function() {
            var e = this.current,
                t = this.entering;
            if (null === e) return null;
            var n = md(e);
            return t && n ? e.firstChild ? (this.current = e.firstChild, this.entering = !0) : this.entering = !1 : e === this.root ? this.current = null : null === e.next ? (this.current = e.parent, this.entering = !1) : (this.current = e.next, this.entering = !0), {
                entering: t,
                node: e
            }
        }, e.prototype.resumeAt = function(e, t) {
            this.current = e, this.entering = !0 === t
        }, e
    }();

    function md(e) {
        switch (e.type) {
            case "document":
            case "blockQuote":
            case "list":
            case "item":
            case "paragraph":
            case "heading":
            case "emph":
            case "strong":
            case "strike":
            case "link":
            case "image":
            case "table":
            case "tableHead":
            case "tableBody":
            case "tableRow":
            case "tableCell":
            case "tableDelimRow":
            case "customInline":
                return !0;
            default:
                return !1
        }
    }
    var gd = 1,
        vd = {};

    function yd(e) {
        delete vd[e]
    }
    var bd = function() {
            function e(e, t) {
                this.parent = null, this.prev = null, this.next = null, this.firstChild = null, this.lastChild = null, this.literal = null, this.id = "document" === e ? -1 : gd++, this.type = e, this.sourcepos = t, vd[this.id] = this
            }
            return e.prototype.isContainer = function() {
                return md(this)
            }, e.prototype.unlink = function() {
                this.prev ? this.prev.next = this.next : this.parent && (this.parent.firstChild = this.next), this.next ? this.next.prev = this.prev : this.parent && (this.parent.lastChild = this.prev), this.parent = null, this.next = null, this.prev = null
            }, e.prototype.replaceWith = function(e) {
                this.insertBefore(e), this.unlink()
            }, e.prototype.insertAfter = function(e) {
                e.unlink(), e.next = this.next, e.next && (e.next.prev = e), e.prev = this, this.next = e, this.parent && (e.parent = this.parent, e.next || (e.parent.lastChild = e))
            }, e.prototype.insertBefore = function(e) {
                e.unlink(), e.prev = this.prev, e.prev && (e.prev.next = e), e.next = this, this.prev = e, e.parent = this.parent, e.prev || (e.parent.firstChild = e)
            }, e.prototype.appendChild = function(e) {
                e.unlink(), e.parent = this, this.lastChild ? (this.lastChild.next = e, e.prev = this.lastChild, this.lastChild = e) : (this.firstChild = e, this.lastChild = e)
            }, e.prototype.prependChild = function(e) {
                e.unlink(), e.parent = this, this.firstChild ? (this.firstChild.prev = e, e.next = this.firstChild, this.firstChild = e) : (this.firstChild = e, this.lastChild = e)
            }, e.prototype.walker = function() {
                return new fd(this)
            }, e
        }(),
        wd = function(e) {
            function t(t, n) {
                var r = e.call(this, t, n) || this;
                return r.open = !0, r.lineOffsets = null, r.stringContent = null, r.lastLineBlank = !1, r.lastLineChecked = !1, r.type = t, r
            }
            return vu(t, e), t
        }(bd),
        kd = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.listData = null, t
            }
            return vu(t, e), t
        }(wd),
        xd = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.level = 0, t.headingType = "atx", t
            }
            return vu(t, e), t
        }(wd),
        Cd = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.isFenced = !1, t.fenceChar = null, t.fenceLength = 0, t.fenceOffset = -1, t.info = null, t.infoPadding = 0, t
            }
            return vu(t, e), t
        }(wd),
        Td = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.columns = [], t
            }
            return vu(t, e), t
        }(wd),
        Md = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.startIdx = 0, t.endIdx = 0, t.paddingLeft = 0, t.paddingRight = 0, t.ignored = !1, t
            }
            return vu(t, e), t
        }(wd),
        Sd = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.title = "", t.dest = "", t.label = "", t
            }
            return vu(t, e), t
        }(wd),
        Ed = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.syntaxLength = 0, t.offset = -1, t.info = "", t
            }
            return vu(t, e), t
        }(wd),
        Nd = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.htmlBlockType = -1, t
            }
            return vu(t, e), t
        }(wd),
        Od = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.destination = null, t.title = null, t.extendedAutolink = !1, t
            }
            return vu(t, e), t
        }(bd),
        Dd = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.tickCount = 0, t
            }
            return vu(t, e), t
        }(bd),
        Ad = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.info = "", t
            }
            return vu(t, e), t
        }(bd);

    function Ld(e, t) {
        switch (e) {
            case "heading":
                return new xd(e, t);
            case "list":
            case "item":
                return new kd(e, t);
            case "link":
            case "image":
                return new Od(e, t);
            case "codeBlock":
                return new Cd(e, t);
            case "htmlBlock":
                return new Nd(e, t);
            case "table":
                return new Td(e, t);
            case "tableCell":
                return new Md(e, t);
            case "document":
            case "paragraph":
            case "blockQuote":
            case "thematicBreak":
            case "tableRow":
            case "tableBody":
            case "tableHead":
            case "frontMatter":
                return new wd(e, t);
            case "code":
                return new Dd(e, t);
            case "refDef":
                return new Sd(e, t);
            case "customBlock":
                return new Ed(e, t);
            case "customInline":
                return new Ad(e, t);
            default:
                return new bd(e, t)
        }
    }

    function Id(e) {
        return "codeBlock" === e.type
    }

    function Rd(e) {
        return "list" === e.type
    }

    function Pd(e) {
        return "refDef" === e.type
    }

    function Bd(e) {
        return "customBlock" === e.type
    }

    function Fd(e, t) {
        var n = Ld("text", t);
        return n.literal = e, n
    }
    var Hd, zd = "[A-Za-z][A-Za-z0-9-]*",
        qd = "<" + zd + "(?:\\s+[a-zA-Z_:][a-zA-Z0-9:._-]*(?:\\s*=\\s*(?:[^\"'=<>`\\x00-\\x20]+|'[^']*'|\"[^\"]*\"))?)*\\s*/?>",
        Vd = "</" + zd + "\\s*[>]",
        jd = new RegExp("^(?:" + qd + "|" + Vd + "|\x3c!----\x3e|\x3c!--(?:-?[^>-])(?:-?[^-])*--\x3e|[<][?].*?[?][>]|<![A-Z]+\\s+[^>]*>|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>)", "i");
    if (String.fromCodePoint) Hd = function(e) {
        try {
            return String.fromCodePoint(e)
        } catch (e) {
            if (e instanceof RangeError) return String.fromCharCode(65533);
            throw e
        }
    };
    else {
        var $d = String.fromCharCode,
            _d = Math.floor;
        Hd = function() {
            for (var e = [], t = 0; t < arguments.length; t++) e[t] = arguments[t];
            var n, r, o = [],
                i = -1,
                s = e.length;
            if (!s) return "";
            for (var a = ""; ++i < s;) {
                var l = Number(e[i]);
                if (!isFinite(l) || l < 0 || l > 1114111 || _d(l) !== l) return String.fromCharCode(65533);
                l <= 65535 ? o.push(l) : (n = 55296 + ((l -= 65536) >> 10), r = l % 1024 + 56320, o.push(n, r)), (i + 1 === s || o.length > 16384) && (a += $d.apply(void 0, o), o.length = 0)
            }
            return a
        }
    }
    var Ud = Hd;

    function Wd(e) {
        var t = /\)+$/.exec(e);
        if (t) {
            for (var n = 0, r = 0, o = e; r < o.length; r++) {
                var i = o[r];
                "(" === i ? n < 0 ? n = 1 : n += 1 : ")" === i && (n -= 1)
            }
            if (n < 0) {
                var s = Math.min(-n, t[0].length);
                return e.substring(0, e.length - s)
            }
        }
        return e
    }

    function Jd(e) {
        return e.replace(/&[A-Za-z0-9]+;$/, "")
    }

    function Kd(e) {
        return bu(bu([], function(e) {
            for (var t, n = new RegExp("(www|https?://).(?:[w-]+.)*[A-Za-z0-9-]+.[A-Za-z0-9-]+[^<\\s]*[^<?!.,:*_?~\\s]", "g"), r = []; t = n.exec(e);) {
                var o = Jd(Wd(t[0])),
                    i = "www" === t[1] ? "http://" : "";
                r.push({
                    text: o,
                    range: [t.index, t.index + o.length - 1],
                    url: "" + i + o
                })
            }
            return r
        }(e)), function(e) {
            for (var t, n = new RegExp("[\\w.+-]+@(?:[\\w-]+\\.)+[\\w-]+", "g"), r = []; t = n.exec(e);) {
                var o = t[0];
                /[_-]+$/.test(o) || r.push({
                    text: o,
                    range: [t.index, t.index + o.length - 1],
                    url: "mailto:" + o
                })
            }
            return r
        }(e)).sort(function(e, t) {
            return e.range[0] - t.range[0]
        })
    }

    function Gd(e) {
        return e[e.length - 1]
    }

    function Xd(e) {
        return e.slice(1, e.length - 1).trim().replace(/[ \t\r\n]+/, " ").toLowerCase().toUpperCase()
    }

    function Zd(e, t) {
        Object.keys(e).forEach(function(n) {
            t(n, e[n])
        })
    }

    function Qd(e) {
        return !Object.keys(e).length
    }
    var Yd = 39,
        ep = 34,
        tp = 36,
        np = "\\\\" + od,
        rp = new RegExp(/[!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u0AF0\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E42\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC9\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDF3C-\uDF3E]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]/),
        op = new RegExp('^(?:"(' + np + '|[^"\\x00])*"|\'(' + np + "|[^'\\x00])*'|\\((" + np + "|[^()\\x00])*\\))"),
        ip = /^(?:<(?:[^<>\n\\\x00]|\\.)*>)/,
        sp = new RegExp("^" + od),
        ap = new RegExp("^" + nd, "i"),
        lp = /`+/,
        cp = /^`+/,
        up = /\.\.\./g,
        dp = /--+/g,
        pp = /^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/,
        hp = /^<[A-Za-z][A-Za-z0-9.+-]{1,31}:[^<>\x00-\x20]*>/i,
        fp = /^ *(?:\n *)?/,
        mp = /^[ \t\n\x0b\x0c\x0d]/,
        gp = /^\s/,
        vp = / *$/,
        yp = /^ */,
        bp = /^ *(?:\n|$)/,
        wp = /^\[(?:[^\\\[\]]|\\.){0,1000}\]/,
        kp = /^[^\n`\[\]\\!<&*_'"~$]+/m,
        xp = function() {
            function e(e) {
                this.subject = "", this.delimiters = null, this.brackets = null, this.pos = 0, this.lineStartNum = 0, this.lineIdx = 0, this.lineOffsets = [0], this.linePosOffset = 0, this.refMap = {}, this.refLinkCandidateMap = {}, this.refDefCandidateMap = {}, this.options = e
            }
            return e.prototype.sourcepos = function(e, t) {
                var n = this.linePosOffset + this.lineOffsets[this.lineIdx],
                    r = this.lineStartNum + this.lineIdx,
                    o = [r, e + n];
                return "number" == typeof t ? [o, [r, t + n]] : o
            }, e.prototype.nextLine = function() {
                this.lineIdx += 1, this.linePosOffset = -this.pos
            }, e.prototype.match = function(e) {
                var t = e.exec(this.subject.slice(this.pos));
                return null === t ? null : (this.pos += t.index + t[0].length, t[0])
            }, e.prototype.peek = function() {
                return this.pos < this.subject.length ? this.subject.charCodeAt(this.pos) : -1
            }, e.prototype.spnl = function() {
                return this.match(fp), !0
            }, e.prototype.parseBackticks = function(e) {
                var t = this.pos + 1,
                    n = this.match(cp);
                if (null === n) return !1;
                for (var r, o = this.pos; null !== (r = this.match(lp));)
                    if (r === n) {
                        var i = this.subject.slice(o, this.pos - n.length),
                            s = this.sourcepos(t, this.pos),
                            a = i.split("\n");
                        if (a.length > 1) {
                            var l = Gd(a);
                            this.lineIdx += a.length - 1, this.linePosOffset = -(this.pos - l.length - n.length), s[1] = this.sourcepos(this.pos), i = a.join(" ")
                        }
                        var c = Ld("code", s);
                        return i.length > 0 && null !== i.match(/[^ ]/) && " " == i[0] && " " == i[i.length - 1] ? c.literal = i.slice(1, i.length - 1) : c.literal = i, c.tickCount = n.length, e.appendChild(c), !0
                    } return this.pos = o, e.appendChild(Fd(n, this.sourcepos(t, this.pos - 1))), !0
            }, e.prototype.parseBackslash = function(e) {
                var t, n = this.subject;
                this.pos += 1;
                var r = this.pos;
                return 10 === this.peek() ? (this.pos += 1, t = Ld("linebreak", this.sourcepos(this.pos - 1, this.pos)), e.appendChild(t), this.nextLine()) : sp.test(n.charAt(this.pos)) ? (e.appendChild(Fd(n.charAt(this.pos), this.sourcepos(r, this.pos))), this.pos += 1) : e.appendChild(Fd("\\", this.sourcepos(r, r))), !0
            }, e.prototype.parseAutolink = function(e) {
                var t, n, r, o = this.pos + 1;
                return (t = this.match(pp)) ? (n = t.slice(1, t.length - 1), (r = Ld("link", this.sourcepos(o, this.pos))).destination = cd("mailto:" + n), r.title = "", r.appendChild(Fd(n, this.sourcepos(o + 1, this.pos - 1))), e.appendChild(r), !0) : !!(t = this.match(hp)) && (n = t.slice(1, t.length - 1), (r = Ld("link", this.sourcepos(o, this.pos))).destination = cd(n), r.title = "", r.appendChild(Fd(n, this.sourcepos(o + 1, this.pos - 1))), e.appendChild(r), !0)
            }, e.prototype.parseHtmlTag = function(e) {
                var t = this.pos + 1,
                    n = this.match(jd);
                if (null === n) return !1;
                var r = Ld("htmlInline", this.sourcepos(t, this.pos));
                return r.literal = n, e.appendChild(r), !0
            }, e.prototype.scanDelims = function(e) {
                var t = 0,
                    n = this.pos;
                if (e === Yd || e === ep) t++, this.pos++;
                else
                    for (; this.peek() === e;) t++, this.pos++;
                if (0 === t || t < 2 && (126 === e || e === tp)) return this.pos = n, null;
                var r, o = 0 === n ? "\n" : this.subject.charAt(n - 1),
                    i = this.peek();
                r = -1 === i ? "\n" : Ud(i);
                var s, a, l = gp.test(r),
                    c = rp.test(r),
                    u = gp.test(o),
                    d = rp.test(o),
                    p = !l && (!c || u || d),
                    h = !u && (!d || l || c);
                return 95 === e ? (s = p && (!h || d), a = h && (!p || c)) : e === Yd || e === ep ? (s = p && !h, a = h) : e === tp ? (s = !l, a = !u) : (s = p, a = h), this.pos = n, {
                    numdelims: t,
                    canOpen: s,
                    canClose: a
                }
            }, e.prototype.handleDelim = function(e, t) {
                var n = this.scanDelims(e);
                if (!n) return !1;
                var r = n.numdelims,
                    o = this.pos + 1;
                this.pos += r;
                var i = Fd(e === Yd ? "’" : e === ep ? "“" : this.subject.slice(o - 1, this.pos), this.sourcepos(o, this.pos));
                return t.appendChild(i), (n.canOpen || n.canClose) && (this.options.smart || e !== Yd && e !== ep) && (this.delimiters = {
                    cc: e,
                    numdelims: r,
                    origdelims: r,
                    node: i,
                    previous: this.delimiters,
                    next: null,
                    canOpen: n.canOpen,
                    canClose: n.canClose
                }, this.delimiters.previous && (this.delimiters.previous.next = this.delimiters)), !0
            }, e.prototype.removeDelimiter = function(e) {
                null !== e.previous && (e.previous.next = e.next), null === e.next ? this.delimiters = e.previous : e.next.previous = e.previous
            }, e.prototype.removeDelimitersBetween = function(e, t) {
                e.next !== t && (e.next = t, t.previous = e)
            }, e.prototype.processEmphasis = function(e) {
                var t, n, r, o, i, s, a, l = !1,
                    c = ((t = {})[95] = [e, e, e], t[42] = [e, e, e], t[39] = [e], t[34] = [e], t[126] = [e], t[36] = [e], t);
                for (r = this.delimiters; null !== r && r.previous !== e;) r = r.previous;
                for (; null !== r;) {
                    var u = r.cc,
                        d = 95 === u || 42 === u;
                    if (r.canClose) {
                        for (n = r.previous, a = !1; null !== n && n !== e && n !== c[u][d ? r.origdelims % 3 : 0];) {
                            if (l = d && (r.canOpen || n.canClose) && r.origdelims % 3 != 0 && (n.origdelims + r.origdelims) % 3 == 0, n.cc === r.cc && n.canOpen && !l) {
                                a = !0;
                                break
                            }
                            n = n.previous
                        }
                        if (o = r, d || 126 === u || u === tp)
                            if (a) {
                                if (n) {
                                    var p = r.numdelims >= 2 && n.numdelims >= 2 ? 2 : 1,
                                        h = d ? 0 : 1;
                                    i = n.node, s = r.node;
                                    var f = d ? 1 === p ? "emph" : "strong" : "strike";
                                    u === tp && (f = "customInline");
                                    var m = Ld(f),
                                        g = i.sourcepos[1],
                                        v = s.sourcepos[0];
                                    m.sourcepos = [
                                        [g[0], g[1] - p + 1],
                                        [v[0], v[1] + p - 1]
                                    ], i.sourcepos[1][1] -= p, s.sourcepos[0][1] += p, i.literal = i.literal.slice(p), s.literal = s.literal.slice(p), n.numdelims -= p, r.numdelims -= p;
                                    for (var y = i.next, b = void 0; y && y !== s;) b = y.next, y.unlink(), m.appendChild(y), y = b;
                                    if (u === tp) {
                                        var w = m.firstChild,
                                            k = w.literal || "",
                                            x = k.split(/\s/)[0];
                                        m.info = x, k.length <= x.length ? w.unlink() : (w.sourcepos[0][1] += x.length, w.literal = k.replace(x + " ", ""))
                                    }
                                    if (i.insertAfter(m), this.removeDelimitersBetween(n, r), n.numdelims <= h && (0 === n.numdelims && i.unlink(), this.removeDelimiter(n)), r.numdelims <= h) {
                                        0 === r.numdelims && s.unlink();
                                        var C = r.next;
                                        this.removeDelimiter(r), r = C
                                    }
                                }
                            } else r = r.next;
                        else u === Yd ? (r.node.literal = "’", a && (n.node.literal = "‘"), r = r.next) : u === ep && (r.node.literal = "”", a && (n.node.literal = "“"), r = r.next);
                        a || (c[u][d ? o.origdelims % 3 : 0] = o.previous, o.canOpen || this.removeDelimiter(o))
                    } else r = r.next
                }
                for (; null !== this.delimiters && this.delimiters !== e;) this.removeDelimiter(this.delimiters)
            }, e.prototype.parseLinkTitle = function() {
                var e = this.match(op);
                return null === e ? null : ld(e.substr(1, e.length - 2))
            }, e.prototype.parseLinkDestination = function() {
                var e = this.match(ip);
                if (null === e) {
                    if (60 === this.peek()) return null;
                    for (var t = this.pos, n = 0, r = void 0; - 1 !== (r = this.peek());)
                        if (92 === r && sp.test(this.subject.charAt(this.pos + 1))) this.pos += 1, -1 !== this.peek() && (this.pos += 1);
                        else if (40 === r) this.pos += 1, n += 1;
                    else if (41 === r) {
                        if (n < 1) break;
                        this.pos += 1, n -= 1
                    } else {
                        if (null !== mp.exec(Ud(r))) break;
                        this.pos += 1
                    }
                    return this.pos === t && 41 !== r || 0 !== n ? null : cd(ld(e = this.subject.substr(t, this.pos - t)))
                }
                return cd(ld(e.substr(1, e.length - 2)))
            }, e.prototype.parseLinkLabel = function() {
                var e = this.match(wp);
                return null === e || e.length > 1001 ? 0 : e.length
            }, e.prototype.parseOpenBracket = function(e) {
                var t = this.pos;
                this.pos += 1;
                var n = Fd("[", this.sourcepos(this.pos, this.pos));
                return e.appendChild(n), this.addBracket(n, t, !1), !0
            }, e.prototype.parseBang = function(e) {
                var t = this.pos;
                if (this.pos += 1, 91 === this.peek()) {
                    this.pos += 1;
                    var n = Fd("![", this.sourcepos(this.pos - 1, this.pos));
                    e.appendChild(n), this.addBracket(n, t + 1, !0)
                } else n = Fd("!", this.sourcepos(this.pos, this.pos)), e.appendChild(n);
                return !0
            }, e.prototype.parseCloseBracket = function(e) {
                var t = null,
                    n = null,
                    r = !1;
                this.pos += 1;
                var o = this.pos,
                    i = this.brackets;
                if (null === i) return e.appendChild(Fd("]", this.sourcepos(o, o))), !0;
                if (!i.active) return e.appendChild(Fd("]", this.sourcepos(o, o))), this.removeBracket(), !0;
                var s = i.image,
                    a = this.pos;
                40 === this.peek() && (this.pos++, this.spnl() && null !== (t = this.parseLinkDestination()) && this.spnl() && (mp.test(this.subject.charAt(this.pos - 1)) && (n = this.parseLinkTitle()), 1) && this.spnl() && 41 === this.peek() ? (this.pos += 1, r = !0) : this.pos = a);
                var l = "";
                if (!r) {
                    var c = this.pos,
                        u = this.parseLinkLabel();
                    if (u > 2 ? l = this.subject.slice(c, c + u) : i.bracketAfter || (l = this.subject.slice(i.index, o)), 0 === u && (this.pos = a), l) {
                        l = Xd(l);
                        var d = this.refMap[l];
                        d && (t = d.destination, n = d.title, r = !0)
                    }
                }
                if (r) {
                    var p = Ld(s ? "image" : "link");
                    p.destination = t, p.title = n || "", p.sourcepos = [i.startpos, this.sourcepos(this.pos)];
                    for (var h = i.node.next, f = void 0; h;) f = h.next, h.unlink(), p.appendChild(h), h = f;
                    if (e.appendChild(p), this.processEmphasis(i.previousDelimiter), this.removeBracket(), i.node.unlink(), !s)
                        for (i = this.brackets; null !== i;) i.image || (i.active = !1), i = i.previous;
                    return this.options.referenceDefinition && (this.refLinkCandidateMap[e.id] = {
                        node: e,
                        refLabel: l
                    }), !0
                }
                return this.removeBracket(), this.pos = o, e.appendChild(Fd("]", this.sourcepos(o, o))), this.options.referenceDefinition && (this.refLinkCandidateMap[e.id] = {
                    node: e,
                    refLabel: l
                }), !0
            }, e.prototype.addBracket = function(e, t, n) {
                null !== this.brackets && (this.brackets.bracketAfter = !0), this.brackets = {
                    node: e,
                    startpos: this.sourcepos(t + (n ? 0 : 1)),
                    previous: this.brackets,
                    previousDelimiter: this.delimiters,
                    index: t,
                    image: n,
                    active: !0
                }
            }, e.prototype.removeBracket = function() {
                this.brackets && (this.brackets = this.brackets.previous)
            }, e.prototype.parseEntity = function(e) {
                var t, n = this.pos + 1;
                return !!(t = this.match(ap)) && (e.appendChild(Fd(Tu.decodeHTML(t), this.sourcepos(n, this.pos))), !0)
            }, e.prototype.parseString = function(e) {
                var t, n = this.pos + 1;
                if (t = this.match(kp)) {
                    if (this.options.smart) {
                        var r = t.replace(up, "…").replace(dp, function(e) {
                            var t = 0,
                                n = 0;
                            return e.length % 3 == 0 ? n = e.length / 3 : e.length % 2 == 0 ? t = e.length / 2 : e.length % 3 == 2 ? (t = 1, n = (e.length - 2) / 3) : (t = 2, n = (e.length - 4) / 3), pd("—", n) + pd("–", t)
                        });
                        e.appendChild(Fd(r, this.sourcepos(n, this.pos)))
                    } else {
                        var o = Fd(t, this.sourcepos(n, this.pos));
                        e.appendChild(o)
                    }
                    return !0
                }
                return !1
            }, e.prototype.parseNewline = function(e) {
                this.pos += 1;
                var t = e.lastChild;
                if (t && "text" === t.type && " " === t.literal[t.literal.length - 1]) {
                    var n = " " === t.literal[t.literal.length - 2],
                        r = t.literal.length;
                    t.literal = t.literal.replace(vp, "");
                    var o = r - t.literal.length;
                    t.sourcepos[1][1] -= o, e.appendChild(Ld(n ? "linebreak" : "softbreak", this.sourcepos(this.pos - o, this.pos)))
                } else e.appendChild(Ld("softbreak", this.sourcepos(this.pos, this.pos)));
                return this.nextLine(), this.match(yp), !0
            }, e.prototype.parseReference = function(e, t) {
                if (!this.options.referenceDefinition) return 0;
                this.subject = e.stringContent, this.pos = 0;
                var n = null,
                    r = this.pos,
                    o = this.parseLinkLabel();
                if (0 === o) return 0;
                var i = this.subject.substr(0, o);
                if (58 !== this.peek()) return this.pos = r, 0;
                this.pos++, this.spnl();
                var s = this.parseLinkDestination();
                if (null === s) return this.pos = r, 0;
                var a = this.pos;
                this.spnl(), this.pos !== a && (n = this.parseLinkTitle()), null === n && (n = "", this.pos = a);
                var l = !0;
                if (null === this.match(bp) && ("" === n ? l = !1 : (n = "", this.pos = a, l = null !== this.match(bp))), !l) return this.pos = r, 0;
                var c = Xd(i);
                if ("" === c) return this.pos = r, 0;
                var u = this.getReferenceDefSourcepos(e);
                e.sourcepos[0][0] = u[1][0] + 1;
                var d = Ld("refDef", u);
                return d.title = n, d.dest = s, d.label = c, e.insertBefore(d), t[c] ? this.refDefCandidateMap[d.id] = d : t[c] = hh(d), this.pos - r
            }, e.prototype.mergeTextNodes = function(e) {
                for (var t, n = []; t = e.next();) {
                    var r = t.entering,
                        o = t.node;
                    if (r && "text" === o.type) n.push(o);
                    else if (1 === n.length) n = [];
                    else if (n.length > 1) {
                        var i = n[0],
                            s = n[n.length - 1];
                        i.sourcepos && s.sourcepos && (i.sourcepos[1] = s.sourcepos[1]), i.next = s.next, i.next && (i.next.prev = i);
                        for (var a = 1; a < n.length; a += 1) i.literal += n[a].literal, n[a].unlink();
                        n = []
                    }
                }
            }, e.prototype.getReferenceDefSourcepos = function(e) {
                for (var t = e.stringContent.split(/\n|\r\n/), n = !1, r = 0, o = {
                        line: 0,
                        ch: 0
                    }, i = 0; i < t.length; i += 1) {
                    var s = t[i];
                    if (mp.test(s)) break;
                    if (/\:/.test(s) && 0 === r) {
                        if (n) break;
                        var a = s.indexOf(":") === s.length - 1 ? i + 1 : i;
                        o = {
                            line: a,
                            ch: t[a].length
                        }, n = !0
                    }
                    var l = s.match(/'|"/g);
                    if (l && (r += l.length), 2 === r) {
                        o = {
                            line: i,
                            ch: s.length
                        };
                        break
                    }
                }
                return [
                    [e.sourcepos[0][0], e.sourcepos[0][1]],
                    [e.sourcepos[0][0] + o.line, o.ch]
                ]
            }, e.prototype.parseInline = function(e) {
                var t, n = !1,
                    r = this.peek();
                if (-1 === r) return !1;
                switch (r) {
                    case 10:
                        n = this.parseNewline(e);
                        break;
                    case 92:
                        n = this.parseBackslash(e);
                        break;
                    case 96:
                        n = this.parseBackticks(e);
                        break;
                    case 42:
                    case 95:
                    case 126:
                    case tp:
                        n = this.handleDelim(r, e);
                        break;
                    case Yd:
                    case ep:
                        n = !!(null === (t = this.options) || void 0 === t ? void 0 : t.smart) && this.handleDelim(r, e);
                        break;
                    case 91:
                        n = this.parseOpenBracket(e);
                        break;
                    case 33:
                        n = this.parseBang(e);
                        break;
                    case 93:
                        n = this.parseCloseBracket(e);
                        break;
                    case 60:
                        n = this.parseAutolink(e) || this.parseHtmlTag(e);
                        break;
                    case 38:
                        e.disabledEntityParse || (n = this.parseEntity(e));
                        break;
                    default:
                        n = this.parseString(e)
                }
                return n || (this.pos += 1, e.appendChild(Fd(Ud(r), this.sourcepos(this.pos, this.pos + 1)))), !0
            }, e.prototype.parse = function(e) {
                for (this.subject = e.stringContent.trim(), this.pos = 0, this.delimiters = null, this.brackets = null, this.lineOffsets = e.lineOffsets || [0], this.lineIdx = 0, this.linePosOffset = 0, this.lineStartNum = e.sourcepos[0][0], function(e) {
                        return "heading" === e.type
                    }(e) && (this.lineOffsets[0] += e.level + 1); this.parseInline(e););
                e.stringContent = null, this.processEmphasis(null), this.mergeTextNodes(e.walker());
                var t = this.options,
                    n = t.extendedAutolinks,
                    r = t.customParser;
                if (n && function(e, t) {
                        var n;
                        "boolean" == typeof t && (t = Kd);
                        for (var r = function() {
                                var e = n.entering,
                                    r = n.node;
                                if (e && "text" === r.type && "link" !== r.parent.type) {
                                    var o = r.literal,
                                        i = t(o);
                                    if (!i || !i.length) return "continue";
                                    for (var s = 0, a = r.sourcepos[0], l = a[0], c = a[1], u = function(e, t) {
                                            return [
                                                [l, c + e],
                                                [l, c + t]
                                            ]
                                        }, d = [], p = 0, h = i; p < h.length; p++) {
                                        var f = h[p],
                                            m = f.range,
                                            g = f.url,
                                            v = f.text;
                                        m[0] > s && d.push(Fd(o.substring(s, m[0]), u(s, m[0] - 1)));
                                        var y = Ld("link", u.apply(void 0, m));
                                        y.appendChild(Fd(v, u.apply(void 0, m))), y.destination = g, y.extendedAutolink = !0, d.push(y), s = m[1] + 1
                                    }
                                    s < o.length && d.push(Fd(o.substring(s), u(s, o.length - 1)));
                                    for (var b = 0, w = d; b < w.length; b++) {
                                        var k = w[b];
                                        r.insertBefore(k)
                                    }
                                    r.unlink()
                                }
                            }; n = e.next();) r()
                    }(e.walker(), n), r && e.firstChild)
                    for (var o, i = e.firstChild.walker(); o = i.next();) {
                        var s = o.node,
                            a = o.entering;
                        r[s.type] && r[s.type](s, {
                            entering: a,
                            options: this.options
                        })
                    }
            }, e
        }(),
        Cp = /^\[([ \txX])\][ \t]+/,
        Tp = /[^ \t\f\v\r\n]/,
        Mp = /^(?:`{3,}|~{3,})(?= *$)/;

    function Sp(e) {
        for (var t = e; t;) {
            if (t.lastLineBlank) return !0;
            var n = t.type;
            if (t.lastLineChecked || "list" !== n && "item" !== n) {
                t.lastLineChecked = !0;
                break
            }
            t.lastLineChecked = !0, t = t.lastChild
        }
        return !1
    }

    function Ep(e, t) {
        return t < e.length ? e.charCodeAt(t) : -1
    }

    function Np(e) {
        return !Tp.test(e)
    }

    function Op(e) {
        return 32 === e || 9 === e
    }
    var Dp = /^\$\$$/,
        Ap = {
            continue: function(e, t) {
                var n = e.currentLine,
                    r = n.match(Dp);
                if (r) return e.lastLineLength = r[0].length, e.finalize(t, e.lineNumber), 2;
                for (var o = t.offset; o > 0 && Op(Ep(n, e.offset));) e.advanceOffset(1, !0), o--;
                return 0
            },
            finalize: function(e, t) {
                if (null !== t.stringContent) {
                    var n = t.stringContent,
                        r = n.indexOf("\n"),
                        o = n.slice(0, r),
                        i = n.slice(r + 1),
                        s = o.match(/^(\s*)(.*)/);
                    t.info = ld(s[2].trim()), t.literal = i, t.stringContent = null
                }
            },
            canContain: function() {
                return !1
            },
            acceptsLines: !0
        },
        Lp = {
            continue: function() {
                return 1
            },
            finalize: function() {},
            canContain: function() {
                return !1
            },
            acceptsLines: !0
        },
        Ip = {
            continue: function() {
                return 0
            },
            finalize: function(e, t) {
                for (var n = t.firstChild; n;) {
                    if (Sp(n) && n.next) {
                        t.listData.tight = !1;
                        break
                    }
                    for (var r = n.firstChild; r;) {
                        if (Sp(r) && (n.next || r.next)) {
                            t.listData.tight = !1;
                            break
                        }
                        r = r.next
                    }
                    n = n.next
                }
            },
            canContain: function(e) {
                return "item" === e
            },
            acceptsLines: !1
        },
        Rp = {
            continue: function(e, t) {
                var n = e.currentLine,
                    r = e.indent;
                if (t.isFenced) {
                    var o = r <= 3 && n.charAt(e.nextNonspace) === t.fenceChar && n.slice(e.nextNonspace).match(Mp);
                    if (o && o[0].length >= t.fenceLength) return e.lastLineLength = e.offset + r + o[0].length, e.finalize(t, e.lineNumber), 2;
                    for (var i = t.fenceOffset; i > 0 && Op(Ep(n, e.offset));) e.advanceOffset(1, !0), i--
                } else if (r >= 4) e.advanceOffset(4, !0);
                else {
                    if (!e.blank) return 1;
                    e.advanceNextNonspace()
                }
                return 0
            },
            finalize: function(e, t) {
                var n;
                if (null !== t.stringContent) {
                    if (t.isFenced) {
                        var r = t.stringContent,
                            o = r.indexOf("\n"),
                            i = r.slice(0, o),
                            s = r.slice(o + 1),
                            a = i.match(/^(\s*)(.*)/);
                        t.infoPadding = a[1].length, t.info = ld(a[2].trim()), t.literal = s
                    } else t.literal = null === (n = t.stringContent) || void 0 === n ? void 0 : n.replace(/(\n *)+$/, "\n");
                    t.stringContent = null
                }
            },
            canContain: function() {
                return !1
            },
            acceptsLines: !0
        },
        Pp = {
            document: {
                continue: function() {
                    return 0
                },
                finalize: function() {},
                canContain: function(e) {
                    return "item" !== e
                },
                acceptsLines: !1
            },
            list: Ip,
            blockQuote: {
                continue: function(e) {
                    var t = e.currentLine;
                    return e.indented || 62 !== Ep(t, e.nextNonspace) ? 1 : (e.advanceNextNonspace(), e.advanceOffset(1, !1), Op(Ep(t, e.offset)) && e.advanceOffset(1, !0), 0)
                },
                finalize: function() {},
                canContain: function(e) {
                    return "item" !== e
                },
                acceptsLines: !1
            },
            item: {
                continue: function(e, t) {
                    if (e.blank) {
                        if (null === t.firstChild) return 1;
                        e.advanceNextNonspace()
                    } else {
                        if (!(e.indent >= t.listData.markerOffset + t.listData.padding)) return 1;
                        e.advanceOffset(t.listData.markerOffset + t.listData.padding, !0)
                    }
                    return 0
                },
                finalize: function(e, t) {
                    if (t.firstChild && "paragraph" === t.firstChild.type) {
                        var n = t.firstChild,
                            r = n.stringContent.match(Cp);
                        if (r) {
                            var o = r[0].length;
                            n.stringContent = n.stringContent.substring(o - 1), n.sourcepos[0][1] += o, n.lineOffsets[0] += o, t.listData.task = !0, t.listData.checked = /[xX]/.test(r[1])
                        }
                    }
                },
                canContain: function(e) {
                    return "item" !== e
                },
                acceptsLines: !1
            },
            heading: {
                continue: function() {
                    return 1
                },
                finalize: function() {},
                canContain: function() {
                    return !1
                },
                acceptsLines: !1
            },
            thematicBreak: {
                continue: function() {
                    return 1
                },
                finalize: function() {},
                canContain: function() {
                    return !1
                },
                acceptsLines: !1
            },
            codeBlock: Rp,
            htmlBlock: {
                continue: function(e, t) {
                    return !e.blank || 6 !== t.htmlBlockType && 7 !== t.htmlBlockType ? 0 : 1
                },
                finalize: function(e, t) {
                    var n;
                    t.literal = (null === (n = t.stringContent) || void 0 === n ? void 0 : n.replace(/(\n *)+$/, "")) || null, t.stringContent = null
                },
                canContain: function() {
                    return !1
                },
                acceptsLines: !0
            },
            paragraph: {
                continue: function(e) {
                    return e.blank ? 1 : 0
                },
                finalize: function(e, t) {
                    if (null !== t.stringContent) {
                        for (var n, r = !1; 91 === Ep(t.stringContent, 0) && (n = e.inlineParser.parseReference(t, e.refMap));) t.stringContent = t.stringContent.slice(n), r = !0;
                        r && Np(t.stringContent) && t.unlink()
                    }
                },
                canContain: function() {
                    return !1
                },
                acceptsLines: !0
            },
            table: {
                continue: function() {
                    return 0
                },
                finalize: function() {},
                canContain: function(e) {
                    return "tableHead" === e || "tableBody" === e
                },
                acceptsLines: !1
            },
            tableBody: {
                continue: function() {
                    return 0
                },
                finalize: function() {},
                canContain: function(e) {
                    return "tableRow" === e
                },
                acceptsLines: !1
            },
            tableHead: {
                continue: function() {
                    return 1
                },
                finalize: function() {},
                canContain: function(e) {
                    return "tableRow" === e || "tableDelimRow" === e
                },
                acceptsLines: !1
            },
            tableRow: {
                continue: function() {
                    return 1
                },
                finalize: function() {},
                canContain: function(e) {
                    return "tableCell" === e
                },
                acceptsLines: !1
            },
            tableCell: {
                continue: function() {
                    return 1
                },
                finalize: function() {},
                canContain: function() {
                    return !1
                },
                acceptsLines: !1
            },
            tableDelimRow: {
                continue: function() {
                    return 1
                },
                finalize: function() {},
                canContain: function(e) {
                    return "tableDelimCell" === e
                },
                acceptsLines: !1
            },
            tableDelimCell: {
                continue: function() {
                    return 1
                },
                finalize: function() {},
                canContain: function() {
                    return !1
                },
                acceptsLines: !1
            },
            refDef: Lp,
            customBlock: Ap,
            frontMatter: Lp
        };

    function Bp(e) {
        for (var t = 0, n = 0, r = [], o = 0; o < e.length; o += 1)
            if ("|" === e[o] && "\\" !== e[o - 1]) {
                var i = e.substring(t, o);
                0 === t && hd(i) ? n = o + 1 : r.push(i), t = o + 1
            } return t < e.length && (hd(i = e.substring(t, e.length)) || r.push(i)), [n, r]
    }

    function Fp(e, t, n, r) {
        for (var o = [], i = 0, s = t; i < s.length; i++) {
            var a = s[i],
                l = a.match(/^[ \t]+/),
                c = l ? l[0].length : 0,
                u = void 0,
                d = void 0;
            if (c === a.length) c = 0, u = 0, d = "";
            else {
                var p = a.match(/[ \t]+$/);
                u = p ? p[0].length : 0, d = a.slice(c, a.length - u)
            }
            var h = r + c,
                f = Ld(e, [
                    [n, r],
                    [n, r + a.length - 1]
                ]);
            f.stringContent = d.replace(/\\\|/g, "|"), f.startIdx = o.length, f.endIdx = o.length, f.lineOffsets = [h - 1], f.paddingLeft = c, f.paddingRight = u, o.push(f), r += a.length + 1
        }
        return o
    }

    function Hp(e) {
        var t = null,
            n = e.stringContent,
            r = n[0];
        return ":" === n[n.length - 1] ? t = ":" === r ? "center" : "right" : ":" === r && (t = "left"), {
            align: t
        }
    }
    var zp = /^(\$\$)(\s*[a-zA-Z])+/,
        qp = /^(\$\$)(\s*[a-zA-Z])+.*(\$\$)/,
        Vp = /^`{3,}(?!.*`)|^~{3,}/,
        jp = [/./, /^<(?:script|pre|style)(?:\s|>|$)/i, /^<!--/, /^<[?]/, /^<![A-Z]/, /^<!\[CDATA\[/, /^<[/]?(?:address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[123456]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul)(?:\s|[/]?[>]|$)/i, new RegExp("^(?:" + qd + "|" + Vd + ")\\s*$", "i")],
        $p = /^(?:=+|-+)[ \t]*$/,
        _p = /^#{1,6}(?:[ \t]+|$)/,
        Up = /^(?:(?:\*[ \t]*){3,}|(?:_[ \t]*){3,}|(?:-[ \t]*){3,})[ \t]*$/,
        Wp = /^[*+-]/,
        Jp = /^(\d{1,9})([.)])/;

    function Kp(e, t) {
        return e.options.disallowDeepHeading && ("blockQuote" === t.type || "item" === t.type)
    }
    var Gp = [function(e) {
            return e.indented || 62 !== Ep(e.currentLine, e.nextNonspace) ? 0 : (e.advanceNextNonspace(), e.advanceOffset(1, !1), Op(Ep(e.currentLine, e.offset)) && e.advanceOffset(1, !0), e.closeUnmatchedBlocks(), e.addChild("blockQuote", e.nextNonspace), 1)
        }, function(e, t) {
            var n;
            if (!e.indented && !Kp(e, t) && (n = e.currentLine.slice(e.nextNonspace).match(_p))) {
                e.advanceNextNonspace(), e.advanceOffset(n[0].length, !1), e.closeUnmatchedBlocks();
                var r = e.addChild("heading", e.nextNonspace);
                return r.level = n[0].trim().length, r.headingType = "atx", r.stringContent = e.currentLine.slice(e.offset).replace(/^[ \t]*#+[ \t]*$/, "").replace(/[ \t]+#+[ \t]*$/, ""), e.advanceOffset(e.currentLine.length - e.offset), 2
            }
            return 0
        }, function(e) {
            var t;
            if (!e.indented && (t = e.currentLine.slice(e.nextNonspace).match(Vp))) {
                var n = t[0].length;
                e.closeUnmatchedBlocks();
                var r = e.addChild("codeBlock", e.nextNonspace);
                return r.isFenced = !0, r.fenceLength = n, r.fenceChar = t[0][0], r.fenceOffset = e.indent, e.advanceNextNonspace(), e.advanceOffset(n, !1), 2
            }
            return 0
        }, function(e, t) {
            if (!e.indented && 60 === Ep(e.currentLine, e.nextNonspace)) {
                var n = e.currentLine.slice(e.nextNonspace),
                    r = e.options.disallowedHtmlBlockTags,
                    o = void 0;
                for (o = 1; o <= 7; o++) {
                    var i = n.match(jp[o]);
                    if (i) {
                        if (7 === o) {
                            if ("paragraph" === t.type) return 0;
                            if (r.length > 0 && new RegExp("</?(?:" + r.join("|") + ")", "i").test(i[0])) return 0
                        }
                        return e.closeUnmatchedBlocks(), e.addChild("htmlBlock", e.offset).htmlBlockType = o, 2
                    }
                }
            }
            return 0
        }, function(e, t) {
            var n;
            if (null !== t.stringContent && !e.indented && "paragraph" === t.type && !Kp(e, t.parent) && (n = e.currentLine.slice(e.nextNonspace).match($p))) {
                e.closeUnmatchedBlocks();
                for (var r = void 0; 91 === Ep(t.stringContent, 0) && (r = e.inlineParser.parseReference(t, e.refMap));) t.stringContent = t.stringContent.slice(r);
                if (t.stringContent.length > 0) {
                    var o = Ld("heading", t.sourcepos);
                    return o.level = "=" === n[0][0] ? 1 : 2, o.headingType = "setext", o.stringContent = t.stringContent, t.insertAfter(o), t.unlink(), e.tip = o, e.advanceOffset(e.currentLine.length - e.offset, !1), 2
                }
                return 0
            }
            return 0
        }, function(e) {
            return !e.indented && Up.test(e.currentLine.slice(e.nextNonspace)) ? (e.closeUnmatchedBlocks(), e.addChild("thematicBreak", e.nextNonspace), e.advanceOffset(e.currentLine.length - e.offset, !1), 2) : 0
        }, function(e, t) {
            var n, r, o, i = t;
            return e.indented && "list" !== t.type || !(n = function(e, t) {
                var n, r, o = e.currentLine.slice(e.nextNonspace),
                    i = {
                        type: "bullet",
                        tight: !0,
                        bulletChar: "",
                        start: 0,
                        delimiter: "",
                        padding: 0,
                        markerOffset: e.indent,
                        task: !1,
                        checked: !1
                    };
                if (e.indent >= 4) return null;
                if (n = o.match(Wp)) i.type = "bullet", i.bulletChar = n[0][0];
                else {
                    if (!(n = o.match(Jp)) || "paragraph" === t.type && "1" !== n[1]) return null;
                    i.type = "ordered", i.start = parseInt(n[1], 10), i.delimiter = n[2]
                }
                if (-1 !== (r = Ep(e.currentLine, e.nextNonspace + n[0].length)) && 9 !== r && 32 !== r) return null;
                if ("paragraph" === t.type && !e.currentLine.slice(e.nextNonspace + n[0].length).match(Tp)) return null;
                e.advanceNextNonspace(), e.advanceOffset(n[0].length, !0);
                var s = e.column,
                    a = e.offset;
                do {
                    e.advanceOffset(1, !0), r = Ep(e.currentLine, e.offset)
                } while (e.column - s < 5 && Op(r));
                var l = -1 === Ep(e.currentLine, e.offset),
                    c = e.column - s;
                return c >= 5 || c < 1 || l ? (i.padding = n[0].length + 1, e.column = s, e.offset = a, Op(Ep(e.currentLine, e.offset)) && e.advanceOffset(1, !0)) : i.padding = n[0].length + c, i
            }(e, i)) ? 0 : (e.closeUnmatchedBlocks(), "list" === e.tip.type && (o = n, (r = i.listData).type === o.type && r.delimiter === o.delimiter && r.bulletChar === o.bulletChar) || ((i = e.addChild("list", e.nextNonspace)).listData = n), (i = e.addChild("item", e.nextNonspace)).listData = n, 1)
        }, function(e) {
            return e.indented && "paragraph" !== e.tip.type && !e.blank ? (e.advanceOffset(4, !0), e.closeUnmatchedBlocks(), e.addChild("codeBlock", e.offset), 2) : 0
        }, function(e, t) {
            var n = t.stringContent;
            if ("paragraph" === t.type && !e.indented && !e.blank) {
                var r = n.length - 1,
                    o = n.lastIndexOf("\n", r - 1) + 1,
                    i = n.slice(o, r),
                    s = e.currentLine.slice(e.nextNonspace),
                    a = Bp(i),
                    l = a[0],
                    c = a[1],
                    u = Bp(s),
                    d = u[0],
                    p = u[1],
                    h = /^[ \t]*:?-+:?[ \t]*$/;
                if (!c.length || !p.length || p.some(function(e) {
                        return !h.test(e)
                    }) || 1 === p.length && 0 !== s.indexOf("|")) return 0;
                var f = t.lineOffsets,
                    m = e.lineNumber - 1,
                    g = Gd(f) + 1,
                    v = Ld("table", [
                        [m, g],
                        [e.lineNumber, e.offset]
                    ]);
                if (v.columns = p.map(function() {
                        return {
                            align: null
                        }
                    }), t.insertAfter(v), 1 === f.length) t.unlink();
                else {
                    t.stringContent = n.slice(0, o);
                    var y = o - (n.lastIndexOf("\n", o - 2) + 1) - 1;
                    e.lastLineLength = f[f.length - 2] + y, e.finalize(t, m - 1)
                }
                e.advanceOffset(e.currentLine.length - e.offset, !1);
                var b = Ld("tableHead", [
                    [m, g],
                    [e.lineNumber, e.offset]
                ]);
                v.appendChild(b);
                var w = Ld("tableRow", [
                        [m, g],
                        [m, g + i.length - 1]
                    ]),
                    k = Ld("tableDelimRow", [
                        [e.lineNumber, e.nextNonspace + 1],
                        [e.lineNumber, e.offset]
                    ]);
                b.appendChild(w), b.appendChild(k), Fp("tableCell", c, m, g + l).forEach(function(e) {
                    w.appendChild(e)
                });
                var x = Fp("tableDelimCell", p, e.lineNumber, e.nextNonspace + 1 + d);
                return x.forEach(function(e) {
                    k.appendChild(e)
                }), v.columns = x.map(Hp), e.tip = v, 2
            }
            return 0
        }, function(e, t) {
            if ("table" !== t.type && "tableBody" !== t.type || !e.blank && -1 === e.currentLine.indexOf("|")) return 0;
            if (e.advanceOffset(e.currentLine.length - e.offset, !1), e.blank) {
                var n = t;
                return "tableBody" === t.type && (n = t.parent, e.finalize(t, e.lineNumber - 1)), e.finalize(n, e.lineNumber - 1), 0
            }
            var r = t;
            "table" === t.type && ((r = e.addChild("tableBody", e.nextNonspace)).stringContent = null);
            var o = Ld("tableRow", [
                [e.lineNumber, e.nextNonspace + 1],
                [e.lineNumber, e.currentLine.length]
            ]);
            r.appendChild(o);
            var i = r.parent,
                s = Bp(e.currentLine.slice(e.nextNonspace)),
                a = s[0];
            return Fp("tableCell", s[1], e.lineNumber, e.nextNonspace + 1 + a).forEach(function(e, t) {
                t >= i.columns.length && (e.ignored = !0), o.appendChild(e)
            }), 2
        }, function(e) {
            var t;
            if (!e.indented && !qp.test(e.currentLine) && (t = e.currentLine.match(zp))) {
                var n = t[1].length;
                e.closeUnmatchedBlocks();
                var r = e.addChild("customBlock", e.nextNonspace);
                return r.syntaxLength = n, r.offset = e.indent, e.advanceNextNonspace(), e.advanceOffset(n, !1), 2
            }
            return 0
        }],
        Xp = /^(-{3}|\+{3}|;{3})$/,
        Zp = function(e, t) {
            var n = e.currentLine,
                r = e.lineNumber,
                o = e.indented;
            return 1 === r && !o && "document" === t.type && Xp.test(n) ? (e.closeUnmatchedBlocks(), e.addChild("frontMatter", e.nextNonspace).stringContent = n, e.advanceNextNonspace(), e.advanceOffset(n.length, !1), 2) : 0
        },
        Qp = {
            continue: function(e, t) {
                var n = e.currentLine,
                    r = n.match(Xp);
                return "frontMatter" === t.type && r ? (t.stringContent += n, e.lastLineLength = r[0].length, e.finalize(t, e.lineNumber), 2) : 0
            },
            finalize: function(e, t) {
                null !== t.stringContent && (t.literal = t.stringContent, t.stringContent = null)
            },
            canContain: function() {
                return !1
            },
            acceptsLines: !0
        },
        Yp = [/./, /<\/(?:script|pre|style)>/i, /-->/, /\?>/, />/, /\]\]>/],
        eh = /^[#`~*+_=<>0-9-;$]/,
        th = /\r\n|\n|\r/;

    function nh() {
        return Ld("document", [
            [1, 1],
            [0, 0]
        ])
    }
    var rh = {
            smart: !1,
            tagFilter: !1,
            extendedAutolinks: !1,
            disallowedHtmlBlockTags: [],
            referenceDefinition: !1,
            disallowDeepHeading: !1,
            customParser: null,
            frontMatter: !1
        },
        oh = function() {
            function e(e) {
                this.options = yu(yu({}, rh), e), this.doc = nh(), this.tip = this.doc, this.oldtip = this.doc, this.lineNumber = 0, this.offset = 0, this.column = 0, this.nextNonspace = 0, this.nextNonspaceColumn = 0, this.indent = 0, this.currentLine = "", this.indented = !1, this.blank = !1, this.partiallyConsumedTab = !1, this.allClosed = !0, this.lastMatchedContainer = this.doc, this.refMap = {}, this.refLinkCandidateMap = {}, this.refDefCandidateMap = {}, this.lastLineLength = 0, this.lines = [], this.options.frontMatter && (Pp.frontMatter = Qp, Gp.unshift(Zp)), this.inlineParser = new xp(this.options)
            }
            return e.prototype.advanceOffset = function(e, t) {
                void 0 === t && (t = !1);
                for (var n, r, o, i = this.currentLine; e > 0 && (o = i[this.offset]);) "\t" === o ? (n = 4 - this.column % 4, t ? (this.partiallyConsumedTab = n > e, r = n > e ? e : n, this.column += r, this.offset += this.partiallyConsumedTab ? 0 : 1, e -= r) : (this.partiallyConsumedTab = !1, this.column += n, this.offset += 1, e -= 1)) : (this.partiallyConsumedTab = !1, this.offset += 1, this.column += 1, e -= 1)
            }, e.prototype.advanceNextNonspace = function() {
                this.offset = this.nextNonspace, this.column = this.nextNonspaceColumn, this.partiallyConsumedTab = !1
            }, e.prototype.findNextNonspace = function() {
                for (var e, t = this.currentLine, n = this.offset, r = this.column;
                    "" !== (e = t.charAt(n));)
                    if (" " === e) n++, r++;
                    else {
                        if ("\t" !== e) break;
                        n++, r += 4 - r % 4
                    } this.blank = "\n" === e || "\r" === e || "" === e, this.nextNonspace = n, this.nextNonspaceColumn = r, this.indent = this.nextNonspaceColumn - this.column, this.indented = this.indent >= 4
            }, e.prototype.addLine = function() {
                if (this.partiallyConsumedTab) {
                    this.offset += 1;
                    var e = 4 - this.column % 4;
                    this.tip.stringContent += pd(" ", e)
                }
                this.tip.lineOffsets ? this.tip.lineOffsets.push(this.offset) : this.tip.lineOffsets = [this.offset], this.tip.stringContent += this.currentLine.slice(this.offset) + "\n"
            }, e.prototype.addChild = function(e, t) {
                for (; !Pp[this.tip.type].canContain(e);) this.finalize(this.tip, this.lineNumber - 1);
                var n = t + 1,
                    r = Ld(e, [
                        [this.lineNumber, n],
                        [0, 0]
                    ]);
                return r.stringContent = "", this.tip.appendChild(r), this.tip = r, r
            }, e.prototype.closeUnmatchedBlocks = function() {
                if (!this.allClosed) {
                    for (; this.oldtip !== this.lastMatchedContainer;) {
                        var e = this.oldtip.parent;
                        this.finalize(this.oldtip, this.lineNumber - 1), this.oldtip = e
                    }
                    this.allClosed = !0
                }
            }, e.prototype.finalize = function(e, t) {
                var n = e.parent;
                e.open = !1, e.sourcepos[1] = [t, this.lastLineLength], Pp[e.type].finalize(this, e), this.tip = n
            }, e.prototype.processInlines = function(e) {
                var t, n = this.options.customParser,
                    r = e.walker();
                for (this.inlineParser.refMap = this.refMap, this.inlineParser.refLinkCandidateMap = this.refLinkCandidateMap, this.inlineParser.refDefCandidateMap = this.refDefCandidateMap, this.inlineParser.options = this.options; t = r.next();) {
                    var o = t.node,
                        i = t.entering,
                        s = o.type;
                    n && n[s] && n[s](o, {
                        entering: i,
                        options: this.options
                    }), i || "paragraph" !== s && "heading" !== s && ("tableCell" !== s || o.ignored) || this.inlineParser.parse(o)
                }
            }, e.prototype.incorporateLine = function(e) {
                var t = this.doc;
                this.oldtip = this.tip, this.offset = 0, this.column = 0, this.blank = !1, this.partiallyConsumedTab = !1, this.lineNumber += 1, -1 !== e.indexOf("\0") && (e = e.replace(/\0/g, "�")), this.currentLine = e;
                for (var n, r = !0;
                    (n = t.lastChild) && n.open;) {
                    switch (t = n, this.findNextNonspace(), Pp[t.type].continue(this, t)) {
                        case 0:
                            break;
                        case 1:
                            r = !1;
                            break;
                        case 2:
                            return void(this.lastLineLength = e.length);
                        default:
                            throw new Error("continue returned illegal value, must be 0, 1, or 2")
                    }
                    if (!r) {
                        t = t.parent;
                        break
                    }
                }
                this.allClosed = t === this.oldtip, this.lastMatchedContainer = t;
                for (var o = "paragraph" !== t.type && Pp[t.type].acceptsLines, i = Gp.length; !o;) {
                    if (this.findNextNonspace(), "table" !== t.type && "tableBody" !== t.type && "paragraph" !== t.type && !this.indented && !eh.test(e.slice(this.nextNonspace))) {
                        this.advanceNextNonspace();
                        break
                    }
                    for (var s = 0; s < i;) {
                        var a = Gp[s](this, t);
                        if (1 === a) {
                            t = this.tip;
                            break
                        }
                        if (2 === a) {
                            t = this.tip, o = !0;
                            break
                        }
                        s++
                    }
                    if (s === i) {
                        this.advanceNextNonspace();
                        break
                    }
                }
                if (this.allClosed || this.blank || "paragraph" !== this.tip.type) {
                    this.closeUnmatchedBlocks(), this.blank && t.lastChild && (t.lastChild.lastLineBlank = !0);
                    for (var l = t.type, c = this.blank && !("blockQuote" === l || Id(t) && t.isFenced || "item" === l && !t.firstChild && t.sourcepos[0][0] === this.lineNumber), u = t; u;) u.lastLineBlank = c, u = u.parent;
                    Pp[l].acceptsLines ? (this.addLine(), "htmlBlock" === t.type && t.htmlBlockType >= 1 && t.htmlBlockType <= 5 && Yp[t.htmlBlockType].test(this.currentLine.slice(this.offset)) && (this.lastLineLength = e.length, this.finalize(t, this.lineNumber))) : this.offset < e.length && !this.blank && (t = this.addChild("paragraph", this.offset), this.advanceNextNonspace(), this.addLine())
                } else this.addLine();
                this.lastLineLength = e.length
            }, e.prototype.parse = function(e, t) {
                this.doc = nh(), this.tip = this.doc, this.lineNumber = 0, this.lastLineLength = 0, this.offset = 0, this.column = 0, this.lastMatchedContainer = this.doc, this.currentLine = "";
                var n = e.split(th),
                    r = n.length;
                this.lines = t || n, this.options.referenceDefinition && this.clearRefMaps(), 10 === e.charCodeAt(e.length - 1) && (r -= 1);
                for (var o = 0; o < r; o++) this.incorporateLine(n[o]);
                for (; this.tip;) this.finalize(this.tip, r);
                return this.processInlines(this.doc), this.doc
            }, e.prototype.partialParseStart = function(e, t) {
                this.doc = nh(), this.tip = this.doc, this.lineNumber = e - 1, this.lastLineLength = 0, this.offset = 0, this.column = 0, this.lastMatchedContainer = this.doc, this.currentLine = "";
                for (var n = t.length, r = 0; r < n; r++) this.incorporateLine(t[r]);
                return this.doc
            }, e.prototype.partialParseExtends = function(e) {
                for (var t = 0; t < e.length; t++) this.incorporateLine(e[t])
            }, e.prototype.partialParseFinish = function() {
                for (; this.tip;) this.finalize(this.tip, this.lineNumber);
                this.processInlines(this.doc)
            }, e.prototype.setRefMaps = function(e, t, n) {
                this.refMap = e, this.refLinkCandidateMap = t, this.refDefCandidateMap = n
            }, e.prototype.clearRefMaps = function() {
                [this.refMap, this.refLinkCandidateMap, this.refDefCandidateMap].forEach(function(e) {
                    var t;
                    t = e, Object.keys(t).forEach(function(e) {
                        delete t[e]
                    })
                })
            }, e
        }();

    function ih(e, t) {
        return e[0] < t[0] ? 1 : e[0] > t[0] ? -1 : e[1] < t[1] ? 1 : e[1] > t[1] ? -1 : 0
    }

    function sh(e, t) {
        var n = e[0];
        return 1 === ih(e[1], t) ? 1 : -1 === ih(n, t) ? -1 : 0
    }

    function ah(e, t) {
        for (var n = 0, r = t; n < r.length; n++) {
            var o = r[n];
            e.insertBefore(o)
        }
    }

    function lh(e, t) {
        var n = e[0];
        return e[1][0] < t ? 1 : n[0] > t ? -1 : 0
    }

    function ch(e, t) {
        for (var n = e.firstChild; n;) {
            var r = lh(n.sourcepos, t);
            if (0 === r) return n;
            if (-1 === r) return n.prev || n;
            n = n.next
        }
        return e.lastChild
    }

    function uh(e) {
        return function(e) {
            return vd[e]
        }(e) || null
    }

    function dh(e, t, n) {
        if (void 0 === n && (n = null), t)
            for (var r = t.walker(); t && t !== n;) {
                e(t);
                var o = r.next();
                if (!o) break;
                t = o.node
            }
    }
    var ph = /\r\n|\n|\r/;

    function hh(e) {
        return {
            id: e.id,
            title: e.title,
            sourcepos: e.sourcepos,
            unlinked: !1,
            destination: e.dest
        }
    }
    var fh = function() {
            function e(e, t) {
                this.refMap = {}, this.refLinkCandidateMap = {}, this.refDefCandidateMap = {}, this.referenceDefinition = !!(null == t ? void 0 : t.referenceDefinition), this.parser = new oh(t), this.parser.setRefMaps(this.refMap, this.refLinkCandidateMap, this.refDefCandidateMap), this.eventHandlerMap = {
                    change: []
                }, e = e || "", this.lineTexts = e.split(ph), this.root = this.parser.parse(e, this.lineTexts)
            }
            return e.prototype.updateLineTexts = function(e, t, n) {
                var r, o = e[0],
                    i = e[1],
                    s = t[0],
                    a = t[1],
                    l = n.split(ph),
                    c = l.length,
                    u = this.lineTexts[o - 1],
                    d = this.lineTexts[s - 1];
                l[0] = u.slice(0, i - 1) + l[0], l[c - 1] = l[c - 1] + d.slice(a - 1);
                var p = s - o + 1;
                return (r = this.lineTexts).splice.apply(r, bu([o - 1, p], l)), c - p
            }, e.prototype.updateRootNodeState = function() {
                if (1 === this.lineTexts.length && "" === this.lineTexts[0]) return this.root.lastLineBlank = !0, void(this.root.sourcepos = [
                    [1, 1],
                    [1, 0]
                ]);
                this.root.lastChild && (this.root.lastLineBlank = this.root.lastChild.lastLineBlank);
                for (var e = this.lineTexts, t = e.length - 1;
                    "" === e[t];) t -= 1;
                e.length - 2 > t && (t += 1), this.root.sourcepos[1] = [t + 1, e[t].length]
            }, e.prototype.replaceRangeNodes = function(e, t, n) {
                e ? (ah(e, n), function(e, t) {
                    if (e.parent === t.parent && e !== t) {
                        for (var n = e.next; n && n !== t;) {
                            for (var r = n.next, o = 0, i = ["parent", "prev", "next"]; o < i.length; o++) {
                                var s = i[o];
                                n[s] && (yd(n[s].id), n[s] = null)
                            }
                            n = r
                        }
                        e.next = t.next, t.next ? t.next.prev = e : e.parent.lastChild = e
                    }
                }(e, t), [e.id, t.id].forEach(function(e) {
                    return yd(e)
                }), e.unlink()) : t ? (ah(t, n), yd(t.id), t.unlink()) : function(e, t) {
                    for (var n = t.length - 1; n >= 0; n -= 1) e.prependChild(t[n])
                }(this.root, n)
            }, e.prototype.getNodeRange = function(e, t) {
                var n = ch(this.root, e[0]),
                    r = ch(this.root, t[0]);
                return r && r.next && t[0] + 1 === r.next.sourcepos[0][0] && (r = r.next), [n, r]
            }, e.prototype.trigger = function(e, t) {
                this.eventHandlerMap[e].forEach(function(e) {
                    e(t)
                })
            }, e.prototype.extendEndLine = function(e) {
                for (;
                    "" === this.lineTexts[e];) e += 1;
                return e
            }, e.prototype.parseRange = function(e, t, n, r) {
                var o;
                e && e.prev && (Rd(e.prev) && function(e) {
                    var t = e.match(/^[ \t]+/);
                    if (t && (t[0].length >= 2 || /\t/.test(t[0]))) return !0;
                    var n = t ? e.slice(t.length) : e;
                    return Wp.test(n) || Jp.test(n)
                }(this.lineTexts[n - 1]) || "table" === e.prev.type && !Np(o = this.lineTexts[n - 1]) && -1 !== o.indexOf("|")) && (n = (e = e.prev).sourcepos[0][0]);
                for (var i = this.lineTexts.slice(n - 1, r), s = this.parser.partialParseStart(n, i), a = t ? t.next : this.root.firstChild, l = s.lastChild, c = l && Id(l) && l.open, u = l && Bd(l) && l.open, d = l && Rd(l);
                    (c || u) && a || d && a && ("list" === a.type || a.sourcepos[0][1] >= 2);) {
                    var p = this.extendEndLine(a.sourcepos[1][0]);
                    this.parser.partialParseExtends(this.lineTexts.slice(r, p)), e || (e = t), t = a, r = p, a = a.next
                }
                return this.parser.partialParseFinish(), {
                    newNodes: function(e) {
                        for (var t = [], n = e.firstChild; n;) t.push(n), n = n.next;
                        return t
                    }(s),
                    extStartNode: e,
                    extEndNode: t
                }
            }, e.prototype.getRemovedNodeRange = function(e, t) {
                return !e || e && Pd(e) || t && Pd(t) ? null : {
                    id: [e.id, t.id],
                    line: [e.sourcepos[0][0] - 1, t.sourcepos[1][0] - 1]
                }
            }, e.prototype.markDeletedRefMap = function(e, t) {
                var n = this;
                if (!Qd(this.refMap)) {
                    var r = function(e) {
                        if (Pd(e)) {
                            var t = n.refMap[e.label];
                            t && e.id === t.id && (t.unlinked = !0)
                        }
                    };
                    e && dh(r, e.parent, t), t && dh(r, t)
                }
            }, e.prototype.replaceWithNewRefDefState = function(e) {
                var t = this;
                if (!Qd(this.refMap)) {
                    var n = function(e) {
                        if (Pd(e)) {
                            var n = e.label,
                                r = t.refMap[n];
                            r && !r.unlinked || (t.refMap[n] = hh(e))
                        }
                    };
                    e.forEach(function(e) {
                        dh(n, e)
                    })
                }
            }, e.prototype.replaceWithRefDefCandidate = function() {
                var e = this;
                Qd(this.refDefCandidateMap) || Zd(this.refDefCandidateMap, function(t, n) {
                    var r = n.label,
                        o = n.sourcepos,
                        i = e.refMap[r];
                    (!i || i.unlinked || i.sourcepos[0][0] > o[0][0]) && (e.refMap[r] = hh(n))
                })
            }, e.prototype.getRangeWithRefDef = function(e, t, n, r, o) {
                if (this.referenceDefinition && !Qd(this.refMap)) {
                    var i = ch(this.root, e - 1),
                        s = ch(this.root, t + 1);
                    i && Pd(i) && i !== n && i !== r && (e = (n = i).sourcepos[0][0]), s && Pd(s) && s !== n && s !== r && (r = s, t = this.extendEndLine(r.sourcepos[1][0] + o))
                }
                return [n, r, e, t]
            }, e.prototype.parse = function(e, t, n) {
                void 0 === n && (n = 0);
                var r = this.getNodeRange(e, t),
                    o = r[0],
                    i = r[1],
                    s = o ? Math.min(o.sourcepos[0][0], e[0]) : e[0],
                    a = this.extendEndLine((i ? Math.max(i.sourcepos[1][0], t[0]) : t[0]) + n),
                    l = this.parseRange.apply(this, this.getRangeWithRefDef(s, a, o, i, n)),
                    c = l.newNodes,
                    u = l.extStartNode,
                    d = l.extEndNode,
                    p = this.getRemovedNodeRange(u, d),
                    h = d ? d.next : this.root.firstChild;
                return this.referenceDefinition ? (this.markDeletedRefMap(u, d), this.replaceRangeNodes(u, d, c), this.replaceWithNewRefDefState(c)) : this.replaceRangeNodes(u, d, c), {
                    nodes: c,
                    removedNodeRange: p,
                    nextNode: h
                }
            }, e.prototype.parseRefLink = function() {
                var e = this,
                    t = [];
                return Qd(this.refMap) || Zd(this.refMap, function(n, r) {
                    r.unlinked && delete e.refMap[n], Zd(e.refLinkCandidateMap, function(r, o) {
                        var i = o.node;
                        o.refLabel === n && t.push(e.parse(i.sourcepos[0], i.sourcepos[1]))
                    })
                }), t
            }, e.prototype.removeUnlinkedCandidate = function() {
                Qd(this.refDefCandidateMap) || [this.refLinkCandidateMap, this.refDefCandidateMap].forEach(function(e) {
                    Zd(e, function(t) {
                        (function(e) {
                            var t = uh(e);
                            if (!t) return !0;
                            for (; t && "document" !== t.type;) {
                                if (!t.parent && !t.prev && !t.next) return !0;
                                t = t.parent
                            }
                            return !1
                        })(t) && delete e[t]
                    })
                })
            }, e.prototype.editMarkdown = function(e, t, n) {
                var r = this.updateLineTexts(e, t, n),
                    o = this.parse(e, t, r),
                    i = function(e) {
                        for (var t = [], n = 1; n < arguments.length; n++) t[n - 1] = arguments[n];
                        var r = yu({}, e);
                        return t.forEach(function(e) {
                            delete r[e]
                        }), r
                    }(o, "nextNode");
                ! function(e, t) {
                    if (e && e.parent && 0 !== t) {
                        var n, r = e.parent.walker();
                        for (r.resumeAt(e, !0); n = r.next();) {
                            var o = n.node;
                            n.entering && (o.sourcepos[0][0] += t, o.sourcepos[1][0] += t)
                        }
                    }
                }(o.nextNode, r), this.updateRootNodeState();
                var s = [i];
                return this.referenceDefinition && (this.removeUnlinkedCandidate(), this.replaceWithRefDefCandidate(), s = s.concat(this.parseRefLink())), this.trigger("change", s), s
            }, e.prototype.getLineTexts = function() {
                return this.lineTexts
            }, e.prototype.getRootNode = function() {
                return this.root
            }, e.prototype.findNodeAtPosition = function(e) {
                var t = function(e, t) {
                    for (var n = e, r = null; n;) {
                        var o = sh(n.sourcepos, t);
                        if (0 === o) {
                            if (!n.firstChild) return n;
                            r = n, n = n.firstChild
                        } else {
                            if (-1 === o) return r;
                            if (!n.next) return r;
                            n = n.next
                        }
                    }
                    return n
                }(this.root, e);
                return t && t !== this.root ? t : null
            }, e.prototype.findFirstNodeAtLine = function(e) {
                return function(e, t) {
                    for (var n = e.firstChild, r = null; n;) {
                        var o = lh(n.sourcepos, t);
                        if (0 === o) {
                            if (n.sourcepos[0][0] === t || !n.firstChild) return n;
                            r = n, n = n.firstChild
                        } else {
                            if (-1 === o) break;
                            r = n, n = n.next
                        }
                    }
                    return r ? function(e) {
                        for (; e.parent && "document" !== e.parent.type && e.parent.sourcepos[0][0] === e.sourcepos[0][0];) e = e.parent;
                        return e
                    }(function(e) {
                        for (; e.lastChild;) e = e.lastChild;
                        return e
                    }(r)) : null
                }(this.root, e)
            }, e.prototype.on = function(e, t) {
                this.eventHandlerMap[e].push(t)
            }, e.prototype.off = function(e, t) {
                var n = this.eventHandlerMap[e],
                    r = n.indexOf(t);
                n.splice(r, 1)
            }, e.prototype.findNodeById = function(e) {
                return uh(e)
            }, e.prototype.removeAllNode = function() {
                vd = {}
            }, e
        }(),
        mh = new RegExp("<(/?(?:" + ["title", "textarea", "style", "xmp", "iframe", "noembed", "noframes", "script", "plaintext"].join("|") + ")[^>]*>)", "ig");

    function gh(e) {
        return mh.test(e) ? e.replace(mh, function(e, t) {
            return "&lt;" + t
        }) : e
    }
    var vh = {
            heading: function(e, t) {
                return {
                    type: t.entering ? "openTag" : "closeTag",
                    tagName: "h" + e.level,
                    outerNewLine: !0
                }
            },
            text: function(e) {
                return {
                    type: "text",
                    content: e.literal
                }
            },
            softbreak: function(e, t) {
                return {
                    type: "html",
                    content: t.options.softbreak
                }
            },
            linebreak: function() {
                return {
                    type: "html",
                    content: "<br />\n"
                }
            },
            emph: function(e, t) {
                return {
                    type: t.entering ? "openTag" : "closeTag",
                    tagName: "em"
                }
            },
            strong: function(e, t) {
                return {
                    type: t.entering ? "openTag" : "closeTag",
                    tagName: "strong"
                }
            },
            paragraph: function(e, t) {
                var n, r = t.entering,
                    o = null === (n = e.parent) || void 0 === n ? void 0 : n.parent;
                return o && "list" === o.type && o.listData.tight ? null : {
                    type: r ? "openTag" : "closeTag",
                    tagName: "p",
                    outerNewLine: !0
                }
            },
            thematicBreak: function() {
                return {
                    type: "openTag",
                    tagName: "hr",
                    outerNewLine: !0,
                    selfClose: !0
                }
            },
            blockQuote: function(e, t) {
                return {
                    type: t.entering ? "openTag" : "closeTag",
                    tagName: "blockquote",
                    outerNewLine: !0,
                    innerNewLine: !0
                }
            },
            list: function(e, t) {
                var n = t.entering,
                    r = e.listData,
                    o = r.type,
                    i = r.start,
                    s = "bullet" === o ? "ul" : "ol",
                    a = {};
                return "ol" === s && null !== i && 1 !== i && (a.start = i.toString()), {
                    type: n ? "openTag" : "closeTag",
                    tagName: s,
                    attributes: a,
                    outerNewLine: !0
                }
            },
            item: function(e, t) {
                return {
                    type: t.entering ? "openTag" : "closeTag",
                    tagName: "li",
                    outerNewLine: !0
                }
            },
            htmlInline: function(e, t) {
                return {
                    type: "html",
                    content: t.options.tagFilter ? gh(e.literal) : e.literal
                }
            },
            htmlBlock: function(e, t) {
                var n = t.options,
                    r = n.tagFilter ? gh(e.literal) : e.literal;
                return n.nodeId ? [{
                    type: "openTag",
                    tagName: "div",
                    outerNewLine: !0
                }, {
                    type: "html",
                    content: r
                }, {
                    type: "closeTag",
                    tagName: "div",
                    outerNewLine: !0
                }] : {
                    type: "html",
                    content: r,
                    outerNewLine: !0
                }
            },
            code: function(e) {
                return [{
                    type: "openTag",
                    tagName: "code"
                }, {
                    type: "text",
                    content: e.literal
                }, {
                    type: "closeTag",
                    tagName: "code"
                }]
            },
            codeBlock: function(e) {
                var t = e.info,
                    n = t ? t.split(/\s+/) : [],
                    r = [];
                return n.length > 0 && n[0].length > 0 && r.push("language-" + dd(n[0])), [{
                    type: "openTag",
                    tagName: "pre",
                    outerNewLine: !0
                }, {
                    type: "openTag",
                    tagName: "code",
                    classNames: r
                }, {
                    type: "text",
                    content: e.literal
                }, {
                    type: "closeTag",
                    tagName: "code"
                }, {
                    type: "closeTag",
                    tagName: "pre",
                    outerNewLine: !0
                }]
            },
            link: function(e, t) {
                if (t.entering) {
                    var n = e,
                        r = n.title,
                        o = n.destination;
                    return {
                        type: "openTag",
                        tagName: "a",
                        attributes: yu({
                            href: dd(o)
                        }, r && {
                            title: dd(r)
                        })
                    }
                }
                return {
                    type: "closeTag",
                    tagName: "a"
                }
            },
            image: function(e, t) {
                var n = t.getChildrenText,
                    r = t.skipChildren,
                    o = e,
                    i = o.title,
                    s = o.destination;
                return r(), {
                    type: "openTag",
                    tagName: "img",
                    selfClose: !0,
                    attributes: yu({
                        src: dd(s),
                        alt: n(e)
                    }, i && {
                        title: dd(i)
                    })
                }
            },
            customBlock: function(e, t, n) {
                var r = e.info.trim().toLowerCase(),
                    o = n[r];
                if (o) try {
                    return o(e, t)
                } catch (e) {
                    console.warn("[@toast-ui/editor] - The error occurred when " + r + " block node was parsed in markdown renderer: " + e)
                }
                return [{
                    type: "openTag",
                    tagName: "div",
                    outerNewLine: !0
                }, {
                    type: "text",
                    content: e.literal
                }, {
                    type: "closeTag",
                    tagName: "div",
                    outerNewLine: !0
                }]
            },
            frontMatter: function(e) {
                return [{
                    type: "openTag",
                    tagName: "div",
                    outerNewLine: !0,
                    attributes: {
                        style: "white-space: pre; display: none;"
                    }
                }, {
                    type: "text",
                    content: e.literal
                }, {
                    type: "closeTag",
                    tagName: "div",
                    outerNewLine: !0
                }]
            },
            customInline: function(e, t, n) {
                var r = e,
                    o = r.info,
                    i = r.firstChild,
                    s = o.trim().toLowerCase(),
                    a = n[s],
                    l = t.entering;
                if (a) try {
                    return a(e, t)
                } catch (e) {
                    console.warn("[@toast-ui/editor] - The error occurred when " + s + " inline node was parsed in markdown renderer: " + e)
                }
                return l ? [{
                    type: "openTag",
                    tagName: "span"
                }, {
                    type: "text",
                    content: "$$" + o + (i ? " " : "")
                }] : [{
                    type: "text",
                    content: "$$"
                }, {
                    type: "closeTag",
                    tagName: "span"
                }]
            }
        },
        yh = {
            strike: function(e, t) {
                return {
                    type: t.entering ? "openTag" : "closeTag",
                    tagName: "del"
                }
            },
            item: function(e, t) {
                var n = t.entering,
                    r = e.listData,
                    o = r.checked,
                    i = r.task;
                if (n) {
                    var s = {
                        type: "openTag",
                        tagName: "li",
                        outerNewLine: !0
                    };
                    return i ? [s, {
                        type: "openTag",
                        tagName: "input",
                        selfClose: !0,
                        attributes: yu(yu({}, o && {
                            checked: ""
                        }), {
                            disabled: "",
                            type: "checkbox"
                        })
                    }, {
                        type: "text",
                        content: " "
                    }] : s
                }
                return {
                    type: "closeTag",
                    tagName: "li",
                    outerNewLine: !0
                }
            },
            table: function(e, t) {
                return {
                    type: t.entering ? "openTag" : "closeTag",
                    tagName: "table",
                    outerNewLine: !0
                }
            },
            tableHead: function(e, t) {
                return {
                    type: t.entering ? "openTag" : "closeTag",
                    tagName: "thead",
                    outerNewLine: !0
                }
            },
            tableBody: function(e, t) {
                return {
                    type: t.entering ? "openTag" : "closeTag",
                    tagName: "tbody",
                    outerNewLine: !0
                }
            },
            tableRow: function(e, t) {
                if (t.entering) return {
                    type: "openTag",
                    tagName: "tr",
                    outerNewLine: !0
                };
                var n = [];
                if (e.lastChild)
                    for (var r = e.parent.parent.columns.length, o = e.lastChild.endIdx + 1; o < r; o += 1) n.push({
                        type: "openTag",
                        tagName: "td",
                        outerNewLine: !0
                    }, {
                        type: "closeTag",
                        tagName: "td",
                        outerNewLine: !0
                    });
                return n.push({
                    type: "closeTag",
                    tagName: "tr",
                    outerNewLine: !0
                }), n
            },
            tableCell: function(e, t) {
                var n = t.entering;
                if (e.ignored) return {
                    type: "text",
                    content: ""
                };
                var r = e.parent.parent,
                    o = "tableHead" === r.type ? "th" : "td",
                    i = r.parent.columns[e.startIdx],
                    s = (null == i ? void 0 : i.align) ? {
                        align: i.align
                    } : null;
                return n ? yu({
                    type: "openTag",
                    tagName: o,
                    outerNewLine: !0
                }, s && {
                    attributes: s
                }) : {
                    type: "closeTag",
                    tagName: o,
                    outerNewLine: !0
                }
            }
        },
        bh = {
            softbreak: "\n",
            gfm: !1,
            tagFilter: !1,
            nodeId: !1
        };

    function wh(e) {
        for (var t = [], n = e.walker(), r = null; r = n.next();) {
            var o = r.node;
            "text" === o.type && t.push(o.literal)
        }
        return t.join("")
    }
    var kh = function() {
            function e(e) {
                this.buffer = [], this.options = yu(yu({}, bh), e), this.convertors = this.createConvertors(), delete this.options.convertors
            }
            return e.prototype.createConvertors = function() {
                var e = yu({}, vh);
                if (this.options.gfm && (e = yu(yu({}, e), yh)), this.options.convertors) {
                    var t = this.options.convertors,
                        n = Object.keys(t),
                        r = yu(yu({}, vh), yh);
                    n.forEach(function(n) {
                        var o = e[n],
                            i = t[n],
                            s = -1 === Object.keys(r).indexOf(n) ? n.toLowerCase() : n;
                        e[s] = o ? function(e, t, n) {
                            return t.origin = function() {
                                return o(e, t, n)
                            }, i(e, t)
                        } : i
                    })
                }
                return e
            }, e.prototype.getConvertors = function() {
                return this.convertors
            }, e.prototype.getOptions = function() {
                return this.options
            }, e.prototype.render = function(e) {
                var t = this;
                this.buffer = [];
                for (var n = e.walker(), r = null, o = function() {
                        var e = r.node,
                            o = r.entering,
                            s = i.convertors[e.type];
                        if (!s) return "continue";
                        var a = !1,
                            l = {
                                entering: o,
                                leaf: !md(e),
                                options: i.options,
                                getChildrenText: wh,
                                skipChildren: function() {
                                    a = !0
                                }
                            },
                            c = Bd(e) || function(e) {
                                return "customInline" === e.type
                            }(e) ? s(e, l, i.convertors) : s(e, l);
                        c && ((Array.isArray(c) ? c : [c]).forEach(function(n, r) {
                            "openTag" === n.type && t.options.nodeId && 0 === r && (n.attributes || (n.attributes = {}), n.attributes["data-nodeid"] = String(e.id)), t.renderHTMLNode(n)
                        }), a && (n.resumeAt(e, !1), n.next()))
                    }, i = this; r = n.next();) o();
                return this.addNewLine(), this.buffer.join("")
            }, e.prototype.renderHTMLNode = function(e) {
                switch (e.type) {
                    case "openTag":
                    case "closeTag":
                        this.renderElementNode(e);
                        break;
                    case "text":
                        this.renderTextNode(e);
                        break;
                    case "html":
                        this.renderRawHtmlNode(e)
                }
            }, e.prototype.generateOpenTagString = function(e) {
                var t = this,
                    n = e.tagName,
                    r = e.classNames,
                    o = e.attributes;
                this.buffer.push("<" + n), r && r.length > 0 && this.buffer.push(' class="' + r.join(" ") + '"'), o && Object.keys(o).forEach(function(e) {
                    var n = o[e];
                    t.buffer.push(" " + e + '="' + n + '"')
                }), e.selfClose && this.buffer.push(" /"), this.buffer.push(">")
            }, e.prototype.generateCloseTagString = function(e) {
                var t = e.tagName;
                this.buffer.push("</" + t + ">")
            }, e.prototype.addNewLine = function() {
                this.buffer.length && "\n" !== Gd(Gd(this.buffer)) && this.buffer.push("\n")
            }, e.prototype.addOuterNewLine = function(e) {
                e.outerNewLine && this.addNewLine()
            }, e.prototype.addInnerNewLine = function(e) {
                e.innerNewLine && this.addNewLine()
            }, e.prototype.renderTextNode = function(e) {
                this.buffer.push(dd(e.content))
            }, e.prototype.renderRawHtmlNode = function(e) {
                this.addOuterNewLine(e), this.buffer.push(e.content), this.addOuterNewLine(e)
            }, e.prototype.renderElementNode = function(e) {
                "openTag" === e.type ? (this.addOuterNewLine(e), this.generateOpenTagString(e), e.selfClose ? this.addOuterNewLine(e) : this.addInnerNewLine(e)) : (this.addInnerNewLine(e), this.generateCloseTagString(e), this.addOuterNewLine(e))
            }, e
        }(),
        xh = Object.hasOwnProperty,
        Ch = Object.setPrototypeOf,
        Th = Object.isFrozen,
        Mh = Object.getPrototypeOf,
        Sh = Object.getOwnPropertyDescriptor,
        Eh = Object.freeze,
        Nh = Object.seal,
        Oh = Object.create,
        Dh = "undefined" != typeof Reflect && Reflect,
        Ah = Dh.apply,
        Lh = Dh.construct;
    Ah || (Ah = function(e, t, n) {
        return e.apply(t, n)
    }), Eh || (Eh = function(e) {
        return e
    }), Nh || (Nh = function(e) {
        return e
    }), Lh || (Lh = function(e, t) {
        return new(Function.prototype.bind.apply(e, [null].concat(function(e) {
            if (Array.isArray(e)) {
                for (var t = 0, n = Array(e.length); t < e.length; t++) n[t] = e[t];
                return n
            }
            return Array.from(e)
        }(t))))
    });
    var Ih, Rh = _h(Array.prototype.forEach),
        Ph = _h(Array.prototype.pop),
        Bh = _h(Array.prototype.push),
        Fh = _h(String.prototype.toLowerCase),
        Hh = _h(String.prototype.match),
        zh = _h(String.prototype.replace),
        qh = _h(String.prototype.indexOf),
        Vh = _h(String.prototype.trim),
        jh = _h(RegExp.prototype.test),
        $h = (Ih = TypeError, function() {
            for (var e = arguments.length, t = Array(e), n = 0; n < e; n++) t[n] = arguments[n];
            return Lh(Ih, t)
        });

    function _h(e) {
        return function(t) {
            for (var n = arguments.length, r = Array(n > 1 ? n - 1 : 0), o = 1; o < n; o++) r[o - 1] = arguments[o];
            return Ah(e, t, r)
        }
    }

    function Uh(e, t) {
        Ch && Ch(e, null);
        for (var n = t.length; n--;) {
            var r = t[n];
            if ("string" == typeof r) {
                var o = Fh(r);
                o !== r && (Th(t) || (t[n] = o), r = o)
            }
            e[r] = !0
        }
        return e
    }

    function Wh(e) {
        var t = Oh(null),
            n = void 0;
        for (n in e) Ah(xh, e, [n]) && (t[n] = e[n]);
        return t
    }

    function Jh(e, t) {
        for (; null !== e;) {
            var n = Sh(e, t);
            if (n) {
                if (n.get) return _h(n.get);
                if ("function" == typeof n.value) return _h(n.value)
            }
            e = Mh(e)
        }
        return function(e) {
            return console.warn("fallback value for", e), null
        }
    }
    var Kh = Eh(["a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "section", "select", "shadow", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]),
        Gh = Eh(["svg", "a", "altglyph", "altglyphdef", "altglyphitem", "animatecolor", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "filter", "font", "g", "glyph", "glyphref", "hkern", "image", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "stop", "style", "switch", "symbol", "text", "textpath", "title", "tref", "tspan", "view", "vkern"]),
        Xh = Eh(["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence"]),
        Zh = Eh(["animate", "color-profile", "cursor", "discard", "fedropshadow", "feimage", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignobject", "hatch", "hatchpath", "mesh", "meshgradient", "meshpatch", "meshrow", "missing-glyph", "script", "set", "solidcolor", "unknown", "use"]),
        Qh = Eh(["math", "menclose", "merror", "mfenced", "mfrac", "mglyph", "mi", "mlabeledtr", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mphantom", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msup", "msubsup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover"]),
        Yh = Eh(["maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none"]),
        ef = Eh(["#text"]),
        tf = Eh(["accept", "action", "align", "alt", "autocapitalize", "autocomplete", "autopictureinpicture", "autoplay", "background", "bgcolor", "border", "capture", "cellpadding", "cellspacing", "checked", "cite", "class", "clear", "color", "cols", "colspan", "controls", "controlslist", "coords", "crossorigin", "datetime", "decoding", "default", "dir", "disabled", "disablepictureinpicture", "disableremoteplayback", "download", "draggable", "enctype", "enterkeyhint", "face", "for", "headers", "height", "hidden", "high", "href", "hreflang", "id", "inputmode", "integrity", "ismap", "kind", "label", "lang", "list", "loading", "loop", "low", "max", "maxlength", "media", "method", "min", "minlength", "multiple", "muted", "name", "noshade", "novalidate", "nowrap", "open", "optimum", "pattern", "placeholder", "playsinline", "poster", "preload", "pubdate", "radiogroup", "readonly", "rel", "required", "rev", "reversed", "role", "rows", "rowspan", "spellcheck", "scope", "selected", "shape", "size", "sizes", "span", "srclang", "start", "src", "srcset", "step", "style", "summary", "tabindex", "title", "translate", "type", "usemap", "valign", "value", "width", "xmlns", "slot"]),
        nf = Eh(["accent-height", "accumulate", "additive", "alignment-baseline", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dur", "edgemode", "elevation", "end", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "targetx", "targety", "transform", "text-anchor", "text-decoration", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan"]),
        rf = Eh(["accent", "accentunder", "align", "bevelled", "close", "columnsalign", "columnlines", "columnspan", "denomalign", "depth", "dir", "display", "displaystyle", "encoding", "fence", "frame", "height", "href", "id", "largeop", "length", "linethickness", "lspace", "lquote", "mathbackground", "mathcolor", "mathsize", "mathvariant", "maxsize", "minsize", "movablelimits", "notation", "numalign", "open", "rowalign", "rowlines", "rowspacing", "rowspan", "rspace", "rquote", "scriptlevel", "scriptminsize", "scriptsizemultiplier", "selection", "separator", "separators", "stretchy", "subscriptshift", "supscriptshift", "symmetric", "voffset", "width", "xmlns"]),
        of = Eh(["xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink"]),
        sf = Nh(/\{\{[\s\S]*|[\s\S]*\}\}/gm),
        af = Nh(/<%[\s\S]*|[\s\S]*%>/gm),
        lf = Nh(/^data-[\-\w.\u00B7-\uFFFF]/),
        cf = Nh(/^aria-[\-\w]+$/),
        uf = Nh(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),
        df = Nh(/^(?:\w+script|data):/i),
        pf = Nh(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),
        hf = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(e) {
            return typeof e
        } : function(e) {
            return e && "function" == typeof Symbol && e.constructor === Symbol && e !== Symbol.prototype ? "symbol" : typeof e
        };

    function ff(e) {
        if (Array.isArray(e)) {
            for (var t = 0, n = Array(e.length); t < e.length; t++) n[t] = e[t];
            return n
        }
        return Array.from(e)
    }
    var mf = function() {
            return "undefined" == typeof window ? null : window
        },
        gf = function e() {
            var t = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : mf(),
                n = function(t) {
                    return e(t)
                };
            if (n.version = "2.3.3", n.removed = [], !t || !t.document || 9 !== t.document.nodeType) return n.isSupported = !1, n;
            var r = t.document,
                o = t.document,
                i = t.DocumentFragment,
                s = t.HTMLTemplateElement,
                a = t.Node,
                l = t.Element,
                c = t.NodeFilter,
                u = t.NamedNodeMap,
                d = void 0 === u ? t.NamedNodeMap || t.MozNamedAttrMap : u,
                p = t.Text,
                h = t.Comment,
                f = t.DOMParser,
                m = t.trustedTypes,
                g = l.prototype,
                v = Jh(g, "cloneNode"),
                y = Jh(g, "nextSibling"),
                b = Jh(g, "childNodes"),
                w = Jh(g, "parentNode");
            if ("function" == typeof s) {
                var k = o.createElement("template");
                k.content && k.content.ownerDocument && (o = k.content.ownerDocument)
            }
            var x = function(e, t) {
                    if ("object" !== (void 0 === e ? "undefined" : hf(e)) || "function" != typeof e.createPolicy) return null;
                    var n = null,
                        r = "data-tt-policy-suffix";
                    t.currentScript && t.currentScript.hasAttribute(r) && (n = t.currentScript.getAttribute(r));
                    var o = "dompurify" + (n ? "#" + n : "");
                    try {
                        return e.createPolicy(o, {
                            createHTML: function(e) {
                                return e
                            }
                        })
                    } catch (e) {
                        return console.warn("TrustedTypes policy " + o + " could not be created."), null
                    }
                }(m, r),
                C = x && te ? x.createHTML("") : "",
                T = o,
                M = T.implementation,
                S = T.createNodeIterator,
                E = T.createDocumentFragment,
                N = T.getElementsByTagName,
                O = r.importNode,
                D = {};
            try {
                D = Wh(o).documentMode ? o.documentMode : {}
            } catch (e) {}
            var A = {};
            n.isSupported = "function" == typeof w && M && void 0 !== M.createHTMLDocument && 9 !== D;
            var L = sf,
                I = af,
                R = lf,
                P = cf,
                B = df,
                F = pf,
                H = uf,
                z = null,
                q = Uh({}, [].concat(ff(Kh), ff(Gh), ff(Xh), ff(Qh), ff(ef))),
                V = null,
                j = Uh({}, [].concat(ff(tf), ff(nf), ff(rf), ff(of))),
                $ = null,
                _ = null,
                U = !0,
                W = !0,
                J = !1,
                K = !1,
                G = !1,
                X = !1,
                Z = !1,
                Q = !1,
                Y = !1,
                ee = !0,
                te = !1,
                ne = !0,
                re = !0,
                oe = !1,
                ie = {},
                se = null,
                ae = Uh({}, ["annotation-xml", "audio", "colgroup", "desc", "foreignobject", "head", "iframe", "math", "mi", "mn", "mo", "ms", "mtext", "noembed", "noframes", "noscript", "plaintext", "script", "style", "svg", "template", "thead", "title", "video", "xmp"]),
                le = null,
                ce = Uh({}, ["audio", "video", "img", "source", "image", "track"]),
                ue = null,
                de = Uh({}, ["alt", "class", "for", "id", "label", "name", "pattern", "placeholder", "role", "summary", "title", "value", "style", "xmlns"]),
                pe = "http://www.w3.org/1998/Math/MathML",
                he = "http://www.w3.org/2000/svg",
                fe = "http://www.w3.org/1999/xhtml",
                me = fe,
                ge = !1,
                ve = void 0,
                ye = ["application/xhtml+xml", "text/html"],
                be = void 0,
                we = null,
                ke = o.createElement("form"),
                xe = function(e) {
                    we && we === e || (e && "object" === (void 0 === e ? "undefined" : hf(e)) || (e = {}), e = Wh(e), z = "ALLOWED_TAGS" in e ? Uh({}, e.ALLOWED_TAGS) : q, V = "ALLOWED_ATTR" in e ? Uh({}, e.ALLOWED_ATTR) : j, ue = "ADD_URI_SAFE_ATTR" in e ? Uh(Wh(de), e.ADD_URI_SAFE_ATTR) : de, le = "ADD_DATA_URI_TAGS" in e ? Uh(Wh(ce), e.ADD_DATA_URI_TAGS) : ce, se = "FORBID_CONTENTS" in e ? Uh({}, e.FORBID_CONTENTS) : ae, $ = "FORBID_TAGS" in e ? Uh({}, e.FORBID_TAGS) : {}, _ = "FORBID_ATTR" in e ? Uh({}, e.FORBID_ATTR) : {}, ie = "USE_PROFILES" in e && e.USE_PROFILES, U = !1 !== e.ALLOW_ARIA_ATTR, W = !1 !== e.ALLOW_DATA_ATTR, J = e.ALLOW_UNKNOWN_PROTOCOLS || !1, K = e.SAFE_FOR_TEMPLATES || !1, G = e.WHOLE_DOCUMENT || !1, Q = e.RETURN_DOM || !1, Y = e.RETURN_DOM_FRAGMENT || !1, ee = !1 !== e.RETURN_DOM_IMPORT, te = e.RETURN_TRUSTED_TYPE || !1, Z = e.FORCE_BODY || !1, ne = !1 !== e.SANITIZE_DOM, re = !1 !== e.KEEP_CONTENT, oe = e.IN_PLACE || !1, H = e.ALLOWED_URI_REGEXP || H, me = e.NAMESPACE || fe, ve = ve = -1 === ye.indexOf(e.PARSER_MEDIA_TYPE) ? "text/html" : e.PARSER_MEDIA_TYPE, be = "application/xhtml+xml" === ve ? function(e) {
                        return e
                    } : Fh, K && (W = !1), Y && (Q = !0), ie && (z = Uh({}, [].concat(ff(ef))), V = [], !0 === ie.html && (Uh(z, Kh), Uh(V, tf)), !0 === ie.svg && (Uh(z, Gh), Uh(V, nf), Uh(V, of)), !0 === ie.svgFilters && (Uh(z, Xh), Uh(V, nf), Uh(V, of)), !0 === ie.mathMl && (Uh(z, Qh), Uh(V, rf), Uh(V, of))), e.ADD_TAGS && (z === q && (z = Wh(z)), Uh(z, e.ADD_TAGS)), e.ADD_ATTR && (V === j && (V = Wh(V)), Uh(V, e.ADD_ATTR)), e.ADD_URI_SAFE_ATTR && Uh(ue, e.ADD_URI_SAFE_ATTR), e.FORBID_CONTENTS && (se === ae && (se = Wh(se)), Uh(se, e.FORBID_CONTENTS)), re && (z["#text"] = !0), G && Uh(z, ["html", "head", "body"]), z.table && (Uh(z, ["tbody"]), delete $.tbody), Eh && Eh(e), we = e)
                },
                Ce = Uh({}, ["mi", "mo", "mn", "ms", "mtext"]),
                Te = Uh({}, ["foreignobject", "desc", "title", "annotation-xml"]),
                Me = Uh({}, Gh);
            Uh(Me, Xh), Uh(Me, Zh);
            var Se = Uh({}, Qh);
            Uh(Se, Yh);
            var Ee = function(e) {
                    Bh(n.removed, {
                        element: e
                    });
                    try {
                        e.parentNode.removeChild(e)
                    } catch (t) {
                        try {
                            e.outerHTML = C
                        } catch (t) {
                            e.remove()
                        }
                    }
                },
                Ne = function(e, t) {
                    try {
                        Bh(n.removed, {
                            attribute: t.getAttributeNode(e),
                            from: t
                        })
                    } catch (e) {
                        Bh(n.removed, {
                            attribute: null,
                            from: t
                        })
                    }
                    if (t.removeAttribute(e), "is" === e && !V[e])
                        if (Q || Y) try {
                            Ee(t)
                        } catch (e) {} else try {
                            t.setAttribute(e, "")
                        } catch (e) {}
                },
                Oe = function(e) {
                    var t = void 0,
                        n = void 0;
                    if (Z) e = "<remove></remove>" + e;
                    else {
                        var r = Hh(e, /^[\r\n\t ]+/);
                        n = r && r[0]
                    }
                    "application/xhtml+xml" === ve && (e = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + e + "</body></html>");
                    var i = x ? x.createHTML(e) : e;
                    if (me === fe) try {
                        t = (new f).parseFromString(i, ve)
                    } catch (e) {}
                    if (!t || !t.documentElement) {
                        t = M.createDocument(me, "template", null);
                        try {
                            t.documentElement.innerHTML = ge ? "" : i
                        } catch (e) {}
                    }
                    var s = t.body || t.documentElement;
                    return e && n && s.insertBefore(o.createTextNode(n), s.childNodes[0] || null), me === fe ? N.call(t, G ? "html" : "body")[0] : G ? t.documentElement : s
                },
                De = function(e) {
                    return S.call(e.ownerDocument || e, e, c.SHOW_ELEMENT | c.SHOW_COMMENT | c.SHOW_TEXT, null, !1)
                },
                Ae = function(e) {
                    return "object" === (void 0 === a ? "undefined" : hf(a)) ? e instanceof a : e && "object" === (void 0 === e ? "undefined" : hf(e)) && "number" == typeof e.nodeType && "string" == typeof e.nodeName
                },
                Le = function(e, t, r) {
                    A[e] && Rh(A[e], function(e) {
                        e.call(n, t, r, we)
                    })
                },
                Ie = function(e) {
                    var t, r = void 0;
                    if (Le("beforeSanitizeElements", e, null), !((t = e) instanceof p || t instanceof h || "string" == typeof t.nodeName && "string" == typeof t.textContent && "function" == typeof t.removeChild && t.attributes instanceof d && "function" == typeof t.removeAttribute && "function" == typeof t.setAttribute && "string" == typeof t.namespaceURI && "function" == typeof t.insertBefore)) return Ee(e), !0;
                    if (Hh(e.nodeName, /[\u0080-\uFFFF]/)) return Ee(e), !0;
                    var o = be(e.nodeName);
                    if (Le("uponSanitizeElement", e, {
                            tagName: o,
                            allowedTags: z
                        }), !Ae(e.firstElementChild) && (!Ae(e.content) || !Ae(e.content.firstElementChild)) && jh(/<[/\w]/g, e.innerHTML) && jh(/<[/\w]/g, e.textContent)) return Ee(e), !0;
                    if ("select" === o && jh(/<template/i, e.innerHTML)) return Ee(e), !0;
                    if (!z[o] || $[o]) {
                        if (re && !se[o]) {
                            var i = w(e) || e.parentNode,
                                s = b(e) || e.childNodes;
                            if (s && i)
                                for (var a = s.length - 1; a >= 0; --a) i.insertBefore(v(s[a], !0), y(e))
                        }
                        return Ee(e), !0
                    }
                    return e instanceof l && ! function(e) {
                        var t = w(e);
                        t && t.tagName || (t = {
                            namespaceURI: fe,
                            tagName: "template"
                        });
                        var n = Fh(e.tagName),
                            r = Fh(t.tagName);
                        if (e.namespaceURI === he) return t.namespaceURI === fe ? "svg" === n : t.namespaceURI === pe ? "svg" === n && ("annotation-xml" === r || Ce[r]) : Boolean(Me[n]);
                        if (e.namespaceURI === pe) return t.namespaceURI === fe ? "math" === n : t.namespaceURI === he ? "math" === n && Te[r] : Boolean(Se[n]);
                        if (e.namespaceURI === fe) {
                            if (t.namespaceURI === he && !Te[r]) return !1;
                            if (t.namespaceURI === pe && !Ce[r]) return !1;
                            var o = Uh({}, ["title", "style", "font", "a", "script"]);
                            return !Se[n] && (o[n] || !Me[n])
                        }
                        return !1
                    }(e) ? (Ee(e), !0) : "noscript" !== o && "noembed" !== o || !jh(/<\/no(script|embed)/i, e.innerHTML) ? (K && 3 === e.nodeType && (r = e.textContent, r = zh(r, L, " "), r = zh(r, I, " "), e.textContent !== r && (Bh(n.removed, {
                        element: e.cloneNode()
                    }), e.textContent = r)), Le("afterSanitizeElements", e, null), !1) : (Ee(e), !0)
                },
                Re = function(e, t, n) {
                    if (ne && ("id" === t || "name" === t) && (n in o || n in ke)) return !1;
                    if (W && !_[t] && jh(R, t));
                    else if (U && jh(P, t));
                    else {
                        if (!V[t] || _[t]) return !1;
                        if (ue[t]);
                        else if (jh(H, zh(n, F, "")));
                        else if ("src" !== t && "xlink:href" !== t && "href" !== t || "script" === e || 0 !== qh(n, "data:") || !le[e])
                            if (J && !jh(B, zh(n, F, "")));
                            else if (n) return !1
                    }
                    return !0
                },
                Pe = function(e) {
                    var t = void 0,
                        r = void 0,
                        o = void 0,
                        i = void 0;
                    Le("beforeSanitizeAttributes", e, null);
                    var s = e.attributes;
                    if (s) {
                        var a = {
                            attrName: "",
                            attrValue: "",
                            keepAttr: !0,
                            allowedAttributes: V
                        };
                        for (i = s.length; i--;) {
                            var l = t = s[i],
                                c = l.name,
                                u = l.namespaceURI;
                            if (r = Vh(t.value), o = be(c), a.attrName = o, a.attrValue = r, a.keepAttr = !0, a.forceKeepAttr = void 0, Le("uponSanitizeAttribute", e, a), r = a.attrValue, !a.forceKeepAttr && (Ne(c, e), a.keepAttr))
                                if (jh(/\/>/i, r)) Ne(c, e);
                                else {
                                    K && (r = zh(r, L, " "), r = zh(r, I, " "));
                                    var d = be(e.nodeName);
                                    if (Re(d, o, r)) try {
                                        u ? e.setAttributeNS(u, c, r) : e.setAttribute(c, r), Ph(n.removed)
                                    } catch (e) {}
                                }
                        }
                        Le("afterSanitizeAttributes", e, null)
                    }
                },
                Be = function e(t) {
                    var n = void 0,
                        r = De(t);
                    for (Le("beforeSanitizeShadowDOM", t, null); n = r.nextNode();) Le("uponSanitizeShadowNode", n, null), Ie(n) || (n.content instanceof i && e(n.content), Pe(n));
                    Le("afterSanitizeShadowDOM", t, null)
                };
            return n.sanitize = function(e, o) {
                var s = void 0,
                    l = void 0,
                    c = void 0,
                    u = void 0,
                    d = void 0;
                if ((ge = !e) && (e = "\x3c!--\x3e"), "string" != typeof e && !Ae(e)) {
                    if ("function" != typeof e.toString) throw $h("toString is not a function");
                    if ("string" != typeof(e = e.toString())) throw $h("dirty is not a string, aborting")
                }
                if (!n.isSupported) {
                    if ("object" === hf(t.toStaticHTML) || "function" == typeof t.toStaticHTML) {
                        if ("string" == typeof e) return t.toStaticHTML(e);
                        if (Ae(e)) return t.toStaticHTML(e.outerHTML)
                    }
                    return e
                }
                if (X || xe(o), n.removed = [], "string" == typeof e && (oe = !1), oe);
                else if (e instanceof a) 1 === (l = (s = Oe("\x3c!----\x3e")).ownerDocument.importNode(e, !0)).nodeType && "BODY" === l.nodeName || "HTML" === l.nodeName ? s = l : s.appendChild(l);
                else {
                    if (!Q && !K && !G && -1 === e.indexOf("<")) return x && te ? x.createHTML(e) : e;
                    if (!(s = Oe(e))) return Q ? null : C
                }
                s && Z && Ee(s.firstChild);
                for (var p = De(oe ? e : s); c = p.nextNode();) 3 === c.nodeType && c === u || Ie(c) || (c.content instanceof i && Be(c.content), Pe(c), u = c);
                if (u = null, oe) return e;
                if (Q) {
                    if (Y)
                        for (d = E.call(s.ownerDocument); s.firstChild;) d.appendChild(s.firstChild);
                    else d = s;
                    return ee && (d = O.call(r, d, !0)), d
                }
                var h = G ? s.outerHTML : s.innerHTML;
                return K && (h = zh(h, L, " "), h = zh(h, I, " ")), x && te ? x.createHTML(h) : h
            }, n.setConfig = function(e) {
                xe(e), X = !0
            }, n.clearConfig = function() {
                we = null, X = !1
            }, n.isValidAttribute = function(e, t, n) {
                we || xe({});
                var r = be(e),
                    o = be(t);
                return Re(r, o, n)
            }, n.addHook = function(e, t) {
                "function" == typeof t && (A[e] = A[e] || [], Bh(A[e], t))
            }, n.removeHook = function(e) {
                A[e] && Ph(A[e])
            }, n.removeHooks = function(e) {
                A[e] && (A[e] = [])
            }, n.removeAllHooks = function() {
                A = {}
            }, n
        }(),
        vf = ["iframe", "embed"],
        yf = [];

    function bf(e) {
        zs(vf, e) && yf.push(e.toLowerCase())
    }

    function wf(e, t) {
        return gf.sanitize(e, $i({
            ADD_TAGS: yf,
            ADD_ATTR: ["rel", "target", "hreflang", "type"],
            FORBID_TAGS: ["input", "script", "textarea", "form", "button", "select", "meta", "style", "link", "title", "object", "base"]
        }, t))
    }

    function kf(e, t) {
        return e.literal.replace(new RegExp("(<\\s*" + t + "[^>]*>)|(</" + t + "\\s*[>])", "ig"), "").trim()
    }

    function xf(e) {
        var t = (e = e.match(Wa)[0]).match(new RegExp($a, "g"));
        return t ? t.reduce(function(e, t) {
            var n = t.trim().split("="),
                r = n[0],
                o = n.slice(1);
            return o.length && (e[r] = o.join("=").replace(/'|"/g, "").trim()), e
        }, {}) : {}
    }

    function Cf(e) {
        return na(e.attributes).reduce(function(e, t) {
            return e[t.nodeName] = t.nodeValue, e
        }, {})
    }

    function Tf(e, t, n, r) {
        var o = r.getToDOMNode(t)(e),
            i = n(o.outerHTML),
            s = document.createElement("div");
        return s.innerHTML = i, {
            dom: o = s.firstChild,
            htmlAttrs: Cf(o)
        }
    }
    var Mf = {
            htmlBlock: function(e, t, n) {
                return {
                    atom: !0,
                    content: "block+",
                    group: "block",
                    attrs: {
                        htmlAttrs: {
                            default: {}
                        },
                        childrenHTML: {
                            default: ""
                        },
                        htmlBlock: {
                            default: !0
                        }
                    },
                    parseDOM: [{
                        tag: e,
                        getAttrs: function(e) {
                            return {
                                htmlAttrs: Cf(e),
                                childrenHTML: e.innerHTML
                            }
                        }
                    }],
                    toDOM: function(r) {
                        var o = Tf(r, e, t, n),
                            i = o.dom,
                            s = o.htmlAttrs;
                        return s.class = s.class ? s.class + " html-block" : "html-block", _i([e, s], na(i.childNodes))
                    }
                }
            },
            htmlInline: function(e, t, n) {
                return {
                    attrs: {
                        htmlAttrs: {
                            default: {}
                        },
                        htmlInline: {
                            default: !0
                        }
                    },
                    parseDOM: [{
                        tag: e,
                        getAttrs: function(e) {
                            return {
                                htmlAttrs: Cf(e)
                            }
                        }
                    }],
                    toDOM: function(r) {
                        var o = Tf(r, e, t, n).htmlAttrs;
                        return [e, o, 0]
                    }
                }
            }
        },
        Sf = /^\s*<\s*\//,
        Ef = {
            paragraph: function(e, t) {
                var n = t.entering,
                    r = t.origin;
                return t.options.nodeId ? {
                    type: n ? "openTag" : "closeTag",
                    outerNewLine: !0,
                    tagName: "p"
                } : r()
            },
            softbreak: function(e) {
                return {
                    type: "html",
                    content: e.prev && "htmlInline" === e.prev.type && /<br ?\/?>/.test(e.prev.literal) ? "\n" : "<br>\n"
                }
            },
            item: function(e, t) {
                if (t.entering) {
                    var n = {},
                        r = [];
                    return e.listData.task && (n["data-task"] = "", r.push("task-list-item"), e.listData.checked && (r.push("checked"), n["data-task-checked"] = "")), {
                        type: "openTag",
                        tagName: "li",
                        classNames: r,
                        attributes: n,
                        outerNewLine: !0
                    }
                }
                return {
                    type: "closeTag",
                    tagName: "li",
                    outerNewLine: !0
                }
            },
            code: function(e) {
                return [{
                    type: "openTag",
                    tagName: "code",
                    attributes: {
                        "data-backticks": String(e.tickCount)
                    }
                }, {
                    type: "text",
                    content: e.literal
                }, {
                    type: "closeTag",
                    tagName: "code"
                }]
            },
            codeBlock: function(e) {
                var t = e,
                    n = t.fenceLength,
                    r = t.info,
                    o = r ? r.split(/\s+/) : [],
                    i = [],
                    s = {};
                if (n > 3 && (s["data-backticks"] = n), o.length > 0 && o[0].length > 0) {
                    var a = o[0];
                    i.push("lang-" + a), s["data-language"] = a
                }
                return [{
                    type: "openTag",
                    tagName: "pre",
                    classNames: i
                }, {
                    type: "openTag",
                    tagName: "code",
                    attributes: s
                }, {
                    type: "text",
                    content: e.literal
                }, {
                    type: "closeTag",
                    tagName: "code"
                }, {
                    type: "closeTag",
                    tagName: "pre"
                }]
            },
            customInline: function(e, t) {
                var n = t.origin,
                    r = t.entering,
                    o = t.skipChildren,
                    i = e.info;
                return -1 !== i.indexOf("widget") && r ? (o(), [{
                    type: "openTag",
                    tagName: "span",
                    classNames: ["tui-widget"]
                }, {
                    type: "html",
                    content: Oa(i, Ia(e)).outerHTML
                }, {
                    type: "closeTag",
                    tagName: "span"
                }]) : n()
            }
        };

    function Nf(e, t) {
        var n = $i({}, Ef);
        return e && (n.link = function(t, n) {
            var r = n.entering,
                o = (0, n.origin)();
            return r && (o.attributes = $i($i({}, o.attributes), e)), o
        }), t && Object.keys(t).forEach(function(e) {
            var r = n[e],
                o = t[e];
            r && bl(o) ? n[e] = function(e, t) {
                var n = $i({}, t);
                return n.origin = function() {
                    return r(e, t)
                }, o(e, n)
            } : zs(["htmlBlock", "htmlInline"], e) && !bl(o) ? n[e] = function(e, t) {
                var n = e.literal.match(Wa);
                if (n) {
                    var r = n[0],
                        i = n[1],
                        s = n[3],
                        a = (i || s).toLowerCase(),
                        l = o[a],
                        c = kf(e, a);
                    if (l) {
                        var u = $i({}, e);
                        return u.attrs = xf(r), u.childrenHTML = c, u.type = a, t.entering = !Sf.test(e.literal), l(u, t)
                    }
                }
                return t.origin()
            } : n[e] = o
        }), n
    }
    var Of = ["list", "item", "blockQuote"],
        Df = ["UL", "OL", "BLOCKQUOTE"];

    function Af(e, t) {
        var n, r = e.child(t);
        return !r.childCount || 1 === r.childCount && !(null === (n = r.firstChild.text) || void 0 === n ? void 0 : n.trim())
    }

    function Lf(e, t, n) {
        var r = ca(t) - 1,
            o = ua(t) - 1,
            i = n[r].getBoundingClientRect(),
            s = n[o].offsetTop - n[r].offsetTop + n[o].clientHeight;
        return {
            height: s <= 0 ? n[r].clientHeight : s + If(e, n, Math.min(o + 1, e.childCount - 1)),
            rect: i
        }
    }

    function If(e, t, n) {
        for (var r = e.childCount - 1, o = 0; n <= r && Af(e, n);) o += t[n].clientHeight, n += 1;
        return o
    }

    function Rf(e, t) {
        for (var n = 0; e && e !== t && (zs(Df, e.tagName) || (n += e.offsetTop), e.offsetParent !== t.offsetParent);) e = e.parentElement;
        return n
    }

    function Pf(e, t, n) {
        return e && t > n + e.offsetTop ? Pf(e.nextElementSibling, t, n) || e : null
    }

    function Bf(e, t) {
        for (var n = e.querySelector('[data-nodeid="' + t.id + '"]'); !n || ha(t);) t = t.parent, n = e.querySelector('[data-nodeid="' + t.id + '"]');
        return function(e) {
            for (var t = e.mdNode, n = e.el;
                (zs(Of, t.type) || "table" === t.type) && t.firstChild;) t = t.firstChild, n = n.firstElementChild;
            return {
                mdNode: t,
                el: n
            }
        }({
            mdNode: t,
            el: n
        })
    }
    var Ff = {};

    function Hf(e) {
        e && (delete Ff[Number(e.getAttribute("data-nodeid"))], na(e.children).forEach(function(e) {
            Hf(e)
        }))
    }
    var zf = Qa("md-preview-highlight"),
        qf = function() {
            function e(e, t) {
                var n = document.createElement("div");
                this.el = n, this.eventEmitter = e, this.isViewer = !!t.isViewer, this.el.className = Qa("md-preview");
                var r = t.linkAttributes,
                    o = t.customHTMLRenderer,
                    i = t.sanitizer,
                    s = t.highlight,
                    a = void 0 !== s && s;
                this.renderer = new kh({
                    gfm: !0,
                    nodeId: !0,
                    convertors: Nf(r, o)
                }), this.cursorNodeId = null, this.sanitizer = i, this.initEvent(a), this.initContentSection(), this.isViewer && (this.previewContent.style.overflowWrap = "break-word")
            }
            return e.prototype.initContentSection = function() {
                this.previewContent = rl('<div class="' + Qa("contents") + '"></div>'), this.isViewer || this.el.appendChild(this.previewContent)
            }, e.prototype.toggleActive = function(e) {
                nl(this.el, "active", e)
            }, e.prototype.initEvent = function(e) {
                var t = this;
                this.eventEmitter.listen("updatePreview", this.update.bind(this)), this.isViewer || (e && (this.eventEmitter.listen("changeToolbarState", function(e) {
                    var n = e.mdNode,
                        r = e.cursorPos;
                    t.updateCursorNode(n, r)
                }), this.eventEmitter.listen("blur", function() {
                    t.removeHighlight()
                })), mu(this.el, "scroll", function(e) {
                    t.eventEmitter.emit("scroll", "preview", function(e, t) {
                        for (var n = t, r = null; n;) {
                            var o = n.firstElementChild;
                            if (!o) break;
                            r = n, n = Pf(o, e, Rf(n, t))
                        }
                        var i = n || r;
                        return i === t ? null : i
                    }(e.target.scrollTop, t.previewContent))
                }), this.eventEmitter.listen("changePreviewTabPreview", function() {
                    return t.toggleActive(!0)
                }), this.eventEmitter.listen("changePreviewTabWrite", function() {
                    return t.toggleActive(!1)
                }))
            }, e.prototype.removeHighlight = function() {
                if (this.cursorNodeId) {
                    var e = this.getElementByNodeId(this.cursorNodeId);
                    e && xs(e, zf)
                }
            }, e.prototype.updateCursorNode = function(e, t) {
                e && ("tableRow" === (e = ya(e, function(e) {
                    return ! function(e) {
                        switch (e.type) {
                            case "code":
                            case "text":
                            case "emph":
                            case "strong":
                            case "strike":
                            case "link":
                            case "image":
                            case "htmlInline":
                            case "linebreak":
                            case "softbreak":
                            case "customInline":
                                return !0;
                            default:
                                return !1
                        }
                    }(e)
                })).type ? e = function(e, t) {
                    for (var n = e.firstChild; n && n.next && !(da(n.next) > t + 1);) n = n.next;
                    return n
                }(e, t[1]) : "tableBody" === e.type && (e = null));
                var n = e ? e.id : null;
                if (this.cursorNodeId !== n) {
                    var r = this.getElementByNodeId(this.cursorNodeId),
                        o = this.getElementByNodeId(n);
                    r && xs(r, zf), o && vs(o, zf), this.cursorNodeId = n
                }
            }, e.prototype.getElementByNodeId = function(e) {
                return e ? this.previewContent.querySelector('[data-nodeid="' + e + '"]') : null
            }, e.prototype.update = function(e) {
                var t = this;
                e.forEach(function(e) {
                    return t.replaceRangeNodes(e)
                }), this.eventEmitter.emit("afterPreviewRender", this)
            }, e.prototype.replaceRangeNodes = function(e) {
                var t = this,
                    n = e.nodes,
                    r = e.removedNodeRange,
                    o = this.previewContent,
                    i = this.eventEmitter.emitReduce("beforePreviewRender", this.sanitizer(n.map(function(e) {
                        return t.renderer.render(e)
                    }).join("")));
                if (r) {
                    var s = r.id,
                        a = s[0],
                        l = s[1],
                        c = this.getElementByNodeId(a),
                        u = this.getElementByNodeId(l);
                    if (c) {
                        c.insertAdjacentHTML("beforebegin", i);
                        for (var d = c; d && d !== u;) {
                            var p = d.nextElementSibling;
                            tl(d), Hf(d), d = p
                        }(null == d ? void 0 : d.parentNode) && (tl(d), Hf(d))
                    }
                } else o.insertAdjacentHTML("afterbegin", i)
            }, e.prototype.getRenderer = function() {
                return this.renderer
            }, e.prototype.destroy = function() {
                uu(this.el, "scroll"), this.el = null
            }, e.prototype.getElement = function() {
                return this.el
            }, e.prototype.getHTML = function() {
                return ll(this.previewContent.innerHTML)
            }, e.prototype.setHTML = function(e) {
                this.previewContent.innerHTML = e
            }, e.prototype.setHeight = function(e) {
                rs(this.el, {
                    height: e + "px"
                })
            }, e.prototype.setMinHeight = function(e) {
                rs(this.el, {
                    minHeight: e + "px"
                })
            }, e
        }();

    function Vf(e, t) {
        for (var n = e.depth; n;) {
            var r = e.node(n);
            if (t(r, n)) return {
                node: r,
                depth: n,
                offset: n > 0 ? e.before(n) : 0
            };
            n -= 1
        }
        return null
    }

    function jf(e) {
        return !!Vf(e, function(e) {
            var t = e.type;
            return "listItem" === t.name || "bulletList" === t.name || "orderedList" === t.name
        })
    }

    function $f(e) {
        return !!Vf(e, function(e) {
            var t = e.type;
            return "tableHeadCell" === t.name || "tableBodyCell" === t.name
        })
    }

    function _f(e) {
        return Vf(e, function(e) {
            return "listItem" === e.type.name
        })
    }

    function Uf(e) {
        return {
            tag: e,
            getAttrs: function(e) {
                var t = e.getAttribute("data-raw-html");
                return $i({}, t && {
                    rawHTML: t
                })
            }
        }
    }

    function Wf(e) {
        return Object.keys(e).reduce(function(t, n) {
            return "rawHTML" !== n && e[n] && (t[n = "className" === n ? "class" : n] = e[n]), t
        }, {})
    }

    function Jf(e) {
        return {
            tag: e,
            getAttrs: function(e) {
                return ["rawHTML", "colspan", "rowspan", "extended"].reduce(function(t, n) {
                    var r = "rawHTML" === n ? "data-raw-html" : n,
                        o = e.getAttribute(r);
                    return o && (t[n] = zs(["rawHTML", "extended"], n) ? o : Number(o)), t
                }, {})
            }
        }
    }

    function Kf(e) {
        var t = e.htmlAttrs,
            n = e.classNames;
        return $i($i({}, t), {
            class: n ? n.join(" ") : null
        })
    }

    function Gf(e, t, n, r) {
        var o = t.$from,
            i = t.$to,
            s = t.depth,
            a = t,
            c = !1;
        if (s >= 2 && o.node(s - 1).type.compatibleContent(n) && 0 === t.startIndex && o.index(s - 1)) {
            var u = e.doc.resolve(t.start - 2);
            a = new D(u, u, s), t.endIndex < t.parent.childCount && (t = new D(o, e.doc.resolve(i.end(s)), s)), c = !0
        }
        var d = function(e, t, n, r) {
            var o = function(e, t) {
                    var n = e.parent,
                        r = e.startIndex,
                        o = e.endIndex,
                        i = n.contentMatchAt(r).findWrapping(t);
                    if (i) {
                        var s = i.length ? i[0] : t;
                        return n.canReplaceWith(r, o, s) ? i : null
                    }
                    return null
                }(e, n),
                i = function(e, t) {
                    var n = e.parent,
                        r = e.startIndex,
                        o = e.endIndex,
                        i = n.child(r),
                        s = t.contentMatch.findWrapping(i.type);
                    if (s) {
                        for (var a = (s.length ? s[s.length - 1] : t).contentMatch, l = r; a && l < o; l += 1) a = a.matchType(n.child(l).type);
                        if (a && a.validEnd) return s
                    }
                    return null
                }(t, n);
            if (o && i) {
                var s = o.map(function(e) {
                        return {
                            type: e
                        }
                    }),
                    a = i.map(function(e) {
                        return {
                            type: e,
                            attrs: r
                        }
                    });
                return s.concat({
                    type: n
                }).concat(a)
            }
            return null
        }(a, t, n, r);
        return d ? function(e, t, n, r, o) {
            for (var i = t.start, s = t.end, a = t.startIndex, c = t.endIndex, u = t.parent, d = l.empty, p = n.length - 1; p >= 0; p -= 1) d = l.from(n[p].type.create(n[p].attrs, d));
            e.step(new Oe(i - (r ? 2 : 0), s, i, s, new f(d, 0, 0), n.length, !0));
            var h = 0;
            for (p = 0; p < n.length; p += 1)
                if (n[p].type === o) {
                    h = p + 1;
                    break
                } for (var m = n.length - h, g = i + n.length - (r ? 2 : 0), v = (p = a, c); p < v; p += 1) !(p === a) && Fe(e.doc, g, m) && (e.split(g, m), g += 2 * m), g += u.child(p).nodeSize;
            return e
        }(e, t, d, c, n) : e
    }

    function Xf(e, t) {
        for (var n = e.resolve(t);
            "paragraph" !== n.node().type.name;) t -= 2, n = e.resolve(t);
        return _f(n)
    }

    function Zf(e) {
        return function(t, n) {
            var r = t.selection,
                o = t.tr,
                i = r.$from,
                s = r.$to,
                a = i.blockRange(s);
            if (a) {
                var l = jf(i) ? function(e, t, n) {
                    var r = t.$from,
                        o = t.$to,
                        i = _f(r),
                        s = _f(o);
                    if (i && s)
                        for (; s;) {
                            var a = s.offset,
                                l = s.node,
                                c = s.depth;
                            l.attrs.task && e.setNodeMarkup(a, null, {
                                task: !1,
                                checked: !1
                            });
                            var u = e.doc.resolve(a);
                            if (u.parent.type !== n) {
                                var d = u.before(c - 1);
                                e.setNodeMarkup(d, n)
                            }
                            if (a === i.offset) break;
                            s = Xf(e.doc, a)
                        }
                    return e
                }(o, a, e) : Gf(o, a, e);
                return n(l), !0
            }
            return !1
        }
    }

    function Qf() {
        return function(e, t) {
            var n = e.selection,
                r = e.tr,
                o = e.schema,
                i = n.$from,
                s = n.$to,
                a = i.blockRange(s);
            if (a) {
                var l = jf(i) ? function(e, t) {
                    var n = t.$from,
                        r = t.$to,
                        o = _f(n),
                        i = _f(r);
                    if (o && i)
                        for (; i;) {
                            var s = i.offset,
                                a = {
                                    task: !i.node.attrs.task,
                                    checked: !1
                                };
                            if (e.setNodeMarkup(s, null, a), s === o.offset) break;
                            i = Xf(e.doc, s)
                        }
                    return e
                }(r, a) : Gf(r, a, o.nodes.bulletList, {
                    task: !0
                });
                return t(l), !0
            }
            return !1
        }
    }

    function Yf() {
        return {
            indent: function() {
                return function(e, t) {
                    var n, r = e.selection,
                        o = e.schema,
                        i = r.$from,
                        s = r.$to;
                    return !(!i.blockRange(s) || !jf(i)) && (n = o.nodes.listItem, function(e, t) {
                        var r = e.tr,
                            o = e.selection,
                            i = o.$from,
                            s = o.$to,
                            a = i.blockRange(s, function(e) {
                                var t = e.childCount,
                                    r = e.firstChild;
                                return !!t && r.type === n
                            });
                        if (a && a.startIndex > 0) {
                            var c = a.parent,
                                u = c.child(a.startIndex - 1);
                            if (u.type !== n) return !1;
                            var d = u.lastChild && u.lastChild.type === c.type,
                                p = d ? l.from(n.create()) : null,
                                h = new f(l.from(n.create(null, l.from(c.type.create(null, p)))), d ? 3 : 1, 0),
                                m = a.start,
                                g = a.end;
                            return r.step(new Oe(m - (d ? 3 : 1), g, m, g, h, 1, !0)), t(r), !0
                        }
                        return !1
                    })(e, t)
                }
            },
            outdent: function() {
                return function(e, t) {
                    var n, r = e.selection,
                        o = e.schema,
                        i = r.$from,
                        s = r.$to;
                    return !(!i.blockRange(s) || !jf(i)) && (n = o.nodes.listItem, function(e, t) {
                        var r = e.tr,
                            o = e.selection,
                            i = o.$from,
                            s = o.$to,
                            a = i.blockRange(s, function(e) {
                                var t = e.childCount,
                                    r = e.firstChild;
                                return !!t && r.type === n
                            });
                        if (a) {
                            var c = i.node(a.depth - 1).type === n ? function(e, t, n) {
                                var r = t.$from,
                                    o = t.$to,
                                    i = t.end,
                                    s = t.depth,
                                    a = t.parent,
                                    c = o.end(s);
                                return i < c && (e.step(new Oe(i - 1, c, i, c, new f(l.from(n.create(null, a.copy())), 1, 0), 1, !0)), t = new D(e.doc.resolve(r.pos), e.doc.resolve(c), s)), e.lift(t, Ie(t)), e
                            }(r, a, n) : function(e, t) {
                                for (var n = t.parent, r = t.end, o = t.endIndex - 1, i = t.startIndex; o > i; o -= 1) r -= n.child(o).nodeSize, e.delete(r - 1, r + 1);
                                var s = e.doc.resolve(t.start),
                                    a = s.nodeAfter,
                                    c = 0 === t.startIndex,
                                    u = t.endIndex === n.childCount,
                                    d = s.node(-1),
                                    p = s.index(-1),
                                    h = d.canReplace(p + (c ? 0 : 1), p + 1, null == a ? void 0 : a.content.append(u ? l.empty : l.from(n)));
                                if (a && h) {
                                    var m = s.pos,
                                        g = m + a.nodeSize;
                                    e.step(new Oe(m - (c ? 1 : 0), g + (u ? 1 : 0), m + 1, g - 1, new f((c ? l.empty : l.from(n.copy(l.empty))).append(u ? l.empty : l.from(n.copy(l.empty))), c ? 0 : 1, u ? 0 : 1), c ? 0 : 1))
                                }
                                return e
                            }(r, a);
                            return t(c), !0
                        }
                        return !1
                    })(e, t)
                }
            }
        }
    }
    var em = new Map,
        tm = function() {
            function e(e, t, n, r) {
                this.table = e, this.tableRows = t, this.tableStartPos = n, this.rowInfo = r
            }
            return e.create = function(t) {
                var n = Vf(t, function(e) {
                    return "table" === e.type.name
                });
                if (n) {
                    var r = n.node,
                        o = n.depth,
                        i = n.offset,
                        s = em.get(r);
                    if ((null == s ? void 0 : s.tableStartPos) === i + 1) return s;
                    var a = [],
                        l = t.start(o),
                        c = r.child(0),
                        u = r.child(1),
                        d = nm(c, l),
                        p = nm(u, l + c.nodeSize);
                    c.forEach(function(e) {
                        return a.push(e)
                    }), u.forEach(function(e) {
                        return a.push(e)
                    });
                    var h = new e(r, a, l, d.concat(p));
                    return em.set(r, h), h
                }
                return null
            }, Object.defineProperty(e.prototype, "totalRowCount", {
                get: function() {
                    return this.rowInfo.length
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(e.prototype, "totalColumnCount", {
                get: function() {
                    return this.rowInfo[0].length
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(e.prototype, "tableStartOffset", {
                get: function() {
                    return this.tableStartPos
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(e.prototype, "tableEndOffset", {
                get: function() {
                    return this.tableStartPos + this.table.nodeSize - 1
                },
                enumerable: !1,
                configurable: !0
            }), e.prototype.getCellInfo = function(e, t) {
                return this.rowInfo[e][t]
            }, e.prototype.posAt = function(e, t) {
                for (var n = 0, r = this.tableStartPos;; n += 1) {
                    var o = r + this.tableRows[n].nodeSize;
                    if (n === e) {
                        for (var i = t; i < this.totalColumnCount && this.rowInfo[n][i].offset < r;) i += 1;
                        return i === this.totalColumnCount ? o : this.rowInfo[n][i].offset
                    }
                    r = o
                }
            }, e.prototype.getNodeAndPos = function(e, t) {
                var n = this.rowInfo[e][t];
                return {
                    node: this.table.nodeAt(n.offset - this.tableStartOffset),
                    pos: n.offset
                }
            }, e.prototype.extendedRowspan = function(e, t) {
                return !1
            }, e.prototype.extendedColspan = function(e, t) {
                return !1
            }, e.prototype.getRowspanCount = function(e, t) {
                return 0
            }, e.prototype.getColspanCount = function(e, t) {
                return 0
            }, e.prototype.decreaseColspanCount = function(e, t) {
                return 0
            }, e.prototype.decreaseRowspanCount = function(e, t) {
                return 0
            }, e.prototype.getColspanStartInfo = function(e, t) {
                return null
            }, e.prototype.getRowspanStartInfo = function(e, t) {
                return null
            }, e.prototype.getCellStartOffset = function(e, t) {
                var n = this.rowInfo[e][t].offset;
                return this.extendedRowspan(e, t) ? this.posAt(e, t) : n
            }, e.prototype.getCellEndOffset = function(e, t) {
                var n = this.rowInfo[e][t],
                    r = n.offset,
                    o = n.nodeSize;
                return this.extendedRowspan(e, t) ? this.posAt(e, t) : r + o
            }, e.prototype.getCellIndex = function(e) {
                for (var t = 0; t < this.totalRowCount; t += 1)
                    for (var n = this.rowInfo[t], r = 0; r < this.totalColumnCount; r += 1)
                        if (n[r].offset + 1 > e.pos) return [t, r];
                return [0, 0]
            }, e.prototype.getRectOffsets = function(e, t) {
                var n, r, o;
                void 0 === t && (t = e), e.pos > t.pos && (e = (n = [t, e])[0], t = n[1]);
                var i = this.getCellIndex(e),
                    s = i[0],
                    a = i[1],
                    l = this.getCellIndex(t),
                    c = l[0],
                    u = l[1];
                return s = (r = ea(s, c))[0], c = r[1], a = (o = ea(a, u))[0], u = o[1], this.getSpannedOffsets({
                    startRowIdx: s,
                    startColIdx: a,
                    endRowIdx: c,
                    endColIdx: u
                })
            }, e.prototype.getSpannedOffsets = function(e) {
                return e
            }, e
        }(),
        nm = function(e, t) {
            var n = [];
            return e.forEach(function(e, r) {
                var o = {
                    rowspanMap: {},
                    colspanMap: {},
                    length: 0
                };
                e.forEach(function(e, n) {
                    for (var i = e.nodeSize, s = 0; o[s];) s += 1;
                    o[s] = {
                        offset: t + r + n + 2,
                        nodeSize: i
                    }, o.length += 1
                }), n.push(o)
            }), n
        };

    function rm(e, t) {
        return Ys(tm.prototype, e), nm = t, tm
    }
    var om = function(e) {
        function t(t, n) {
            void 0 === n && (n = t);
            var r = this,
                o = t.node(0),
                i = tm.create(t),
                s = i.getRectOffsets(t, n),
                a = function(e, t, n) {
                    for (var r = n.startRowIdx, o = n.startColIdx, i = n.endRowIdx, s = n.endColIdx, a = [], l = r; l <= i; l += 1)
                        for (var c = o; c <= s; c += 1) {
                            var u = t.getCellInfo(l, c),
                                d = u.offset,
                                p = u.nodeSize;
                            a.push(new nt(e.resolve(d + 1), e.resolve(d + p - 1)))
                        }
                    return a
                }(o, i, s);
            return (r = e.call(this, a[0].$from, a[0].$to, a) || this).startCell = t, r.endCell = n, r.offsetMap = i, r.isCellSelection = !0, r.visible = !1, r
        }
        return ji(t, e), t.prototype.map = function(e, n) {
            var r = this.startCell.pos,
                o = this.endCell.pos,
                i = e.resolve(n.map(r)),
                s = e.resolve(n.map(o)),
                a = tm.create(i);
            if (this.offsetMap.totalColumnCount > a.totalColumnCount || this.offsetMap.totalRowCount > a.totalRowCount) {
                var l = {
                        tableBody: 1,
                        tableRow: 2,
                        tableCell: 3,
                        paragraph: 4
                    } [s.parent.type.name],
                    c = s.end(s.depth - l),
                    u = Math.min(c - 4, s.pos);
                return it.create(e, u)
            }
            return new t(i, s)
        }, t.prototype.eq = function(e) {
            return e instanceof t && e.startCell.pos === this.startCell.pos && e.endCell.pos === this.endCell.pos
        }, t.prototype.content = function() {
            for (var e = this.startCell.node(-2), t = this.startCell.start(-2), n = e.child(1).firstChild, r = e.child(0).type.create(), o = e.child(1).type.create(), i = tm.create(this.startCell), s = i.getRectOffsets(this.startCell, this.endCell), a = s.startRowIdx, c = s.startColIdx, u = s.endRowIdx, d = s.endColIdx, p = !1, h = a; h <= u; h += 1) {
                for (var m = [], g = c; g <= d; g += 1) {
                    var v = i.getCellInfo(h, g).offset,
                        y = e.nodeAt(v - t);
                    y && (p = "tableHeadCell" === y.type.name, i.extendedRowspan(h, g) || i.extendedColspan(h, g) ? m.push(y.type.create({
                        extended: !0
                    })) : m.push(y.copy(y.content)))
                }
                var b = n.copy(l.from(m)),
                    w = p ? r : o;
                w.content = w.content.append(l.from(b))
            }
            return new f(function(e, t) {
                var n = [];
                return e.childCount && n.push(e), t.childCount && n.push(t), l.from(n)
            }(r, o), 1, 1)
        }, t.prototype.toJSON = function() {
            return JSON.stringify(this)
        }, t
    }(tt);

    function im(e, t, n, r) {
        for (var o = n.nodes, i = o.tableRow, s = o.tableBodyCell, a = o.paragraph, l = [], c = 0; c < e; c += 1) {
            for (var u = [], d = 0; d < t; d += 1) {
                var p = r && r[c * t + d],
                    h = a.create(null, p ? n.text(p) : []);
                u.push(s.create(null, h))
            }
            l.push(i.create(null, u))
        }
        return l
    }

    function sm(e, t, n, r) {
        void 0 === r && (r = null);
        for (var o = n.nodes, i = o.tableHeadCell, s = o.tableBodyCell, a = o.paragraph, l = 0 === t ? i : s, c = [], u = 0; u < e; u += 1) c.push(l.create(r, a.create()));
        return c
    }

    function am(e, t) {
        for (; e && e !== t;) {
            if ("TD" === e.nodeName || "TH" === e.nodeName) return e;
            e = e.parentNode
        }
        return null
    }

    function lm(e) {
        return Vf(e, function(e) {
            var t = e.type;
            return "tableHeadCell" === t.name || "tableBodyCell" === t.name
        })
    }

    function cm(e) {
        if (e instanceof it) {
            var t = e.$anchor,
                n = lm(t);
            if (n) {
                var r = t.node(0).resolve(t.before(n.depth));
                return {
                    anchor: r,
                    head: r
                }
            }
        }
        var o = e;
        return {
            anchor: o.startCell,
            head: o.endCell
        }
    }

    function um(e) {
        var t;
        if (e.size) {
            var n = e.content,
                r = e.openStart,
                o = e.openEnd;
            if (1 !== n.childCount) return null;
            for (; 1 === n.childCount && (r > 0 && o > 0 || "table" === (null === (t = n.firstChild) || void 0 === t ? void 0 : t.type.name));) r -= 1, o -= 1, n = n.firstChild.content;
            if ("tableHead" === n.firstChild.type.name || "tableBody" === n.firstChild.type.name) return n
        }
        return null
    }

    function dm(e) {
        var t = e.startRowIdx,
            n = e.startColIdx;
        return {
            rowCount: e.endRowIdx - t + 1,
            columnCount: e.endColIdx - n + 1
        }
    }

    function pm(e, t) {
        return $i($i({}, e.attrs), t)
    }
    var hm = new Ct("cellSelection"),
        fm = function() {
            function e(e) {
                this.view = e, this.handlers = {
                    mousedown: this.handleMousedown.bind(this),
                    mousemove: this.handleMousemove.bind(this),
                    mouseup: this.handleMouseup.bind(this)
                }, this.startCellPos = null, this.init()
            }
            return e.prototype.init = function() {
                this.view.dom.addEventListener("mousedown", this.handlers.mousedown)
            }, e.prototype.handleMousedown = function(e) {
                var t = am(e.target, this.view.dom);
                if (2 !== e.button) {
                    if (t) {
                        var n = this.getCellPos(e);
                        n && (this.startCellPos = n), this.bindEvent()
                    }
                } else e.preventDefault()
            }, e.prototype.handleMousemove = function(e) {
                var t, n = hm.getState(this.view.state),
                    r = this.getCellPos(e),
                    o = this.startCellPos;
                n ? t = this.view.state.doc.resolve(n) : o !== r && (t = o), t && o && r && this.setCellSelection(o, r)
            }, e.prototype.handleMouseup = function() {
                this.startCellPos = null, this.unbindEvent(), null !== hm.getState(this.view.state) && this.view.dispatch(this.view.state.tr.setMeta(hm, -1))
            }, e.prototype.bindEvent = function() {
                var e = this.view.dom;
                e.addEventListener("mousemove", this.handlers.mousemove), e.addEventListener("mouseup", this.handlers.mouseup)
            }, e.prototype.unbindEvent = function() {
                var e = this.view.dom;
                e.removeEventListener("mousemove", this.handlers.mousemove), e.removeEventListener("mouseup", this.handlers.mouseup)
            }, e.prototype.getCellPos = function(e) {
                var t = e.clientX,
                    n = e.clientY,
                    r = this.view.posAtCoords({
                        left: t,
                        top: n
                    });
                if (r) {
                    var o = this.view.state.doc,
                        i = o.resolve(r.pos),
                        s = lm(i);
                    if (s) {
                        var a = i.before(s.depth);
                        return o.resolve(a)
                    }
                }
                return null
            }, e.prototype.setCellSelection = function(e, t) {
                var n = this.view.state,
                    r = n.selection,
                    o = n.tr,
                    i = null === hm.getState(this.view.state),
                    s = new om(e, t);
                if (i || !r.eq(s)) {
                    var a = o.setSelection(s);
                    i && a.setMeta(hm, t.pos), this.view.dispatch(a)
                }
            }, e.prototype.destroy = function() {
                this.view.dom.removeEventListener("mousedown", this.handlers.mousedown)
            }, e
        }(),
        mm = Qa("cell-selected");

    function gm(e) {
        var t = e.selection,
            n = e.doc;
        if (t instanceof om) {
            var r = [];
            return t.ranges.forEach(function(e) {
                var t = e.$from,
                    n = e.$to;
                r.push(io.node(t.pos - 1, n.pos + 1, {
                    class: mm
                }))
            }), lo.create(n, r)
        }
        return null
    }
    var vm = function() {
            function e() {
                this.keys = [], this.values = []
            }
            return e.prototype.getKeyIndex = function(e) {
                return ss(e, this.keys)
            }, e.prototype.get = function(e) {
                return this.values[this.getKeyIndex(e)]
            }, e.prototype.set = function(e, t) {
                var n = this.getKeyIndex(e);
                return n > -1 ? this.values[n] = t : (this.keys.push(e), this.values.push(t)), this
            }, e.prototype.has = function(e) {
                return this.getKeyIndex(e) > -1
            }, e.prototype.delete = function(e) {
                var t = this.getKeyIndex(e);
                return t > -1 && (this.keys.splice(t, 1), this.values.splice(t, 1), !0)
            }, e.prototype.forEach = function(e, t) {
                var n = this;
                void 0 === t && (t = this), this.values.forEach(function(r, o) {
                    r && n.keys[o] && e.call(t, r, n.keys[o], n)
                })
            }, e.prototype.clear = function() {
                this.keys = [], this.values = []
            }, e
        }(),
        ym = "en-US",
        bm = function() {
            function e() {
                this.code = ym, this.langs = new vm
            }
            return e.prototype.setCode = function(e) {
                this.code = e || ym
            }, e.prototype.setLanguage = function(e, t) {
                var n = this;
                (e = [].concat(e)).forEach(function(e) {
                    if (n.langs.has(e)) {
                        var r = n.langs.get(e);
                        n.langs.set(e, Ji(r, t))
                    } else n.langs.set(e, t)
                })
            }, e.prototype.get = function(e, t) {
                t || (t = this.code);
                var n = this.langs.get(t);
                n || (n = this.langs.get(ym));
                var r = n[e];
                if (!r) throw new Error('There is no text key "' + e + '" in ' + t);
                return r
            }, e
        }(),
        wm = new bm,
        km = [
            [{
                action: "Add row to up",
                command: "addRowToUp",
                disableInThead: !0,
                className: "add-row-up"
            }, {
                action: "Add row to down",
                command: "addRowToDown",
                disableInThead: !0,
                className: "add-row-down"
            }, {
                action: "Remove row",
                command: "removeRow",
                disableInThead: !0,
                className: "remove-row"
            }],
            [{
                action: "Add column to left",
                command: "addColumnToLeft",
                className: "add-column-left"
            }, {
                action: "Add column to right",
                command: "addColumnToRight",
                className: "add-column-right"
            }, {
                action: "Remove column",
                command: "removeColumn",
                className: "remove-column"
            }],
            [{
                action: "Align column to left",
                command: "alignColumn",
                payload: {
                    align: "left"
                },
                className: "align-column-left"
            }, {
                action: "Align column to center",
                command: "alignColumn",
                payload: {
                    align: "center"
                },
                className: "align-column-center"
            }, {
                action: "Align column to right",
                command: "alignColumn",
                payload: {
                    align: "right"
                },
                className: "align-column-right"
            }],
            [{
                action: "Remove table",
                command: "removeTable",
                className: "remove-table"
            }]
        ];

    function xm(e, t) {
        return km.map(function(n) {
            return n.map(function(n) {
                var r = n.action,
                    o = n.command,
                    i = n.payload,
                    s = n.disableInThead,
                    a = n.className;
                return {
                    label: wm.get(r),
                    onClick: function() {
                        e.emit("command", o, i)
                    },
                    disabled: t && !!s,
                    className: a
                }
            })
        }).concat()
    }
    var Cm = ["image", "link", "customBlock", "frontMatter"],
        Tm = ["strong", "strike", "emph", "code"],
        Mm = ["bulletList", "orderedList", "taskList"];

    function Sm(e, t, n) {
        var r = e.$from,
            o = e.$to,
            i = e.from,
            s = e.to,
            a = {
                indent: {
                    active: !1,
                    disabled: !0
                },
                outdent: {
                    active: !1,
                    disabled: !0
                }
            };
        return t.nodesBetween(i, s, function(e, t, i) {
            var s = function(e, t) {
                var n = e.type.name;
                return "listItem" === n ? e.attrs.task ? "taskList" : t.type.name : -1 !== n.indexOf("table") ? "table" : n
            }(e, i);
            zs(Cm, s) || (zs(Mm, s) ? (function(e, t) {
                t[e] = {
                    active: !0
                }, Mm.filter(function(t) {
                    return t !== e
                }).forEach(function(e) {
                    t[e] && delete t[e]
                })
            }(s, a), a.indent.disabled = !1, a.outdent.disabled = !1) : "paragraph" === s || "text" === s ? function(e, t, n, r) {
                Tm.forEach(function(o) {
                    var i = n.marks[o],
                        s = e.marksAcross(t) || [];
                    i.isInSet(s) && (r[o] = {
                        active: !0
                    })
                })
            }(r, o, n, a) : a[s] = {
                active: !0
            })
        }), a
    }

    function Em(e) {
        return new wt({
            view: function() {
                return {
                    update: function(t) {
                        var n = t.state,
                            r = n.selection,
                            o = n.doc,
                            i = n.schema;
                        e.emit("changeToolbarState", {
                            toolbarState: Sm(r, o, i)
                        })
                    }
                }
            }
        })
    }
    var Nm = function() {
            function e(e, t, n, r) {
                var o = this;
                this.openEditor = function() {
                    if (o.innerEditorView) throw new Error("The editor is already opened.");
                    o.dom.draggable = !1, o.wrapper.style.display = "none", o.innerViewContainer.style.display = "block", o.innerEditorView = new Ao(o.innerViewContainer, {
                        state: yt.create({
                            doc: o.node,
                            plugins: [Jo({
                                "Mod-z": function() {
                                    return zi(o.innerEditorView.state, o.innerEditorView.dispatch)
                                },
                                "Shift-Mod-z": function() {
                                    return qi(o.innerEditorView.state, o.innerEditorView.dispatch)
                                },
                                Tab: function(e, t) {
                                    return t(e.tr.insertText("\t")), !0
                                },
                                Enter: ei,
                                Escape: function() {
                                    return o.cancelEditing(), !0
                                },
                                "Ctrl-Enter": function() {
                                    return o.saveAndFinishEditing(), !0
                                }
                            }), Fi()]
                        }),
                        dispatchTransaction: function(e) {
                            return o.dispatchInner(e)
                        },
                        handleDOMEvents: {
                            mousedown: function() {
                                return o.editorView.hasFocus() && o.innerEditorView.focus(), !0
                            },
                            blur: function() {
                                return o.saveAndFinishEditing(), !0
                            }
                        }
                    }), o.innerEditorView.focus()
                }, this.node = e, this.editorView = t, this.getPos = n, this.toDOMAdaptor = r, this.innerEditorView = null, this.canceled = !1, this.dom = document.createElement("div"), this.dom.className = Qa("custom-block"), this.wrapper = document.createElement("div"), this.wrapper.className = Qa("custom-block-view"), this.createInnerViewContainer(), this.renderCustomBlock(), this.dom.appendChild(this.innerViewContainer), this.dom.appendChild(this.wrapper)
            }
            return e.prototype.renderToolArea = function() {
                var e = this,
                    t = document.createElement("div"),
                    n = document.createElement("span"),
                    r = document.createElement("button");
                t.className = "tool", n.textContent = this.node.attrs.info, n.className = "info", r.type = "button", r.addEventListener("click", function() {
                    return e.openEditor()
                }), t.appendChild(n), t.appendChild(r), this.wrapper.appendChild(t)
            }, e.prototype.renderCustomBlock = function() {
                var e = this.toDOMAdaptor.getToDOMNode(this.node.attrs.info);
                if (e) {
                    for (var t = e(this.node); this.wrapper.hasChildNodes();) this.wrapper.removeChild(this.wrapper.lastChild);
                    t && this.wrapper.appendChild(t), this.renderToolArea()
                }
            }, e.prototype.createInnerViewContainer = function() {
                this.innerViewContainer = document.createElement("div"), this.innerViewContainer.className = Qa("custom-block-editor"), this.innerViewContainer.style.display = "none"
            }, e.prototype.closeEditor = function() {
                this.innerEditorView && (this.innerEditorView.destroy(), this.innerEditorView = null, this.innerViewContainer.style.display = "none"), this.wrapper.style.display = "block"
            }, e.prototype.saveAndFinishEditing = function() {
                var e = this.editorView.state.selection.to,
                    t = this.editorView.state;
                this.editorView.dispatch(t.tr.setSelection(ia(t.tr, e))), this.editorView.focus(), this.renderCustomBlock(), this.closeEditor()
            }, e.prototype.cancelEditing = function() {
                var e = function(e) {
                    let t = Pi.getState(e);
                    return t ? t.done.eventCount : 0
                }(this.innerEditorView.state);
                for (this.canceled = !0; e--;) zi(this.innerEditorView.state, this.innerEditorView.dispatch), zi(this.editorView.state, this.editorView.dispatch);
                this.canceled = !1;
                var t = this.editorView.state.selection.to,
                    n = this.editorView.state;
                this.editorView.dispatch(n.tr.setSelection(it.create(n.doc, t))), this.editorView.focus(), this.closeEditor()
            }, e.prototype.dispatchInner = function(e) {
                var t = this.innerEditorView.state.applyTransaction(e),
                    n = t.state,
                    r = t.transactions;
                if (this.innerEditorView.updateState(n), !this.canceled && bl(this.getPos)) {
                    for (var o = this.editorView.state.tr, i = ye.offset(this.getPos() + 1), s = 0; s < r.length; s += 1)
                        for (var a = r[s].steps, l = 0; l < a.length; l += 1) o.step(a[l].map(i));
                    o.docChanged && this.editorView.dispatch(o)
                }
            }, e.prototype.update = function(e) {
                return !!e.sameMarkup(this.node) && (this.node = e, this.innerEditorView || this.renderCustomBlock(), !0)
            }, e.prototype.stopEvent = function(e) {
                return !!this.innerEditorView && !!e.target && this.innerEditorView.dom.contains(e.target)
            }, e.prototype.ignoreMutation = function() {
                return !0
            }, e.prototype.destroy = function() {
                this.dom.removeEventListener("dblclick", this.openEditor), this.closeEditor()
            }, e
        }(),
        Om = "image-link",
        Dm = function() {
            function e(e, t, n, r) {
                var o, i = this;
                this.handleMousedown = function(e) {
                    e.preventDefault();
                    var t = e.target,
                        n = e.offsetX,
                        r = e.offsetY;
                    if (i.imageLink && bl(i.getPos) && Fa(t, Om)) {
                        var o = getComputedStyle(t, ":before");
                        if (e.stopPropagation(), Xa(o, n, r)) {
                            var s = i.view.state.tr,
                                a = i.getPos();
                            s.setSelection(ia(s, a, a + 1)), i.view.dispatch(s), i.eventEmitter.emit("openPopup", "link", i.imageLink.attrs)
                        }
                    }
                }, this.node = e, this.view = t, this.getPos = n, this.eventEmitter = r, this.imageLink = null !== (o = e.marks.filter(function(e) {
                    return "link" === e.type.name
                })[0]) && void 0 !== o ? o : null, this.dom = this.createElement(), this.bindEvent()
            }
            return e.prototype.createElement = function() {
                var e = this.createImageElement(this.node);
                if (this.imageLink) {
                    var t = document.createElement("span");
                    return t.className = Om, t.appendChild(e), t
                }
                return e
            }, e.prototype.createImageElement = function(e) {
                var t = document.createElement("img"),
                    n = e.attrs,
                    r = n.imageUrl,
                    o = n.altText,
                    i = Kf(e.attrs);
                return t.src = r, o && (t.alt = o), al(i, t), t
            }, e.prototype.bindEvent = function() {
                this.imageLink && this.dom.addEventListener("mousedown", this.handleMousedown)
            }, e.prototype.stopEvent = function() {
                return !0
            }, e.prototype.destroy = function() {
                this.imageLink && this.dom.removeEventListener("mousedown", this.handleMousedown)
            }, e
        }(),
        Am = function() {
            function e(e, t, n, r) {
                var o = this;
                this.contentDOM = null, this.input = null, this.timer = null, this.handleMousedown = function(e) {
                    var t = e.target;
                    if ("none" !== getComputedStyle(t, ":after").backgroundImage && bl(o.getPos)) {
                        var n = o.view.coordsAtPos(o.getPos()),
                            r = n.top,
                            i = n.right;
                        o.createLanguageEditor({
                            top: r,
                            right: i
                        })
                    }
                }, this.handleKeydown = function(e) {
                    "Enter" === e.key && o.input && (e.preventDefault(), o.changeLanguage())
                }, this.node = e, this.view = t, this.getPos = n, this.eventEmitter = r, this.createElement(), this.bindDOMEvent(), this.bindEvent()
            }
            return e.prototype.createElement = function() {
                var e = this.node.attrs.language,
                    t = document.createElement("div");
                t.setAttribute("data-language", e || "text"), t.className = "toastui-editor-ww-code-block";
                var n = this.createCodeBlockElement(),
                    r = n.firstChild;
                t.appendChild(n), this.dom = t, this.contentDOM = r
            }, e.prototype.createCodeBlockElement = function() {
                var e = document.createElement("pre"),
                    t = document.createElement("code"),
                    n = this.node.attrs.language,
                    r = Kf(this.node.attrs);
                return n && t.setAttribute("data-language", n), al(r, e), e.appendChild(t), e
            }, e.prototype.createLanguageEditor = function(e) {
                var t = this,
                    n = e.top,
                    r = e.right,
                    o = document.createElement("span");
                o.className = "toastui-editor-ww-code-block-language";
                var i = document.createElement("input");
                i.type = "text", i.value = this.node.attrs.language, o.appendChild(i), this.view.dom.parentElement.appendChild(o);
                var s = o.clientWidth;
                rs(o, {
                    top: n + 10 + "px",
                    left: r - s - 10 + "px",
                    width: s + "px"
                }), this.input = i, this.input.addEventListener("blur", function() {
                    return t.changeLanguage()
                }), this.input.addEventListener("keydown", this.handleKeydown), this.clearTimer(), this.timer = setTimeout(function() {
                    t.input.focus()
                })
            }, e.prototype.bindDOMEvent = function() {
                this.dom && this.dom.addEventListener("click", this.handleMousedown)
            }, e.prototype.bindEvent = function() {
                var e = this;
                this.eventEmitter.listen("scroll", function() {
                    e.input && e.reset()
                })
            }, e.prototype.changeLanguage = function() {
                if (this.input && bl(this.getPos)) {
                    var e = this.input.value;
                    this.reset();
                    var t = this.getPos(),
                        n = this.view.state.tr;
                    n.setNodeMarkup(t, null, {
                        language: e
                    }), this.view.dispatch(n)
                }
            }, e.prototype.reset = function() {
                var e;
                if (null === (e = this.input) || void 0 === e ? void 0 : e.parentElement) {
                    var t = this.input.parentElement;
                    this.input = null, tl(t)
                }
            }, e.prototype.clearTimer = function() {
                this.timer && (clearTimeout(this.timer), this.timer = null)
            }, e.prototype.stopEvent = function() {
                return !0
            }, e.prototype.update = function(e) {
                return !!e.sameMarkup(this.node) && (this.node = e, !0)
            }, e.prototype.destroy = function() {
                this.reset(), this.clearTimer(), this.dom && this.dom.removeEventListener("click", this.handleMousedown)
            }, e
        }(),
        Lm = /MsoListParagraph/,
        Im = /style=(.|\n)*mso-/,
        Rm = /mso-list:(.*)/,
        Pm = /O:P/,
        Bm = /^(n|u|l)/;

    function Fm(e) {
        for (var t = [], n = document.createTreeWalker(e, 1, null, !1); n.nextNode();) {
            var r = n.currentNode;
            if (el(r)) {
                var o = r,
                    i = o.outerHTML,
                    s = o.textContent,
                    a = Im.test(i),
                    l = Rm.test(i);
                a && !l && s ? t.push([r, !0]) : (Pm.test(r.nodeName) || a && !s || l) && t.push([r, !1])
            }
        }
        return t.forEach(function(e) {
            var t = e[0];
            e[1] ? function(e) {
                for (var t = []; e.firstChild;) t.push(e.firstChild), e.parentNode && e.parentNode.insertBefore(e.firstChild, e);
                tl(e)
            }(t) : tl(t)
        }), e.innerHTML.trim()
    }

    function Hm(e) {
        var t = e[0].unordered ? "ul" : "ol",
            n = document.createElement(t);
        return e.forEach(function(e) {
            var t = e.children,
                r = e.contents,
                o = document.createElement("li");
            o.innerHTML = r, n.appendChild(o), t.length && n.appendChild(Hm(t))
        }), n
    }

    function zm(e) {
        return Hm(function(e) {
            var t = [];
            return e.forEach(function(e, n) {
                var r = t[n - 1],
                    o = function(e, t) {
                        var n = e.getAttribute("style");
                        if (n) {
                            var r = n.match(Rm)[1].trim().split(" ")[1];
                            return {
                                id: t,
                                level: parseInt(r.replace("level", ""), 10),
                                prev: null,
                                parent: null,
                                children: [],
                                unordered: Bm.test(e.textContent || ""),
                                contents: Fm(e)
                            }
                        }
                        return null
                    }(e, n);
                o && (r && function(e, t) {
                    if (t.level < e.level) t.children.push(e), e.parent = t;
                    else {
                        for (; t && t.level !== e.level;) t = t.parent;
                        t && (e.prev = t, e.parent = t.parent, e.parent && e.parent.children.push(e))
                    }
                }(o, r), t.push(o))
            }), t
        }(e).filter(function(e) {
            return !e.parent
        }))
    }

    function qm(e) {
        return function(e) {
            return Im.test(e)
        }(e = function(e) {
            return /<\/td>((?!<\/tr>)[\s\S])*$/i.test(e) && (e = "<tr>" + e + "</tr>"), /<\/tr>((?!<\/table>)[\s\S])*$/i.test(e) && (e = "<table>" + e + "</table>"), e
        }(e = function(e) {
            var t = e.indexOf("\x3c!--StartFragment--\x3e"),
                n = e.lastIndexOf("\x3c!--EndFragment--\x3e");
            return t > -1 && n > -1 && (e = e.slice(t + 20, n)), e.replace(/<br[^>]*>/g, Ga)
        }(e))) && (e = function(e) {
            var t = document.createElement("div");
            t.innerHTML = e;
            var n, r = [],
                o = (n = na(t.querySelectorAll("p.MsoListParagraph"))).length ? n : [];
            return o.forEach(function(e) {
                var n, o, i = function(e) {
                    for (; e && !el(e);) e = e.nextSibling;
                    return !e || !Lm.test(e.className)
                }(e.nextSibling);
                if (r.push(e), i) {
                    var s = zm(r),
                        a = e.nextSibling;
                    a ? (n = s, (o = a).parentNode && o.parentNode.insertBefore(n, o)) : function(e, t) {
                        (t = Gi(t) ? na(t) : [t]).forEach(function(t) {
                            e.appendChild(t)
                        })
                    }(t, s), r = []
                }
                tl(e)
            }), (o.length ? "<p></p>" : "") + t.innerHTML
        }(e)), e
    }

    function Vm(e, t, n) {
        for (var r = [], o = e.childCount, i = 0; i < o; i += 1)
            if (!e.child(i).attrs.extended) {
                var s = i < o ? n.create(e.child(i).attrs, e.child(i).content) : n.createAndFill();
                r.push(s)
            } return r
    }

    function jm(e, t, n) {
        var r = n.nodes,
            o = r.tableRow,
            i = Vm(e, 0, r.tableHeadCell);
        return o.create(null, i)
    }

    function $m(e, t, n) {
        var r = n.nodes,
            o = r.tableRow,
            i = Vm(e, 0, r.tableBodyCell);
        return o.create(null, i)
    }

    function _m(e) {
        var t = [],
            n = [];
        return "tableHead" === e.firstChild.type.name && e.firstChild.forEach(function(e) {
            return t.push(e)
        }), "tableBody" === e.lastChild.type.name && e.lastChild.forEach(function(e) {
            return n.push(e)
        }), _i(_i([], t), n)
    }

    function Um(e, t, n) {
        var r = jm(e, 0, n);
        return n.nodes.tableHead.create(null, r)
    }

    function Wm(e, t, n) {
        var r = e.map(function(e) {
            return $m(e, 0, n)
        });
        if (!e.length) {
            var o = function(e, t) {
                for (var n = t.nodes, r = n.tableRow, o = n.tableBodyCell, i = [], s = 0; s < e; s += 1) {
                    var a = o.createAndFill();
                    i.push(a)
                }
                return r.create({
                    dummyRowForPasting: !0
                }, i)
            }(t, n);
            r.push(o)
        }
        return n.nodes.tableBody.create(null, r)
    }

    function Jm(e) {
        return 4 * e
    }
    var Km = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "doc"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "block+"
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(fl),
        Gm = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "paragraph"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "inline*",
                        group: "block",
                        attrs: $i({}, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: [{
                            tag: "p"
                        }],
                        toDOM: function(e) {
                            return ["p", Kf(e.attrs), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(fl),
        Xm = /\s{1,4}$/,
        Zm = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "text"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        group: "inline"
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.addSpaces = function() {
                return function(e, t) {
                    var n = e.selection,
                        r = e.tr,
                        o = n.$from,
                        i = n.$to;
                    return !(!o.blockRange(i) || jf(o) || $f(o) || (t(r.insertText("    ", o.pos, i.pos)), 0))
                }
            }, t.prototype.removeSpaces = function() {
                return function(e, t) {
                    var n = e.selection,
                        r = e.tr,
                        o = n.$from,
                        i = n.$to,
                        s = n.from;
                    if (o.blockRange(i) && !jf(o) && !$f(o)) {
                        var a = o.nodeBefore;
                        if (a && a.isText) {
                            var l = a.text,
                                c = l.replace(Xm, ""),
                                u = l.length - c.length;
                            return t(r.delete(s - u, s)), !0
                        }
                    }
                    return !1
                }
            }, t.prototype.keymaps = function() {
                return {
                    Tab: this.addSpaces(),
                    "Shift-Tab": this.removeSpaces()
                }
            }, t
        }(fl),
        Qm = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "heading"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "levels", {
                get: function() {
                    return [1, 2, 3, 4, 5, 6]
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    var e = this.levels.map(function(e) {
                        return {
                            tag: "h" + e,
                            getAttrs: function(t) {
                                var n = t.getAttribute("data-raw-html");
                                return $i({
                                    level: e
                                }, n && {
                                    rawHTML: n
                                })
                            }
                        }
                    });
                    return {
                        attrs: $i({
                            level: {
                                default: 1
                            },
                            headingType: {
                                default: "atx"
                            },
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        content: "inline*",
                        group: "block",
                        defining: !0,
                        parseDOM: e,
                        toDOM: function(e) {
                            var t = e.attrs;
                            return ["h" + t.level, Kf(t), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function(e) {
                    return function(t, n) {
                        return ci(t.schema.nodes[e.level ? "heading" : "paragraph"], e)(t, n)
                    }
                }
            }, t
        }(fl),
        Ym = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "codeBlock"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "text*",
                        group: "block",
                        attrs: $i({
                            language: {
                                default: null
                            },
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        code: !0,
                        defining: !0,
                        marks: "",
                        parseDOM: [{
                            tag: "pre",
                            preserveWhitespace: "full",
                            getAttrs: function(e) {
                                var t = e.getAttribute("data-raw-html"),
                                    n = e.firstElementChild;
                                return $i({
                                    language: (null == n ? void 0 : n.getAttribute("data-language")) || null
                                }, t && {
                                    rawHTML: t
                                })
                            }
                        }],
                        toDOM: function(e) {
                            var t = e.attrs;
                            return [t.rawHTML || "pre", ["code", $i({
                                "data-language": t.language
                            }, Kf(t)), 0]]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function() {
                    return function(e, t) {
                        return ci(e.schema.nodes.codeBlock)(e, t)
                    }
                }
            }, t.prototype.moveCursor = function(e) {
                var t = this;
                return function(n, r) {
                    var o, i = n.tr,
                        s = n.doc,
                        a = n.schema,
                        l = n.selection.$from;
                    if (t.context.view.endOfTextblock(e) && "codeBlock" === l.node().type.name) {
                        var c = l.parent.textContent.split("\n"),
                            u = "up" === e ? l.start() : l.end(),
                            d = "up" === e ? [u, c[0].length + u] : [u - Ks(c).length, u],
                            p = s.resolve("up" === e ? l.before() : l.after()),
                            h = "up" === e ? p.nodeBefore : p.nodeAfter;
                        if ((o = l.pos) >= d[0] && o <= d[1] && !h) {
                            var f = sa(i, p, a);
                            if (f) return r(f), !0
                        }
                    }
                    return !1
                }
            }, t.prototype.keymaps = function() {
                var e = this.commands()();
                return {
                    "Shift-Mod-p": e,
                    "Shift-Mod-P": e,
                    ArrowUp: this.moveCursor("up"),
                    ArrowDown: this.moveCursor("down")
                }
            }, t
        }(fl),
        eg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "bulletList"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "listItem+",
                        group: "block",
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: [Uf("ul")],
                        toDOM: function(e) {
                            return ["ul", Kf(e.attrs), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.changeList = function() {
                return function(e, t) {
                    return Zf(e.schema.nodes.bulletList)(e, t)
                }
            }, t.prototype.commands = function() {
                return {
                    bulletList: this.changeList,
                    taskList: Qf
                }
            }, t.prototype.keymaps = function() {
                var e = this.changeList(),
                    t = Yf(),
                    n = t.indent,
                    r = t.outdent;
                return {
                    "Mod-u": e,
                    "Mod-U": e,
                    Tab: n(),
                    "Shift-Tab": r()
                }
            }, t
        }(fl),
        tg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "orderedList"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "listItem+",
                        group: "block",
                        attrs: $i({
                            order: {
                                default: 1
                            },
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: [{
                            tag: "ol",
                            getAttrs: function(e) {
                                var t = e.getAttribute("start"),
                                    n = e.getAttribute("data-raw-html");
                                return $i({
                                    order: e.hasAttribute("start") ? Number(t) : 1
                                }, n && {
                                    rawHTML: n
                                })
                            }
                        }],
                        toDOM: function(e) {
                            var t = e.attrs;
                            return [t.rawHTML || "ol", $i({
                                start: 1 === t.order ? null : t.order
                            }, Kf(t)), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function() {
                    return function(e, t) {
                        return Zf(e.schema.nodes.orderedList)(e, t)
                    }
                }
            }, t.prototype.keymaps = function() {
                var e = this.commands()(),
                    t = Yf(),
                    n = t.indent,
                    r = t.outdent;
                return {
                    "Mod-o": e,
                    "Mod-O": e,
                    Tab: n(),
                    "Shift-Tab": r()
                }
            }, t
        }(fl),
        ng = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "listItem"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "paragraph block*",
                        selectable: !1,
                        attrs: {
                            task: {
                                default: !1
                            },
                            checked: {
                                default: !1
                            },
                            rawHTML: {
                                default: null
                            }
                        },
                        defining: !0,
                        parseDOM: [{
                            tag: "li",
                            getAttrs: function(e) {
                                var t = e.getAttribute("data-raw-html");
                                return $i({
                                    task: e.hasAttribute("data-task"),
                                    checked: e.hasAttribute("data-task-checked")
                                }, t && {
                                    rawHTML: t
                                })
                            }
                        }],
                        toDOM: function(e) {
                            var t = e.attrs,
                                n = t.task,
                                r = t.checked;
                            if (!n) return [t.rawHTML || "li", 0];
                            var o = ["task-list-item"];
                            return r && o.push("checked"), [t.rawHTML || "li", $i({
                                class: o.join(" "),
                                "data-task": n
                            }, r && {
                                "data-task-checked": r
                            }), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.liftToPrevListItem = function() {
                return function(e, t) {
                    var n = e.selection,
                        r = e.tr,
                        o = e.schema,
                        i = n.$from,
                        s = n.empty,
                        a = o.nodes.listItem,
                        l = i.parent,
                        c = i.node(-1);
                    if (s && !l.childCount && c.type === a) {
                        if (i.index(-2) >= 1) return r.delete(i.start(-1) - 1, i.end(-1)), t(r), !0;
                        if (i.node(-3).type === a) return r.delete(i.start(-2) - 1, i.end(-1)), t(r), !0
                    }
                    return !1
                }
            }, t.prototype.keymaps = function() {
                return {
                    Backspace: this.liftToPrevListItem(),
                    Enter: function(e, t) {
                        return (n = e.schema.nodes.listItem, function(e, t) {
                            var r = e.tr,
                                o = e.selection,
                                i = o.$from,
                                s = o.$to;
                            if (i.depth < 2 || !i.sameParent(s)) return !1;
                            var a = i.node(-1);
                            if (a.type !== n) return !1;
                            if (0 === i.parent.content.size && i.node(-1).childCount === i.indexAfter(-1)) {
                                if (2 === i.depth || i.node(-3).type !== n || i.index(-2) !== i.node(-2).childCount - 1) return !1;
                                for (var c = i.index(-1) > 0, u = l.empty, d = i.depth - (c ? 1 : 2); d >= i.depth - 3; d -= 1) u = l.from(i.node(d).copy(u));
                                return u = u.append(l.from(n.createAndFill())), r.replace(c ? i.before() : i.before(-1), i.after(-3), new f(u, c ? 3 : 2, 2)), r.setSelection(tt.near(r.doc.resolve(i.pos + (c ? 3 : 2)))), t(r), !0
                            }
                            var p = s.pos === i.end() ? a.contentMatchAt(0).defaultType : null,
                                h = p && [null, {
                                    type: p
                                }];
                            return r.delete(i.pos, s.pos), !!Fe(r.doc, i.pos, 2, h) && (r.split(i.pos, 2, h), t(r), !0)
                        })(e, t);
                        var n
                    }
                }
            }, t
        }(fl),
        rg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "blockQuote"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        content: "block+",
                        group: "block",
                        parseDOM: [Uf("blockquote")],
                        toDOM: function(e) {
                            return ["blockquote", Kf(e.attrs), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function() {
                    return function(e, t) {
                        return function(e, t = null) {
                            return function(n, r) {
                                let {
                                    $from: o,
                                    $to: i
                                } = n.selection, s = o.blockRange(i), a = s && function(e, t, n = null, r = e) {
                                    let o = function(e, t) {
                                            let {
                                                parent: n,
                                                startIndex: r,
                                                endIndex: o
                                            } = e, i = n.contentMatchAt(r).findWrapping(t);
                                            if (!i) return null;
                                            let s = i.length ? i[0] : t;
                                            return n.canReplaceWith(r, o, s) ? i : null
                                        }(e, t),
                                        i = o && function(e, t) {
                                            let {
                                                parent: n,
                                                startIndex: r,
                                                endIndex: o
                                            } = e, i = n.child(r), s = t.contentMatch.findWrapping(i.type);
                                            if (!s) return null;
                                            let a = (s.length ? s[s.length - 1] : t).contentMatch;
                                            for (let e = r; a && e < o; e++) a = a.matchType(n.child(e).type);
                                            return a && a.validEnd ? s : null
                                        }(r, t);
                                    return i ? o.map(Re).concat({
                                        type: t,
                                        attrs: n
                                    }).concat(i.map(Re)) : null
                                }(s, e, t);
                                return !!a && (r && r(n.tr.wrap(s, a).scrollIntoView()), !0)
                            }
                        }(e.schema.nodes.blockQuote)(e, t)
                    }
                }
            }, t.prototype.keymaps = function() {
                var e = this.commands()();
                return {
                    "Alt-q": e,
                    "Alt-Q": e
                }
            }, t
        }(fl),
        og = {
            left: function(e, t) {
                var n = e[0],
                    r = e[1],
                    o = t.totalColumnCount,
                    i = 0 === r;
                if (0 !== n || !i) {
                    r -= 1, i && (n -= 1, r = o - 1);
                    var s = t.getCellInfo(n, r);
                    return s.offset + s.nodeSize - 2
                }
                return null
            },
            right: function(e, t) {
                var n = e[0],
                    r = e[1],
                    o = t.totalRowCount,
                    i = t.totalColumnCount,
                    s = r === i - 1;
                if (n !== o - 1 || !s) {
                    var a = r + 1,
                        l = t.getColspanStartInfo(n, r);
                    return (null == l ? void 0 : l.count) > 1 && (a += l.count - 1), (s || a === i) && (n += 1, a = 0), t.getCellInfo(n, a).offset + 2
                }
                return null
            },
            up: function(e, t) {
                var n = e[0],
                    r = e[1];
                if (n > 0) {
                    var o = t.getCellInfo(n - 1, r);
                    return o.offset + o.nodeSize - 2
                }
                return null
            },
            down: function(e, t) {
                var n = e[0],
                    r = e[1];
                if (n < t.totalRowCount - 1) {
                    var o = n + 1,
                        i = t.getRowspanStartInfo(n, r);
                    return (null == i ? void 0 : i.count) > 1 && (o += i.count - 1), t.getCellInfo(o, r).offset + 2
                }
                return null
            }
        };

    function ig(e, t, n) {
        var r = n[0],
            o = n[1],
            i = t.getRowspanStartInfo(r, o),
            s = "up" === e && 0 === r,
            a = "down" === e && ((null == i ? void 0 : i.count) > 1 ? r + i.count - 1 : r) === t.totalRowCount - 1;
        return s || a
    }

    function sg(e, t, n, r) {
        void 0 === r && (r = !1);
        var o = e.doc.resolve(t.tableEndOffset);
        return r || !o.nodeAfter ? sa(e, o, n) : e.setSelection(tt.near(o, 1))
    }

    function ag(e, t, n, r) {
        var o = (0, og[e])(n, r);
        if (o) {
            var i = "right" === e || "down" === e ? 1 : -1;
            return t.setSelection(tt.near(t.doc.resolve(o), i))
        }
        return null
    }

    function lg(e, t, n) {
        var r = e.getCellInfo(t, 0).offset,
            o = e.getCellInfo(t, n - 1);
        return {
            from: r,
            to: o.offset + o.nodeSize
        }
    }
    var cg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "table"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "tableHead{1} tableBody{1}",
                        group: "block",
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: [Uf("table")],
                        toDOM: function(e) {
                            return ["table", Kf(e.attrs), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.addTable = function() {
                return function(e) {
                    return void 0 === e && (e = {
                            rowCount: 2,
                            columnCount: 1,
                            data: []
                        }),
                        function(t, n) {
                            var r = e.rowCount,
                                o = e.columnCount,
                                i = e.data,
                                s = t.schema,
                                a = t.selection,
                                l = t.tr,
                                c = a.from,
                                u = a.to,
                                d = a.$from;
                            if (c === u && !$f(d)) {
                                var p = s.nodes,
                                    h = p.tableHead,
                                    f = p.tableBody,
                                    m = null == i ? void 0 : i.slice(0, o),
                                    g = null == i ? void 0 : i.slice(o, i.length),
                                    v = function(e, t, n) {
                                        for (var r = t.nodes, o = r.tableRow, i = r.tableHeadCell, s = r.paragraph, a = [], l = 0; l < e; l += 1) {
                                            var c = n && n[l],
                                                u = s.create(null, c ? t.text(c) : []);
                                            a.push(i.create(null, u))
                                        }
                                        return [o.create(null, a)]
                                    }(o, s, m),
                                    y = im(r - 1, o, s, g),
                                    b = s.nodes.table.create(null, [h.create(null, v), f.create(null, y)]);
                                return n(l.replaceSelectionWith(b)), !0
                            }
                            return !1
                        }
                }
            }, t.prototype.removeTable = function() {
                return function() {
                    return function(e, t) {
                        var n = e.selection,
                            r = e.tr,
                            o = tm.create(n.$anchor);
                        if (o) {
                            var i = o.tableStartOffset,
                                s = o.tableEndOffset,
                                a = i - 1,
                                l = ia(r.delete(a, s), a);
                            return t(r.setSelection(l)), !0
                        }
                        return !1
                    }
                }
            }, t.prototype.addColumn = function(e) {
                return function() {
                    return function(t, n) {
                        var r = t.selection,
                            o = t.tr,
                            i = t.schema,
                            s = cm(r),
                            a = s.anchor,
                            l = s.head;
                        if (a && l) {
                            for (var c = tm.create(a), u = c.getRectOffsets(a, l), d = "left" === e ? u.startColIdx : u.endColIdx + 1, p = dm(u).columnCount, h = c.totalRowCount, f = 0; f < h; f += 1) {
                                var m = sm(p, f, i);
                                o.insert(o.mapping.map(c.posAt(f, d)), m)
                            }
                            return n(o), !0
                        }
                        return !1
                    }
                }
            }, t.prototype.removeColumn = function() {
                return function() {
                    return function(e, t) {
                        var n = e.selection,
                            r = e.tr,
                            o = cm(n),
                            i = o.anchor,
                            s = o.head;
                        if (i && s) {
                            var a = tm.create(i),
                                l = a.getRectOffsets(i, s),
                                c = a.totalColumnCount,
                                u = a.totalRowCount;
                            if (dm(l).columnCount === c) return !1;
                            for (var d = l.startColIdx, p = l.endColIdx, h = r.mapping.maps.length, f = 0; f < u; f += 1)
                                for (var m = p; m >= d; m -= 1) {
                                    var g = a.getCellInfo(f, m),
                                        v = g.offset,
                                        y = g.nodeSize,
                                        b = r.mapping.slice(h).map(v),
                                        w = b + y;
                                    r.delete(b, w)
                                }
                            return t(r), !0
                        }
                        return !1
                    }
                }
            }, t.prototype.addRow = function(e) {
                return function() {
                    return function(t, n) {
                        var r = t.selection,
                            o = t.schema,
                            i = t.tr,
                            s = cm(r),
                            a = s.anchor,
                            l = s.head;
                        if (a && l) {
                            var c = tm.create(a),
                                u = c.totalColumnCount,
                                d = c.getRectOffsets(a, l),
                                p = dm(d).rowCount,
                                h = function(e, t, n) {
                                    var r, o, i;
                                    return "up" === e ? (r = n.startRowIdx, o = 0, i = -1) : (r = n.endRowIdx, o = t.totalColumnCount - 1, i = t.getCellInfo(r, o).nodeSize + 1), {
                                        targetRowIdx: r,
                                        insertColIdx: o,
                                        nodeSize: i
                                    }
                                }(e, c, d),
                                f = h.targetRowIdx,
                                m = h.insertColIdx,
                                g = h.nodeSize;
                            if (0 !== f) {
                                for (var v = [], y = i.mapping.map(c.posAt(f, m)) + g, b = [], w = 0; w < u; w += 1) b = b.concat(sm(1, f, o));
                                for (var k = 0; k < p; k += 1) v.push(o.nodes.tableRow.create(null, b));
                                return n(i.insert(y, v)), !0
                            }
                        }
                        return !1
                    }
                }
            }, t.prototype.removeRow = function() {
                return function() {
                    return function(e, t) {
                        var n = e.selection,
                            r = e.tr,
                            o = cm(n),
                            i = o.anchor,
                            s = o.head;
                        if (i && s) {
                            var a = tm.create(i),
                                l = a.totalRowCount,
                                c = a.totalColumnCount,
                                u = a.getRectOffsets(i, s),
                                d = dm(u).rowCount,
                                p = u.startRowIdx,
                                h = u.endRowIdx;
                            if (d === l - 1 || 0 === p) return !1;
                            for (var f = h; f >= p; f -= 1) {
                                var m = lg(a, f, c),
                                    g = m.from,
                                    v = m.to;
                                r.delete(g - 1, v + 1)
                            }
                            return t(r), !0
                        }
                        return !1
                    }
                }
            }, t.prototype.alignColumn = function() {
                return function(e) {
                    return void 0 === e && (e = {
                            align: "center"
                        }),
                        function(t, n) {
                            var r = e.align,
                                o = t.selection,
                                i = t.tr,
                                s = cm(o),
                                a = s.anchor,
                                l = s.head;
                            if (a && l) {
                                for (var c = tm.create(a), u = c.totalRowCount, d = c.getRectOffsets(a, l), p = d.startColIdx, h = d.endColIdx, f = 0; f < u; f += 1)
                                    for (var m = p; m <= h; m += 1)
                                        if (!c.extendedRowspan(f, m) && !c.extendedColspan(f, m)) {
                                            var g = c.getNodeAndPos(f, m),
                                                v = g.node,
                                                y = g.pos,
                                                b = pm(v, {
                                                    align: r
                                                });
                                            i.setNodeMarkup(y, null, b)
                                        } return n(i), !0
                            }
                            return !1
                        }
                }
            }, t.prototype.moveToCell = function(e) {
                return function(t, n) {
                    var r = t.selection,
                        o = t.tr,
                        i = t.schema,
                        s = cm(r),
                        a = s.anchor,
                        l = s.head;
                    if (a && l) {
                        var c, u = tm.create(a),
                            d = u.getCellIndex(a);
                        if (c = ig(e, u, d) ? sg(o, u, i) : ag(e, o, d, u)) return n(c), !0
                    }
                    return !1
                }
            }, t.prototype.moveInCell = function(e) {
                var t = this;
                return function(n, r) {
                    var o = n.selection,
                        i = n.tr,
                        s = n.doc,
                        a = n.schema,
                        l = o.$from;
                    if (!t.context.view.endOfTextblock(e)) return !1;
                    var c = Vf(l, function(e) {
                        var t = e.type;
                        return "tableHeadCell" === t.name || "tableBodyCell" === t.name
                    });
                    if (c) {
                        var u = Vf(l, function(e) {
                                return "paragraph" === e.type.name
                            }),
                            d = c.depth;
                        if (u && function(e, t, n, r) {
                                var o = t[0],
                                    i = t[1],
                                    s = o + 3,
                                    a = i >= s,
                                    l = a ? o + 1 : i,
                                    c = function(e, t, n, r, o) {
                                        var i = t[2];
                                        if ("left" === e || "up" === e) {
                                            if (o && ! function(e, t, n) {
                                                    var r = n[0],
                                                        o = n[1],
                                                        i = t.resolve(e.before(r - 1));
                                                    return o === r && !i.nodeBefore
                                                }(n, r, [t[0], t[1]])) return !1;
                                            var s = n.before(i);
                                            if (r.resolve(s).nodeBefore) return !1
                                        }
                                        return !0
                                    }(e, [i, s, l], n, r, a),
                                    u = function(e, t, n, r, o) {
                                        if ("right" === e || "down" === e) {
                                            if (o && ! function(e) {
                                                    for (var t, n, r = e.depth; r && "tableBodyCell" !== (n = e.node(r)).type.name;) {
                                                        if ("listItem" === n.type.name) {
                                                            var o = e.node(r - 1).lastChild === n,
                                                                i = "paragraph" !== (null === (t = n.lastChild) || void 0 === t ? void 0 : t.type.name);
                                                            return !!o && !i
                                                        }
                                                        r -= 1
                                                    }
                                                    return !1
                                                }(n)) return !1;
                                            var i = n.after(t);
                                            if (r.resolve(i).nodeAfter) return !1
                                        }
                                        return !0
                                    }(e, l, n, r, a);
                                return c && u
                            }(e, [d, u.depth], l, s)) {
                            var p = cm(o).anchor,
                                h = tm.create(p),
                                f = h.getCellIndex(p),
                                m = void 0;
                            if (function(e, t, n) {
                                    var r = n[0],
                                        o = n[1];
                                    if ("up" === e || "down" === e) return !1;
                                    var i = t.tableStartOffset,
                                        s = t.tableEndOffset,
                                        a = t.getCellInfo(r, o),
                                        l = a.offset,
                                        c = a.nodeSize;
                                    return ("left" === e ? i : s) === ("left" === e ? l - 2 : l + c + 3)
                                }(e, h, f) ? m = function(e, t, n) {
                                    var r = e.doc.resolve(t.before(n - 3));
                                    return e.setSelection(new at(r))
                                }(i, l, d) : ig(e, h, f) ? "up" === e ? m = function(e, t, n) {
                                    var r = e.doc.resolve(t.tableStartOffset - 1);
                                    return r.nodeBefore ? e.setSelection(tt.near(r, -1)) : sa(e, r, n)
                                }(i, h, a) : "down" === e && (m = sg(i, h, a)) : m = ag(e, i, f, h), m) return r(m), !0
                        }
                    }
                    return !1
                }
            }, t.prototype.deleteCells = function() {
                return function(e, t) {
                    var n = e.schema,
                        r = e.selection,
                        o = e.tr,
                        i = cm(r),
                        s = i.anchor,
                        a = i.head;
                    if (s && a && !(r instanceof it)) {
                        for (var l = tm.create(s), c = l.getRectOffsets(s, a), u = c.startRowIdx, d = c.startColIdx, p = c.endRowIdx, h = c.endColIdx, f = u; f <= p; f += 1)
                            for (var m = d; m <= h; m += 1)
                                if (!l.extendedRowspan(f, m) && !l.extendedColspan(f, m)) {
                                    var g = l.getNodeAndPos(f, m),
                                        v = g.node,
                                        y = g.pos,
                                        b = sm(1, f, n, v.attrs);
                                    o.replaceWith(o.mapping.map(y), o.mapping.map(y + v.nodeSize), b)
                                } return t(o), !0
                    }
                    return !1
                }
            }, t.prototype.exitTable = function() {
                return function(e, t) {
                    var n = e.selection,
                        r = e.tr,
                        o = e.schema,
                        i = n.$from;
                    if (Vf(i, function(e) {
                            var t = e.type;
                            return "tableHeadCell" === t.name || "tableBodyCell" === t.name
                        }) && Vf(i, function(e) {
                            return "paragraph" === e.type.name
                        })) {
                        var s = cm(n).anchor;
                        return t(sg(r, tm.create(s), o, !0)), !0
                    }
                    return !1
                }
            }, t.prototype.commands = function() {
                return {
                    addTable: this.addTable(),
                    removeTable: this.removeTable(),
                    addColumnToLeft: this.addColumn("left"),
                    addColumnToRight: this.addColumn("right"),
                    removeColumn: this.removeColumn(),
                    addRowToUp: this.addRow("up"),
                    addRowToDown: this.addRow("down"),
                    removeRow: this.removeRow(),
                    alignColumn: this.alignColumn()
                }
            }, t.prototype.keymaps = function() {
                var e = this.deleteCells();
                return {
                    Tab: this.moveToCell("right"),
                    "Shift-Tab": this.moveToCell("left"),
                    ArrowUp: this.moveInCell("up"),
                    ArrowDown: this.moveInCell("down"),
                    ArrowLeft: this.moveInCell("left"),
                    ArrowRight: this.moveInCell("right"),
                    Backspace: e,
                    "Mod-Backspace": e,
                    Delete: e,
                    "Mod-Delete": e,
                    "Mod-Enter": this.exitTable()
                }
            }, t
        }(fl),
        ug = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "tableHead"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "tableRow{1}",
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: [Uf("thead")],
                        toDOM: function(e) {
                            return ["thead", Kf(e.attrs), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(fl),
        dg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "tableBody"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "tableRow+",
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: [{
                            tag: "tbody",
                            getAttrs: function(e) {
                                var t = e.querySelectorAll("tr")[0].children.length,
                                    n = e.getAttribute("data-raw-html");
                                return !!t && $i({}, n && {
                                    rawHTML: n
                                })
                            }
                        }],
                        toDOM: function(e) {
                            return ["tbody", Kf(e.attrs), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(fl),
        pg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "tableRow"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "(tableHeadCell | tableBodyCell)*",
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: [{
                            tag: "tr",
                            getAttrs: function(e) {
                                var t = e.children.length,
                                    n = e.getAttribute("data-raw-html");
                                return !!t && $i({}, n && {
                                    rawHTML: n
                                })
                            }
                        }],
                        toDOM: function(e) {
                            return ["tr", Kf(e.attrs), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(fl),
        hg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "tableHeadCell"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "paragraph+",
                        attrs: $i({
                            align: {
                                default: null
                            },
                            className: {
                                default: null
                            },
                            rawHTML: {
                                default: null
                            },
                            colspan: {
                                default: null
                            },
                            extended: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        isolating: !0,
                        parseDOM: [Jf("th")],
                        toDOM: function(e) {
                            var t = e.attrs,
                                n = Wf(t);
                            return ["th", $i($i({}, n), Kf(t)), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(fl),
        fg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "tableBodyCell"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "(paragraph | bulletList | orderedList)+",
                        attrs: {
                            align: {
                                default: null
                            },
                            className: {
                                default: null
                            },
                            rawHTML: {
                                default: null
                            },
                            colspan: {
                                default: null
                            },
                            rowspan: {
                                default: null
                            },
                            extended: {
                                default: null
                            }
                        },
                        isolating: !0,
                        parseDOM: [Jf("td")],
                        toDOM: function(e) {
                            return ["td", Wf(e.attrs), 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t
        }(fl),
        mg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "image"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        inline: !0,
                        attrs: $i({
                            imageUrl: {
                                default: ""
                            },
                            altText: {
                                default: null
                            },
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        group: "inline",
                        selectable: !1,
                        parseDOM: [{
                            tag: "img[src]",
                            getAttrs: function(e) {
                                var t = wf(e, {
                                        RETURN_DOM_FRAGMENT: !0
                                    }).firstChild,
                                    n = t.getAttribute("src") || "",
                                    r = t.getAttribute("data-raw-html"),
                                    o = t.getAttribute("alt");
                                return $i({
                                    imageUrl: n,
                                    altText: o
                                }, r && {
                                    rawHTML: r
                                })
                            }
                        }],
                        toDOM: function(e) {
                            var t = e.attrs;
                            return [t.rawHTML || "img", $i($i({
                                src: Hs(t.imageUrl)
                            }, t.altText && {
                                alt: t.altText
                            }), Kf(t))]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.addImage = function() {
                return function(e) {
                    return function(t, n) {
                        var r = t.schema,
                            o = t.tr,
                            i = e,
                            s = i.imageUrl,
                            a = i.altText;
                        if (!s) return !1;
                        var l = r.nodes.image.createAndFill($i({
                            imageUrl: s
                        }, a && {
                            altText: a
                        }));
                        return n(o.replaceSelectionWith(l).scrollIntoView()), !0
                    }
                }
            }, t.prototype.commands = function() {
                return {
                    addImage: this.addImage()
                }
            }, t
        }(fl),
        gg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "thematicBreak"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        group: "block",
                        parseDOM: [{
                            tag: "hr"
                        }],
                        selectable: !1,
                        toDOM: function(e) {
                            var t = e.attrs;
                            return ["div", Kf(t), [t.rawHTML || "hr"]]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.hr = function() {
                var e = this;
                return function() {
                    return function(t, n) {
                        var r, o = t.selection,
                            i = o.$from;
                        if (i === o.$to) {
                            var s = t.doc,
                                a = t.schema.nodes,
                                l = a.thematicBreak,
                                c = a.paragraph,
                                u = [l.create()],
                                d = i.node(1),
                                p = s.child(s.childCount - 1) === d,
                                h = s.resolve(i.after(1)),
                                f = (null === (r = i.nodeAfter) || void 0 === r ? void 0 : r.type.name) === e.name;
                            return (p || f) && u.push(c.create()), n(t.tr.insert(h.pos, u).scrollIntoView()), !0
                        }
                        return !1
                    }
                }
            }, t.prototype.commands = function() {
                return {
                    hr: this.hr()
                }
            }, t.prototype.keymaps = function() {
                var e = this.hr()();
                return {
                    "Mod-l": e,
                    "Mod-L": e
                }
            }, t
        }(fl),
        vg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "strong"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    var e = ["b", "strong"].map(function(e) {
                        return {
                            tag: e,
                            getAttrs: function(e) {
                                var t = e.getAttribute("data-raw-html");
                                return $i({}, t && {
                                    rawHTML: t
                                })
                            }
                        }
                    });
                    return {
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: e,
                        toDOM: function(e) {
                            var t = e.attrs;
                            return [t.rawHTML || "strong", Kf(t)]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.bold = function() {
                return function() {
                    return function(e, t) {
                        return ui(e.schema.marks.strong)(e, t)
                    }
                }
            }, t.prototype.commands = function() {
                return {
                    bold: this.bold()
                }
            }, t.prototype.keymaps = function() {
                var e = this.bold()();
                return {
                    "Mod-b": e,
                    "Mod-B": e
                }
            }, t
        }(Ql),
        yg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "emph"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    var e = ["i", "em"].map(function(e) {
                        return {
                            tag: e,
                            getAttrs: function(e) {
                                var t = e.getAttribute("data-raw-html");
                                return $i({}, t && {
                                    rawHTML: t
                                })
                            }
                        }
                    });
                    return {
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: e,
                        toDOM: function(e) {
                            var t = e.attrs;
                            return [t.rawHTML || "em", Kf(t)]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.italic = function() {
                return function() {
                    return function(e, t) {
                        return ui(e.schema.marks.emph)(e, t)
                    }
                }
            }, t.prototype.commands = function() {
                return {
                    italic: this.italic()
                }
            }, t.prototype.keymaps = function() {
                var e = this.italic()();
                return {
                    "Mod-i": e,
                    "Mod-I": e
                }
            }, t
        }(Ql),
        bg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "strike"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    var e = ["s", "del"].map(function(e) {
                        return {
                            tag: e,
                            getAttrs: function(e) {
                                var t = e.getAttribute("data-raw-html");
                                return $i({}, t && {
                                    rawHTML: t
                                })
                            }
                        }
                    });
                    return {
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: e,
                        toDOM: function(e) {
                            var t = e.attrs;
                            return [t.rawHTML || "del", Kf(t)]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function() {
                    return function(e, t) {
                        return ui(e.schema.marks.strike)(e, t)
                    }
                }
            }, t.prototype.keymaps = function() {
                var e = this.commands()();
                return {
                    "Mod-s": e,
                    "Mod-S": e
                }
            }, t
        }(Ql),
        wg = function(e) {
            function t(t) {
                var n = e.call(this) || this;
                return n.linkAttributes = t, n
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "link"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    var e = this;
                    return {
                        attrs: $i({
                            linkUrl: {
                                default: ""
                            },
                            title: {
                                default: null
                            },
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        inclusive: !1,
                        parseDOM: [{
                            tag: "a[href]",
                            getAttrs: function(e) {
                                var t = wf(e, {
                                        RETURN_DOM_FRAGMENT: !0
                                    }).firstChild,
                                    n = t.getAttribute("href") || "",
                                    r = t.getAttribute("title") || "",
                                    o = t.getAttribute("data-raw-html");
                                return $i({
                                    linkUrl: n,
                                    title: r
                                }, o && {
                                    rawHTML: o
                                })
                            }
                        }],
                        toDOM: function(t) {
                            var n = t.attrs;
                            return [n.rawHTML || "a", $i($i({
                                href: Hs(n.linkUrl)
                            }, e.linkAttributes), Kf(n))]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.addLink = function() {
                return function(e) {
                    return function(t, n) {
                        var r = e,
                            o = r.linkUrl,
                            i = r.linkText,
                            s = void 0 === i ? "" : i,
                            a = t.schema,
                            l = t.tr,
                            c = t.selection,
                            u = c.empty,
                            d = c.from,
                            p = c.to;
                        if (d && p && o) {
                            var h = {
                                    linkUrl: o
                                },
                                f = a.mark("link", h);
                            if (u && s) {
                                var m = oa(a, s, f);
                                l.replaceRangeWith(d, p, m)
                            } else l.addMark(d, p, f);
                            return n(l.scrollIntoView()), !0
                        }
                        return !1
                    }
                }
            }, t.prototype.toggleLink = function() {
                return function(e) {
                    return function(t, n) {
                        return ui(t.schema.marks.link, e)(t, n)
                    }
                }
            }, t.prototype.commands = function() {
                return {
                    addLink: this.addLink(),
                    toggleLink: this.toggleLink()
                }
            }, t
        }(Ql),
        kg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "code"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        attrs: $i({
                            rawHTML: {
                                default: null
                            }
                        }, {
                            htmlAttrs: {
                                default: null
                            },
                            classNames: {
                                default: null
                            }
                        }),
                        parseDOM: [{
                            tag: "code",
                            getAttrs: function(e) {
                                var t = e.getAttribute("data-raw-html");
                                return $i({}, t && {
                                    rawHTML: t
                                })
                            }
                        }],
                        toDOM: function(e) {
                            var t = e.attrs;
                            return [t.rawHTML || "code", Kf(t)]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function() {
                    return function(e, t) {
                        return ui(e.schema.marks.code)(e, t)
                    }
                }
            }, t.prototype.keymaps = function() {
                var e = this.commands()();
                return {
                    "Shift-Mod-c": e,
                    "Shift-Mod-C": e
                }
            }, t
        }(Ql),
        xg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "customBlock"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "text*",
                        group: "block",
                        attrs: {
                            info: {
                                default: null
                            }
                        },
                        atom: !0,
                        code: !0,
                        defining: !0,
                        parseDOM: [{
                            tag: "div[data-custom-info]",
                            getAttrs: function(e) {
                                return {
                                    info: e.getAttribute("data-custom-info")
                                }
                            }
                        }],
                        toDOM: function(e) {
                            return ["div", {
                                "data-custom-info": e.attrs.info || null
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function(e) {
                    return function(t, n) {
                        return !!(null == e ? void 0 : e.info) && ci(t.schema.nodes.customBlock, e)(t, n)
                    }
                }
            }, t
        }(fl),
        Cg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "frontMatter"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "text*",
                        group: "block",
                        code: !0,
                        defining: !0,
                        parseDOM: [{
                            preserveWhitespace: "full",
                            tag: "div[data-front-matter]"
                        }],
                        toDOM: function() {
                            return ["div", {
                                "data-front-matter": "true"
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function() {
                    return function(e, t, n) {
                        var r = e.selection.$from;
                        return !(!n.endOfTextblock("down") || "frontMatter" !== r.node().type.name) && ni(e, t)
                    }
                }
            }, t.prototype.keymaps = function() {
                return {
                    Enter: this.commands()()
                }
            }, t
        }(fl),
        Tg = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), Object.defineProperty(t.prototype, "name", {
                get: function() {
                    return "htmlComment"
                },
                enumerable: !1,
                configurable: !0
            }), Object.defineProperty(t.prototype, "schema", {
                get: function() {
                    return {
                        content: "text*",
                        group: "block",
                        code: !0,
                        defining: !0,
                        parseDOM: [{
                            preserveWhitespace: "full",
                            tag: "div[data-html-comment]"
                        }],
                        toDOM: function() {
                            return ["div", {
                                "data-html-comment": "true"
                            }, 0]
                        }
                    }
                },
                enumerable: !1,
                configurable: !0
            }), t.prototype.commands = function() {
                return function() {
                    return function(e, t, n) {
                        var r = e.selection.$from;
                        return !(!n.endOfTextblock("down") || "htmlComment" !== r.node().type.name) && ni(e, t)
                    }
                }
            }, t.prototype.keymaps = function() {
                return {
                    Enter: this.commands()()
                }
            }, t
        }(fl),
        Mg = Qa("contents"),
        Sg = function(e) {
            function t(t, n) {
                var r = e.call(this, t) || this,
                    o = n.toDOMAdaptor,
                    i = n.htmlSchemaMap,
                    s = void 0 === i ? {} : i,
                    a = n.linkAttributes,
                    l = void 0 === a ? {} : a,
                    c = n.useCommandShortcut,
                    u = void 0 === c || c,
                    d = n.wwPlugins,
                    p = void 0 === d ? [] : d,
                    h = n.wwNodeViews,
                    f = void 0 === h ? {} : h;
                return r.editorType = "wysiwyg", r.el.classList.add("ww-mode"), r.toDOMAdaptor = o, r.linkAttributes = l, r.extraPlugins = p, r.pluginNodeViews = f, r.specs = r.createSpecs(), r.schema = r.createSchema(s), r.context = r.createContext(), r.keymaps = r.createKeymaps(u), r.view = r.createView(), r.commands = r.createCommands(), r.specs.setContext($i($i({}, r.context), {
                    view: r.view
                })), r.initEvent(), r
            }
            return ji(t, e), t.prototype.createSpecs = function() {
                return e = this.linkAttributes, new xl([new Km, new Gm, new Zm, new Qm, new Ym, new eg, new tg, new ng, new rg, new cg, new ug, new dg, new pg, new hg, new fg, new mg, new gg, new vg, new yg, new bg, new wg(e), new kg, new xg, new Cg, new vl, new Tg]);
                var e
            }, t.prototype.createContext = function() {
                return {
                    schema: this.schema,
                    eventEmitter: this.eventEmitter
                }
            }, t.prototype.createSchema = function(e) {
                return new Z({
                    nodes: $i($i({}, this.specs.nodes), e.nodes),
                    marks: $i($i({}, this.specs.marks), e.marks)
                })
            }, t.prototype.createPlugins = function() {
                return _i([new wt({
                    key: hm,
                    state: {
                        init: function() {
                            return null
                        },
                        apply: function(e, t) {
                            var n = e.getMeta(hm);
                            if (n) return -1 === n ? null : n;
                            if (Ts(t) || !e.docChanged) return t;
                            var r = e.mapping.mapResult(t),
                                o = r.deleted,
                                i = r.pos;
                            return o ? null : i
                        }
                    },
                    props: {
                        decorations: gm,
                        createSelectionBetween: function(e) {
                            var t = e.state;
                            return Ts(hm.getState(t)) ? null : t.selection
                        }
                    },
                    view: function(e) {
                        return new fm(e)
                    }
                }), (e = this.eventEmitter, new wt({
                    props: {
                        handleDOMEvents: {
                            contextmenu: function(t, n) {
                                var r = am(n.target, t.dom);
                                if (r) {
                                    n.preventDefault();
                                    var o = n,
                                        i = o.clientX,
                                        s = o.clientY,
                                        a = t.dom.parentNode.getBoundingClientRect(),
                                        l = a.left,
                                        c = a.top,
                                        u = "TH" === r.nodeName;
                                    return e.emit("contextmenu", {
                                        pos: {
                                            left: i - l + 10 + "px",
                                            top: s - c + 30 + "px"
                                        },
                                        menuGroups: xm(e, u),
                                        tableCell: r
                                    }), !0
                                }
                                return !1
                            }
                        }
                    }
                })), new wt({
                    props: {
                        handleDOMEvents: {
                            mousedown: function(e, t) {
                                var n = t,
                                    r = n.clientX,
                                    o = n.clientY,
                                    i = e.posAtCoords({
                                        left: r,
                                        top: o
                                    });
                                if (i) {
                                    var s = e.state,
                                        a = s.doc,
                                        l = s.tr,
                                        c = a.resolve(i.pos),
                                        u = _f(c),
                                        d = t.target,
                                        p = getComputedStyle(d, ":before"),
                                        h = t,
                                        f = h.offsetX,
                                        m = h.offsetY;
                                    if (!u || !Xa(p, f, m)) return !1;
                                    t.preventDefault();
                                    var g = c.before(u.depth),
                                        v = u.node.attrs;
                                    return l.setNodeMarkup(g, null, $i($i({}, v), {
                                        checked: !v.checked
                                    })), e.dispatch(l), !0
                                }
                                return !1
                            }
                        }
                    }
                }), Em(this.eventEmitter)], this.createPluginProps()).concat(this.defaultPlugins);
                var e
            }, t.prototype.createPluginNodeViews = function() {
                var e = this.eventEmitter,
                    t = this.pluginNodeViews,
                    n = {};
                return t && Object.keys(t).forEach(function(r) {
                    n[r] = function(n, o, i) {
                        return t[r](n, o, i, e)
                    }
                }), n
            }, t.prototype.createView = function() {
                var e = this,
                    t = this.toDOMAdaptor,
                    n = this.eventEmitter;
                return new Ao(this.el, {
                    state: this.createState(),
                    attributes: {
                        class: Mg
                    },
                    nodeViews: $i({
                        customBlock: function(e, n, r) {
                            return new Nm(e, n, r, t)
                        },
                        image: function(e, t, r) {
                            return new Dm(e, t, r, n)
                        },
                        codeBlock: function(e, t, r) {
                            return new Am(e, t, r, n)
                        },
                        widget: ml
                    }, this.createPluginNodeViews()),
                    dispatchTransaction: function(t) {
                        var n = e.view.state.applyTransaction(t).state;
                        e.view.updateState(n), e.emitChangeEvent(t.scrollIntoView()), e.eventEmitter.emit("setFocusedNode", n.selection.$from.node(1))
                    },
                    transformPastedHTML: qm,
                    transformPasted: function(t) {
                        return function(e, t, n) {
                            var r = [],
                                o = e.content,
                                i = e.openStart,
                                s = e.openEnd;
                            return o.forEach(function(e) {
                                if ("table" === e.type.name) {
                                    var o = um(new f(l.from(e), 0, 0));
                                    if (o) {
                                        var i = _m(o),
                                            s = "tableBody" === o.firstChild.type.name,
                                            a = function(e, t, n, r) {
                                                var o = function(e) {
                                                    return e.reduce(function(e, t) {
                                                        return e.childCount > t.childCount ? e : t
                                                    }).childCount
                                                }(e);
                                                if (n && r) return t.nodes.table.create(null, [Wm(e, o, t)]);
                                                var i = e[0],
                                                    s = e.slice(1),
                                                    a = [Um(i, 0, t)];
                                                return s.length && a.push(Wm(s, o, t)), t.nodes.table.create(null, a)
                                            }(i, t, s, n);
                                        r.push(a)
                                    }
                                } else r.push(e)
                            }), new f(l.from(r), i, s)
                        }(t, e.schema, $f(e.view.state.selection.$from))
                    },
                    handlePaste: function(e, t, n) {
                        return function(e, t) {
                            var n = e.state,
                                r = n.selection,
                                o = n.schema,
                                i = n.tr,
                                s = cm(r),
                                a = s.anchor,
                                l = s.head;
                            if (a && l) {
                                var c = um(t);
                                if (!c) return !1;
                                var u = tm.create(a),
                                    d = u.getRectOffsets(a, l),
                                    p = function(e, t, n) {
                                        var r = [],
                                            o = _m(e),
                                            i = (o[0].childCount, o.length),
                                            s = 0 === t.startRowIdx,
                                            a = o.slice(0, i);
                                        if (s) {
                                            var l = a.shift();
                                            if (l) {
                                                var c = jm(l, 0, n).content;
                                                r.push(c)
                                            }
                                        }
                                        return a.forEach(function(e) {
                                            if (!e.attrs.dummyRowForPasting) {
                                                var t = $m(e, 0, n).content;
                                                r.push(t)
                                            }
                                        }), r
                                    }(c, d, o),
                                    h = function(e, t, n) {
                                        for (var r = t.startRowIdx, o = t.startColIdx, i = n.length, s = 0, a = function(e) {
                                                var t = n[e].childCount;
                                                n[e].forEach(function(e) {
                                                    var n = e.attrs.colspan;
                                                    n > 1 && (t += n - 1)
                                                }), s = Math.max(s, t)
                                            }, l = 0; l < i; l += 1) a(l);
                                        var c = r + i - 1,
                                            u = o + s - 1;
                                        return {
                                            startRowIdx: r,
                                            startColIdx: o,
                                            endRowIdx: c,
                                            endColIdx: u,
                                            addedRowCount: Math.max(c + 1 - e.totalRowCount, 0),
                                            addedColumnCount: Math.max(u + 1 - e.totalColumnCount, 0)
                                        }
                                    }(u, d, p),
                                    m = [];
                                return function(e, t) {
                                    var n = dm(e.getSpannedOffsets(t)),
                                        r = n.rowCount,
                                        o = n.columnCount,
                                        i = dm(t),
                                        s = i.rowCount,
                                        a = i.columnCount;
                                    return r === s && o === a
                                }(u, h) && (function(e, t) {
                                    for (var n = e.startRowIdx, r = e.startColIdx, o = e.endRowIdx, i = e.endColIdx, s = e.addedRowCount, a = e.addedColumnCount, l = n; l <= o - s; l += 1) t.push({
                                        rowIdx: l,
                                        startColIdx: r,
                                        endColIdx: i - a
                                    })
                                }(h, m), h.addedColumnCount && function(e, t, n, r, o) {
                                    for (var i = r.startRowIdx, s = r.startColIdx, a = r.endRowIdx, l = r.endColIdx, c = r.addedRowCount, u = r.addedColumnCount, d = n.totalRowCount, p = 0, h = 0; h < d; h += 1) {
                                        var f = n.getCellInfo(h, l - u),
                                            m = f.offset,
                                            g = f.nodeSize,
                                            v = e.mapping.map(m + g),
                                            y = sm(u, h, t);
                                        if (e.insert(v, y), h >= i && h <= a - c) {
                                            var b = n.getCellInfo(h, l - u),
                                                w = e.mapping.map(b.offset),
                                                k = v + Jm(u);
                                            o[p] = {
                                                rowIdx: h,
                                                startColIdx: s,
                                                endColIdx: l,
                                                dummyOffsets: [w, k]
                                            }, p += 1
                                        }
                                    }
                                }(i, o, u, h, m), h.addedRowCount && function(e, t, n, r, o) {
                                    var i = r.addedRowCount,
                                        s = r.addedColumnCount,
                                        a = r.startColIdx,
                                        l = r.endColIdx,
                                        c = e.mapping.maps.length,
                                        u = n.tableEndOffset - 2,
                                        d = im(i, n.totalColumnCount + s, t),
                                        p = u;
                                    e.insert(e.mapping.slice(c).map(p), d);
                                    for (var h = 0; h < i; h += 1) {
                                        var f = p + Jm(a) + 1,
                                            m = p + Jm(l + 1) + 1,
                                            g = p + Jm(n.totalColumnCount + s) + 2;
                                        o.push({
                                            rowIdx: h + n.totalRowCount,
                                            startColIdx: a,
                                            endColIdx: l,
                                            dummyOffsets: [f, m]
                                        }), p = g
                                    }
                                }(i, o, u, h, m), function(e, t, n, r) {
                                    var o = e.mapping.maps.length;
                                    n.forEach(function(n, i) {
                                        var s = n.rowIdx,
                                            a = n.startColIdx,
                                            l = n.endColIdx,
                                            c = n.dummyOffsets,
                                            u = e.mapping.slice(o),
                                            d = new f(t[i], 0, 0),
                                            p = c ? c[0] : r.getCellStartOffset(s, a),
                                            h = c ? c[1] : r.getCellEndOffset(s, l);
                                        e.replace(u.map(p), u.map(h), d)
                                    })
                                }(i, p, m, u), e.dispatch(i), function(e, t, n) {
                                    var r = e.state,
                                        o = r.tr,
                                        i = r.doc,
                                        s = tm.create(i.resolve(n)),
                                        a = t[0],
                                        l = a.rowIdx,
                                        c = a.startColIdx,
                                        u = Ks(t),
                                        d = u.rowIdx,
                                        p = u.endColIdx,
                                        h = s.getCellInfo(l, c).offset,
                                        f = s.getCellInfo(d, p).offset;
                                    e.dispatch(o.setSelection(new om(i.resolve(h), i.resolve(f))))
                                }(e, m, u.getCellInfo(0, 0).offset)), !0
                            }
                            return !1
                        }(e, n)
                    },
                    handleKeyDown: function(t, n) {
                        return e.eventEmitter.emit("keydown", e.editorType, n), !1
                    },
                    handleDOMEvents: {
                        paste: function(t, n) {
                            var r = n.clipboardData || window.clipboardData,
                                o = null == r ? void 0 : r.items;
                            if (o) {
                                var i = na(o).some(function(e) {
                                    return "string" === e.kind && "text/rtf" === e.type
                                });
                                if (!i) {
                                    var s = pl(o);
                                    s && (n.preventDefault(), dl(e.eventEmitter, s, n.type))
                                }
                            }
                            return !1
                        },
                        keyup: function(t, n) {
                            return e.eventEmitter.emit("keyup", e.editorType, n), !1
                        },
                        scroll: function() {
                            return e.eventEmitter.emit("scroll", "editor"), !0
                        }
                    }
                })
            }, t.prototype.createCommands = function() {
                return this.specs.commands(this.view, Yf())
            }, t.prototype.getHTML = function() {
                return ll(this.view.dom.innerHTML)
            }, t.prototype.getModel = function() {
                return this.view.state.doc
            }, t.prototype.getSelection = function() {
                var e = this.view.state.selection;
                return [e.from, e.to]
            }, t.prototype.getSchema = function() {
                return this.view.state.schema
            }, t.prototype.replaceSelection = function(e, t, n) {
                var r = this.view.state,
                    o = r.schema,
                    i = r.tr,
                    s = e.split("\n").map(function(e) {
                        return ra(o, La(e, o))
                    }),
                    a = new f(l.from(s), 1, 1),
                    c = Cs(t) && Cs(n) ? i.replaceRange(t, n, a) : i.replaceSelection(a);
                this.view.dispatch(c), this.focus()
            }, t.prototype.deleteSelection = function(e, t) {
                var n = this.view.state.tr,
                    r = Cs(e) && Cs(t) ? n.deleteRange(e, t) : n.deleteSelection();
                this.view.dispatch(r.scrollIntoView())
            }, t.prototype.getSelectedText = function(e, t) {
                var n = this.view.state,
                    r = n.doc,
                    o = n.selection,
                    i = o.from,
                    s = o.to;
                return Cs(e) && Cs(t) && (i = e, s = t), r.textBetween(i, s, "\n")
            }, t.prototype.setModel = function(e, t) {
                void 0 === t && (t = !1);
                var n = this.view.state,
                    r = n.tr,
                    o = n.doc;
                this.view.dispatch(r.replaceWith(0, o.content.size, e)), t && this.moveCursorToEnd(!0)
            }, t.prototype.setSelection = function(e, t) {
                void 0 === t && (t = e);
                var n = this.view.state.tr,
                    r = ia(n, e, t);
                this.view.dispatch(n.setSelection(r).scrollIntoView())
            }, t.prototype.addWidget = function(e, t, n) {
                var r = this.view,
                    o = r.dispatch,
                    i = r.state;
                o(i.tr.setMeta("widget", {
                    pos: null != n ? n : i.selection.to,
                    node: e,
                    style: t
                }))
            }, t.prototype.replaceWithWidget = function(e, t, n) {
                var r = this.view.state,
                    o = r.tr,
                    i = La(n, r.schema);
                this.view.dispatch(o.replaceWith(e, t, i))
            }, t.prototype.getRangeInfoOfNode = function(e) {
                var t = this.view.state,
                    n = t.doc,
                    r = t.selection,
                    o = e ? n.resolve(e) : r.$from,
                    i = o.marks(),
                    s = o.node(),
                    a = o.start(),
                    l = o.end(),
                    c = s.type.name;
                if (i.length || "paragraph" === c) {
                    var u = i[i.length - 1];
                    c = u ? u.type.name : "text", s.forEach(function(e, t) {
                        var n = e.isText,
                            r = e.nodeSize,
                            i = e.marks,
                            s = o.pos - a;
                        n && t <= s && t + r >= s && function(e) {
                            return !e.length || zs(e, u)
                        }(i) && (l = (a += t) + r)
                    })
                }
                return {
                    range: [a, l],
                    type: c
                }
            }, t
        }(yl),
        Eg = as,
        Ng = Ts,
        Og = function(e) {
            return !(t = e, Eg(t) || Ng(t) || !1 === e);
            var t
        },
        Dg = ["afterPreviewRender", "updatePreview", "changeMode", "needChangeMode", "command", "changePreviewStyle", "changePreviewTabPreview", "changePreviewTabWrite", "scroll", "contextmenu", "show", "hide", "changeLanguage", "changeToolbarState", "toggleScrollSync", "mixinTableOffsetMapPrototype", "setFocusedNode", "removePopupWidget", "query", "openPopup", "closePopup", "addImageBlobHook", "beforePreviewRender", "beforeConvertWysiwygToMarkdown", "load", "loadUI", "change", "caretChange", "destroy", "focus", "blur", "keydown", "keyup"],
        Ag = function() {
            function e() {
                var e = this;
                this.events = new vm, this.eventTypes = Dg.reduce(function(e, t) {
                    return $i($i({}, e), {
                        type: t
                    })
                }, {}), this.hold = !1, Dg.forEach(function(t) {
                    e.addEventType(t)
                })
            }
            return e.prototype.listen = function(e, t) {
                var n = this.getTypeInfo(e),
                    r = this.events.get(n.type) || [];
                if (!this.hasEventType(n.type)) throw new Error("There is no event type " + n.type);
                n.namespace && (t.namespace = n.namespace), r.push(t), this.events.set(n.type, r)
            }, e.prototype.emit = function(e) {
                for (var t = [], n = 1; n < arguments.length; n++) t[n - 1] = arguments[n];
                var r = this.getTypeInfo(e),
                    o = this.events.get(r.type),
                    i = [];
                return !this.hold && o && o.forEach(function(e) {
                    var n = e.apply(void 0, t);
                    as(n) || i.push(n)
                }), i
            }, e.prototype.emitReduce = function(e, t) {
                for (var n = [], r = 2; r < arguments.length; r++) n[r - 2] = arguments[r];
                var o = this.events.get(e);
                return !this.hold && o && o.forEach(function(e) {
                    var r = e.apply(void 0, _i([t], n));
                    !Og(r) || (t = r)
                }), t
            }, e.prototype.getTypeInfo = function(e) {
                var t = e.split(".");
                return {
                    type: t[0],
                    namespace: t[1]
                }
            }, e.prototype.hasEventType = function(e) {
                return !as(this.eventTypes[this.getTypeInfo(e).type])
            }, e.prototype.addEventType = function(e) {
                if (this.hasEventType(e)) throw new Error("There is already have event type " + e);
                this.eventTypes[e] = e
            }, e.prototype.removeEventHandler = function(e, t) {
                var n = this,
                    r = this.getTypeInfo(e),
                    o = r.type,
                    i = r.namespace;
                o && t ? this.removeEventHandlerWithHandler(o, t) : o && !i ? this.events.delete(o) : !o && i ? this.events.forEach(function(e, t) {
                    n.removeEventHandlerWithTypeInfo(t, i)
                }) : o && i && this.removeEventHandlerWithTypeInfo(o, i)
            }, e.prototype.removeEventHandlerWithHandler = function(e, t) {
                var n = this.events.get(e);
                if (n) {
                    var r = n.indexOf(t);
                    n.indexOf(t) >= 0 && n.splice(r, 1)
                }
            }, e.prototype.removeEventHandlerWithTypeInfo = function(e, t) {
                var n = [],
                    r = this.events.get(e);
                r && (r.map(function(e) {
                    return e.namespace !== t && n.push(e), null
                }), this.events.set(e, n))
            }, e.prototype.getEvents = function() {
                return this.events
            }, e.prototype.holdEventInvoke = function(e) {
                this.hold = !0, e(), this.hold = !1
            }, e
        }(),
        Lg = function() {
            function e(e, t, n, r) {
                this.eventEmitter = e, this.mdCommands = t, this.wwCommands = n, this.getEditorType = r, this.initEvent()
            }
            return e.prototype.initEvent = function() {
                var e = this;
                this.eventEmitter.listen("command", function(t, n) {
                    e.exec(t, n)
                })
            }, e.prototype.addCommand = function(e, t, n) {
                "markdown" === e ? this.mdCommands[t] = n : this.wwCommands[t] = n
            }, e.prototype.deleteCommand = function(e, t) {
                "markdown" === e ? delete this.mdCommands[t] : delete this.wwCommands[t]
            }, e.prototype.exec = function(e, t) {
                "markdown" === this.getEditorType() ? this.mdCommands[e](t) : this.wwCommands[e](t)
            }, e
        }();

    function Ig(e) {
        return "\n" === e[e.length - 1] ? e.slice(0, e.length - 1) : e
    }

    function Rg(e, t) {
        var n = e.schema,
            r = t.literal.match(Wa);
        if (r) {
            var o = r[1],
                i = r[3],
                s = (o || i).toLowerCase();
            return "htmlInline" === t.type && !(!n.marks[s] && !n.nodes[s])
        }
        return !1
    }

    function Pg(e) {
        return zs(["text", "strong", "emph", "strike", "image", "link", "code"], e.type)
    }

    function Bg(e) {
        return "softbreak" === (null == e ? void 0 : e.type)
    }

    function Fg(e) {
        var t = e.type,
            n = e.literal,
            r = "htmlInline" === t && n.match(Wa);
        if (r) {
            var o = r[1],
                i = r[3],
                s = o || i;
            if (s) return zs(["ul", "ol", "li"], s.toLowerCase())
        }
        return !1
    }

    function Hg(e) {
        for (var t = [], n = 1; n < arguments.length; n++) t[n - 1] = arguments[n];
        var r = document.createElement("div");
        r.innerHTML = wf(e);
        var o = r.firstChild;
        return t.map(function(e) {
            return o.getAttribute(e) || ""
        })
    }
    var zg = {
            "b, strong": function(e, t, n) {
                var r = e.schema.marks.strong;
                n ? e.openMark(r.create({
                    rawHTML: n
                })) : e.closeMark(r)
            },
            "i, em": function(e, t, n) {
                var r = e.schema.marks.emph;
                n ? e.openMark(r.create({
                    rawHTML: n
                })) : e.closeMark(r)
            },
            "s, del": function(e, t, n) {
                var r = e.schema.marks.strike;
                n ? e.openMark(r.create({
                    rawHTML: n
                })) : e.closeMark(r)
            },
            code: function(e, t, n) {
                var r = e.schema.marks.code;
                n ? e.openMark(r.create({
                    rawHTML: n
                })) : e.closeMark(r)
            },
            a: function(e, t, n) {
                var r = t.literal,
                    o = e.schema.marks.link;
                if (n) {
                    var i = Hg(r, "href")[0];
                    e.openMark(o.create({
                        linkUrl: i,
                        rawHTML: n
                    }))
                } else e.closeMark(o)
            },
            img: function(e, t, n) {
                var r = t.literal;
                if (n) {
                    var o = Hg(r, "src", "alt"),
                        i = o[0],
                        s = o[1],
                        a = e.schema.nodes.image;
                    e.addNode(a, $i({
                        rawHTML: n,
                        imageUrl: i
                    }, s && {
                        altText: s
                    }))
                }
            },
            hr: function(e, t, n) {
                e.addNode(e.schema.nodes.thematicBreak, {
                    rawHTML: n
                })
            },
            br: function(e, t) {
                var n = e.schema.nodes.paragraph,
                    r = t.parent,
                    o = t.prev,
                    i = t.next;
                "paragraph" === (null == r ? void 0 : r.type) ? (Bg(o) && e.openNode(n), Bg(i) ? e.closeNode() : i && (e.closeNode(), e.openNode(n))) : "tableCell" === (null == r ? void 0 : r.type) && (o && (Pg(o) || Rg(e, o)) && e.closeNode(), i && (Pg(i) || Rg(e, i)) && e.openNode(n))
            },
            pre: function(e, t, n) {
                var r, o, i = document.createElement("div");
                i.innerHTML = t.literal;
                var s = null === (o = null === (r = i.firstChild) || void 0 === r ? void 0 : r.firstChild) || void 0 === o ? void 0 : o.textContent;
                e.openNode(e.schema.nodes.codeBlock, {
                    rawHTML: n
                }), e.addText(Ig(s)), e.closeNode()
            },
            "ul, ol": function(e, t, n) {
                if ("tableCell" === t.parent.type) {
                    var r = e.schema.nodes,
                        o = r.bulletList,
                        i = r.orderedList,
                        s = r.paragraph,
                        a = "ul" === n ? o : i;
                    n ? (t.prev && !Fg(t.prev) && e.closeNode(), e.openNode(a, {
                        rawHTML: n
                    })) : (e.closeNode(), t.next && !Fg(t.next) && e.openNode(s))
                }
            },
            li: function(e, t, n) {
                var r;
                if ("tableCell" === (null === (r = t.parent) || void 0 === r ? void 0 : r.type)) {
                    var o = e.schema.nodes,
                        i = o.listItem,
                        s = o.paragraph;
                    if (n) {
                        var a = function(e) {
                            var t = e.literal;
                            return {
                                task: /data-task/.test(t),
                                checked: /data-task-checked/.test(t)
                            }
                        }(t);
                        t.prev && !Fg(t.prev) && e.closeNode(), e.openNode(i, $i({
                            rawHTML: n
                        }, a)), t.next && !Fg(t.next) && e.openNode(s)
                    } else t.prev && !Fg(t.prev) && e.closeNode(), e.closeNode()
                }
            }
        },
        qg = function(e) {
            var t = {};
            return Object.keys(e).forEach(function(n) {
                n.split(", ").forEach(function(r) {
                    var o = r.toLowerCase();
                    t[o] = e[n]
                })
            }), t
        }(zg);

    function Vg(e) {
        return "htmlInline" === e.type && Ja.test(e.literal)
    }

    function jg(e) {
        na(e.childNodes).forEach(function(e) {
            if (el(e)) {
                var t = e.nodeName.toLowerCase();
                e.setAttribute("data-raw-html", t), e.childNodes && jg(e)
            }
        })
    }
    var $g = {
            text: function(e, t) {
                e.addText(t.literal || "")
            },
            paragraph: function(e, t, n, r) {
                var o;
                if (n.entering) {
                    var i = e.schema.nodes.paragraph;
                    "paragraph" === (null === (o = t.prev) || void 0 === o ? void 0 : o.type) && (e.openNode(i, r), e.closeNode()), e.openNode(i, r)
                } else e.closeNode()
            },
            heading: function(e, t, n, r) {
                if (n.entering) {
                    var o = t,
                        i = o.level,
                        s = o.headingType;
                    e.openNode(e.schema.nodes.heading, $i({
                        level: i,
                        headingType: s
                    }, r))
                } else e.closeNode()
            },
            codeBlock: function(e, t, n) {
                var r = e.schema.nodes.codeBlock,
                    o = t,
                    i = o.info,
                    s = o.literal;
                e.openNode(r, $i({
                    language: i
                }, n)), e.addText(Ig(s || "")), e.closeNode()
            },
            list: function(e, t, n, r) {
                if (n.entering) {
                    var o = e.schema.nodes,
                        i = o.bulletList,
                        s = o.orderedList,
                        a = t.listData,
                        l = a.type,
                        c = a.start;
                    "bullet" === l ? e.openNode(i, r) : e.openNode(s, $i({
                        order: c
                    }, r))
                } else e.closeNode()
            },
            item: function(e, t, n, r) {
                var o = n.entering,
                    i = e.schema.nodes.listItem,
                    s = t.listData,
                    a = s.task,
                    l = s.checked;
                if (o) {
                    var c = $i($i($i({}, a && {
                        task: a
                    }), l && {
                        checked: l
                    }), r);
                    e.openNode(i, c)
                } else e.closeNode()
            },
            blockQuote: function(e, t, n, r) {
                n.entering ? e.openNode(e.schema.nodes.blockQuote, r) : e.closeNode()
            },
            image: function(e, t, n, r) {
                var o = n.entering,
                    i = n.skipChildren,
                    s = e.schema.nodes.image,
                    a = t,
                    l = a.destination,
                    c = a.firstChild;
                o && i && i(), e.addNode(s, $i($i({
                    imageUrl: l
                }, c && {
                    altText: c.literal
                }), r))
            },
            thematicBreak: function(e, t, n, r) {
                e.addNode(e.schema.nodes.thematicBreak, r)
            },
            strong: function(e, t, n, r) {
                var o = n.entering,
                    i = e.schema.marks.strong;
                o ? e.openMark(i.create(r)) : e.closeMark(i)
            },
            emph: function(e, t, n, r) {
                var o = n.entering,
                    i = e.schema.marks.emph;
                o ? e.openMark(i.create(r)) : e.closeMark(i)
            },
            link: function(e, t, n, r) {
                var o = n.entering,
                    i = e.schema.marks.link,
                    s = t,
                    a = s.destination,
                    l = s.title;
                if (o) {
                    var c = $i({
                        linkUrl: a,
                        title: l
                    }, r);
                    e.openMark(i.create(c))
                } else e.closeMark(i)
            },
            softbreak: function(e, t) {
                if ("paragraph" === t.parent.type) {
                    var n = t.prev,
                        r = t.next;
                    n && !Vg(n) && e.closeNode(), r && !Vg(r) && e.openNode(e.schema.nodes.paragraph)
                }
            },
            table: function(e, t, n, r) {
                n.entering ? e.openNode(e.schema.nodes.table, r) : e.closeNode()
            },
            tableHead: function(e, t, n, r) {
                n.entering ? e.openNode(e.schema.nodes.tableHead, r) : e.closeNode()
            },
            tableBody: function(e, t, n, r) {
                n.entering ? e.openNode(e.schema.nodes.tableBody, r) : e.closeNode()
            },
            tableRow: function(e, t, n, r) {
                n.entering ? e.openNode(e.schema.nodes.tableRow, r) : e.closeNode()
            },
            tableCell: function(e, t, n) {
                var r = n.entering;
                if (!t.ignored) {
                    var o = function(t) {
                        return t && (Pg(t) || Rg(e, t))
                    };
                    if (r) {
                        var i = e.schema.nodes,
                            s = i.tableHeadCell,
                            a = i.tableBodyCell,
                            l = i.paragraph,
                            c = t.parent.parent,
                            u = "tableHead" === c.type ? s : a,
                            d = (c.parent.columns[t.startIdx] || {}).align,
                            p = $i({}, t.attrs);
                        d && (p.align = d), e.openNode(u, p), o(t.firstChild) && e.openNode(l)
                    } else o(t.lastChild) && e.closeNode(), e.closeNode()
                }
            },
            strike: function(e, t, n, r) {
                var o = n.entering,
                    i = e.schema.marks.strike;
                o ? e.openMark(i.create(r)) : e.closeMark(i)
            },
            code: function(e, t, n, r) {
                var o = e.schema.marks.code;
                e.openMark(o.create(r)), e.addText(Ig(t.literal || "")), e.closeMark(o)
            },
            customBlock: function(e, t) {
                var n = e.schema.nodes,
                    r = n.customBlock,
                    o = n.paragraph,
                    i = t,
                    s = i.info,
                    a = i.literal;
                e.openNode(r, {
                    info: s
                }), e.addText(Ig(a || "")), e.closeNode(), t.next || (e.openNode(o), e.closeNode())
            },
            frontMatter: function(e, t) {
                e.openNode(e.schema.nodes.frontMatter), e.addText(t.literal), e.closeNode()
            },
            htmlInline: function(e, t) {
                var n = t.literal,
                    r = n.match(Wa),
                    o = r[1],
                    i = r[3],
                    s = (o || i).toLowerCase(),
                    a = e.schema.marks[s],
                    l = wf(n);
                if (null == a ? void 0 : a.spec.attrs.htmlInline)
                    if (o) {
                        var c = xf(l);
                        e.openMark(a.create({
                            htmlAttrs: c
                        }))
                    } else e.closeMark(a);
                else {
                    var u = qg[s];
                    u && u(e, t, o)
                }
            },
            htmlBlock: function(e, t) {
                var n = t.literal,
                    r = document.createElement("div");
                if (Ka.test(n)) e.openNode(e.schema.nodes.htmlComment), e.addText(t.literal), e.closeNode();
                else {
                    var o = n.match(Wa),
                        i = o[1],
                        s = o[3],
                        a = (i || s).toLowerCase(),
                        l = e.schema.nodes[a],
                        c = wf(n);
                    if (null == l ? void 0 : l.spec.attrs.htmlBlock) {
                        var u = xf(c),
                            d = kf(t, a);
                        e.addNode(l, {
                            htmlAttrs: u,
                            childrenHTML: d
                        })
                    } else r.innerHTML = c, jg(r), e.convertByDOMParser(r)
                }
            },
            customInline: function(e, t, n) {
                var r = n.entering,
                    o = n.skipChildren,
                    i = t,
                    s = i.info,
                    a = i.firstChild,
                    l = e.schema;
                if (-1 !== s.indexOf("widget") && r) {
                    var c = Ia(t);
                    o(), e.addNode(l.nodes.widget, {
                        info: s
                    }, [l.text(Na(s, c))])
                } else {
                    var u = "$$";
                    r && (u += a ? s + " " : s), e.addText(u)
                }
            }
        },
        _g = function() {
            function e(e, t) {
                this.schema = e, this.convertors = t, this.stack = [{
                    type: this.schema.topNodeType,
                    attrs: null,
                    content: []
                }], this.marks = p.none
            }
            return e.prototype.top = function() {
                return Ks(this.stack)
            }, e.prototype.push = function(e) {
                this.stack.length && this.top().content.push(e)
            }, e.prototype.addText = function(e) {
                if (e) {
                    var t = this.top().content,
                        n = Ks(t),
                        r = this.schema.text(e, this.marks),
                        o = n && (s = r, !!((i = n).isText && s.isText && p.sameSet(i.marks, s.marks)) && i.withText(i.text + s.text));
                    o ? t[t.length - 1] = o : t.push(r)
                }
                var i, s
            }, e.prototype.openMark = function(e) {
                this.marks = e.addToSet(this.marks)
            }, e.prototype.closeMark = function(e) {
                this.marks = e.removeFromSet(this.marks)
            }, e.prototype.addNode = function(e, t, n) {
                var r = e.createAndFill(t, n, this.marks);
                return r ? (this.push(r), r) : null
            }, e.prototype.openNode = function(e, t) {
                this.stack.push({
                    type: e,
                    attrs: t,
                    content: []
                })
            }, e.prototype.closeNode = function() {
                this.marks.length && (this.marks = p.none);
                var e = this.stack.pop(),
                    t = e.type,
                    n = e.attrs,
                    r = e.content;
                return this.addNode(t, n, r)
            }, e.prototype.convertByDOMParser = function(e) {
                var t = this;
                Y.fromSchema(this.schema).parse(e).content.forEach(function(e) {
                    return t.push(e)
                })
            }, e.prototype.closeUnmatchedHTMLInline = function(e, t) {
                var n;
                if (!t && "htmlInline" !== e.type)
                    for (var r = this.stack.length - 1; r >= 0; r -= 1) {
                        var o = this.stack[r];
                        if (!(null === (n = o.attrs) || void 0 === n ? void 0 : n.rawHTML)) break;
                        o.content.length ? this.closeNode() : this.stack.pop()
                    }
            }, e.prototype.convert = function(e, t) {
                for (var n = e.walker(), r = n.next(), o = function() {
                        var e = r.node,
                            o = r.entering,
                            s = i.convertors[e.type],
                            a = !1;
                        if (s) {
                            var l = {
                                entering: o,
                                leaf: !xa(e),
                                getChildrenText: Ca,
                                options: {
                                    gfm: !0,
                                    nodeId: !1,
                                    tagFilter: !1,
                                    softbreak: "\n"
                                },
                                skipChildren: function() {
                                    a = !0
                                }
                            };
                            if (i.closeUnmatchedHTMLInline(e, o), s(i, e, l), (null == t ? void 0 : t.node) === e) {
                                var c = i.stack.reduce(function(e, t) {
                                    return e + t.content.reduce(function(e, t) {
                                        return e + t.nodeSize
                                    }, 0)
                                }, 0) + 1;
                                t.setMappedPos(c)
                            }
                        }
                        a && (n.resumeAt(e, !1), n.next()), r = n.next()
                    }, i = this; r;) o()
            }, e.prototype.convertNode = function(e, t) {
                return this.convert(e, t), this.stack.length ? this.closeNode() : null
            }, e
        }(),
        Ug = {
            text: function(e, t) {
                var n, r = t.node,
                    o = null !== (n = r.text) && void 0 !== n ? n : "";
                (r.marks || []).some(function(e) {
                    return "link" === e.type.name
                }) ? e.text(_s(o), !1) : e.text(o)
            },
            paragraph: function(e, t) {
                var n = t.node,
                    r = t.parent,
                    o = t.index,
                    i = void 0 === o ? 0 : o;
                if (e.stopNewline) e.convertInline(n);
                else {
                    var s = 0 === i,
                        a = !s && r.child(i - 1),
                        l = a && 0 === a.childCount,
                        c = i < r.childCount - 1 && r.child(i + 1),
                        u = c && "paragraph" === c.type.name,
                        d = 0 === n.childCount;
                    if (d && l) e.write("<br>\n");
                    else if (!d || l || s) e.convertInline(n), u ? e.write("\n") : e.closeBlock(n);
                    else {
                        if ("listItem" === (null == r ? void 0 : r.type.name)) {
                            var p = e.getDelim();
                            e.setDelim(""), e.write("<br>"), e.setDelim(p)
                        }
                        e.write("\n")
                    }
                }
            },
            heading: function(e, t, n) {
                var r = t.node,
                    o = n.delim;
                "atx" === r.attrs.headingType ? (e.write(o + " "), e.convertInline(r), e.closeBlock(r)) : (e.convertInline(r), e.ensureNewLine(), e.write(o), e.closeBlock(r))
            },
            codeBlock: function(e, t, n) {
                var r = t.node,
                    o = n.delim,
                    i = n.text,
                    s = o,
                    a = s[0],
                    l = s[1];
                e.write(a), e.ensureNewLine(), e.text(i, !1), e.ensureNewLine(), e.write(l), e.closeBlock(r)
            },
            blockQuote: function(e, t, n) {
                var r = t.node,
                    o = t.parent,
                    i = n.delim;
                (null == o ? void 0 : o.type.name) === r.type.name && e.flushClose(1), e.wrapBlock(i, null, r, function() {
                    return e.convertNode(r)
                })
            },
            bulletList: function(e, t, n) {
                var r = t.node,
                    o = n.delim;
                e.convertList(r, $s(" ", 4), function() {
                    return o + " "
                })
            },
            orderedList: function(e, t) {
                var n = t.node,
                    r = n.attrs.order || 1;
                e.convertList(n, $s(" ", 4), function(e) {
                    return String(r + e) + ". "
                })
            },
            listItem: function(e, t) {
                var n = t.node,
                    r = n.attrs,
                    o = r.task,
                    i = r.checked;
                o && e.write("[" + (i ? "x" : " ") + "] "), e.convertNode(n)
            },
            image: function(e, t, n) {
                var r = n.attrs;
                e.write("![" + (null == r ? void 0 : r.altText) + "](" + (null == r ? void 0 : r.imageUrl) + ")")
            },
            thematicBreak: function(e, t, n) {
                var r = t.node,
                    o = n.delim;
                e.write(o), e.closeBlock(r)
            },
            table: function(e, t) {
                var n = t.node;
                e.convertNode(n), e.closeBlock(n)
            },
            tableHead: function(e, t, n) {
                var r = t.node,
                    o = n.delim,
                    i = r.firstChild;
                e.convertNode(r);
                var s = null != o ? o : "";
                !o && i && i.forEach(function(e) {
                    var t, n, r, o, i, a = (t = e.textContent, n = e.attrs.align, r = t.length, o = "", i = "", "left" === n ? (o = ":", r -= 1) : "right" === n ? (i = ":", r -= 1) : "center" === n && (o = ":", i = ":", r -= 2), "" + o + $s("-", Math.max(r, 3)) + i);
                    s += "| " + a + " "
                }), e.write(s + "|"), e.ensureNewLine()
            },
            tableBody: function(e, t) {
                var n = t.node;
                e.convertNode(n)
            },
            tableRow: function(e, t) {
                var n = t.node;
                e.convertNode(n), e.write("|"), e.ensureNewLine()
            },
            tableHeadCell: function(e, t, n) {
                var r = t.node,
                    o = n.delim,
                    i = void 0 === o ? "| " : o;
                e.write(i), e.convertTableCell(r), e.write(" ")
            },
            tableBodyCell: function(e, t, n) {
                var r = t.node,
                    o = n.delim,
                    i = void 0 === o ? "| " : o;
                e.write(i), e.convertTableCell(r), e.write(" ")
            },
            customBlock: function(e, t, n) {
                var r = t.node,
                    o = n.delim,
                    i = n.text,
                    s = o,
                    a = s[0],
                    l = s[1];
                e.write(a), e.ensureNewLine(), e.text(i, !1), e.ensureNewLine(), e.write(l), e.closeBlock(r)
            },
            frontMatter: function(e, t, n) {
                var r = t.node,
                    o = n.text;
                e.text(o, !1), e.closeBlock(r)
            },
            widget: function(e, t, n) {
                var r = n.text;
                e.write(r)
            },
            html: function(e, t, n) {
                var r = t.node,
                    o = n.text;
                e.write(o), r.attrs.htmlBlock && e.closeBlock(r)
            },
            htmlComment: function(e, t, n) {
                var r = t.node,
                    o = n.text;
                e.write(o), e.closeBlock(r)
            }
        };

    function Wg(e, t) {
        var n = e.text,
            r = /`+/g,
            o = 0;
        if (e.isText && n)
            for (var i = r.exec(n); i;) o = Math.max(o, i[0].length), i = r.exec(n);
        for (var s = o > 0 && t > 0 ? " `" : "`", a = 0; a < o; a += 1) s += "`";
        return o > 0 && t < 0 && (s += " "), s
    }

    function Jg(e) {
        return e ? ["<" + e + ">", "</" + e + ">"] : null
    }

    function Kg(e) {
        return e ? "<" + e + ">" : null
    }

    function Gg(e) {
        return e ? "</" + e + ">" : null
    }
    var Xg = {
            heading: function(e) {
                var t = e.node.attrs,
                    n = t.level,
                    r = $s("#", n);
                return "setext" === t.headingType && (r = 1 === n ? "===" : "---"), {
                    delim: r,
                    rawHTML: Jg(t.rawHTML)
                }
            },
            codeBlock: function(e) {
                var t = e.node,
                    n = t.attrs,
                    r = t.textContent;
                return {
                    delim: ["```" + (n.language || ""), "```"],
                    rawHTML: Jg(n.rawHTML),
                    text: r
                }
            },
            blockQuote: function(e) {
                return {
                    delim: "> ",
                    rawHTML: Jg(e.node.attrs.rawHTML)
                }
            },
            bulletList: function(e, t) {
                var n = e.node,
                    r = t.inTable,
                    o = n.attrs.rawHTML;
                return r && (o = o || "ul"), {
                    delim: "*",
                    rawHTML: Jg(o)
                }
            },
            orderedList: function(e, t) {
                var n = e.node,
                    r = t.inTable,
                    o = n.attrs.rawHTML;
                return r && (o = o || "ol"), {
                    rawHTML: Jg(o)
                }
            },
            listItem: function(e, t) {
                var n = e.node,
                    r = t.inTable,
                    o = n.attrs,
                    i = o.task,
                    s = o.checked,
                    a = n.attrs.rawHTML;
                return r && (a = a || "li"), {
                    rawHTML: a ? ["<" + a + (i ? ' class="task-list-item' + (s ? " checked" : "") + '"' : "") + (i ? " data-task" + (s ? " data-task-checked" : "") : "") + ">", "</" + a + ">"] : null
                }
            },
            table: function(e) {
                return {
                    rawHTML: Jg(e.node.attrs.rawHTML)
                }
            },
            tableHead: function(e) {
                return {
                    rawHTML: Jg(e.node.attrs.rawHTML)
                }
            },
            tableBody: function(e) {
                return {
                    rawHTML: Jg(e.node.attrs.rawHTML)
                }
            },
            tableRow: function(e) {
                return {
                    rawHTML: Jg(e.node.attrs.rawHTML)
                }
            },
            tableHeadCell: function(e) {
                return {
                    rawHTML: Jg(e.node.attrs.rawHTML)
                }
            },
            tableBodyCell: function(e) {
                return {
                    rawHTML: Jg(e.node.attrs.rawHTML)
                }
            },
            image: function(e) {
                var t = e.node.attrs,
                    n = t.rawHTML,
                    r = t.altText,
                    o = t.imageUrl.replace(/&amp;/g, "&"),
                    i = r ? ' alt="' + Hs(r) + '"' : "";
                return {
                    rawHTML: n ? "<" + n + ' src="' + Hs(o) + '"' + i + ">" : null,
                    attrs: {
                        altText: _s(r || ""),
                        imageUrl: o
                    }
                }
            },
            thematicBreak: function(e) {
                return {
                    delim: "***",
                    rawHTML: Kg(e.node.attrs.rawHTML)
                }
            },
            customBlock: function(e) {
                var t = e.node,
                    n = t.attrs,
                    r = t.textContent;
                return {
                    delim: ["$$" + n.info, "$$"],
                    text: r
                }
            },
            frontMatter: function(e) {
                return {
                    text: e.node.textContent
                }
            },
            widget: function(e) {
                return {
                    text: e.node.textContent
                }
            },
            strong: function(e, t) {
                var n = e.node,
                    r = t.entering,
                    o = n.attrs.rawHTML;
                return {
                    delim: "**",
                    rawHTML: r ? Kg(o) : Gg(o)
                }
            },
            emph: function(e, t) {
                var n = e.node,
                    r = t.entering,
                    o = n.attrs.rawHTML;
                return {
                    delim: "*",
                    rawHTML: r ? Kg(o) : Gg(o)
                }
            },
            strike: function(e, t) {
                var n = e.node,
                    r = t.entering,
                    o = n.attrs.rawHTML;
                return {
                    delim: "~~",
                    rawHTML: r ? Kg(o) : Gg(o)
                }
            },
            link: function(e, t) {
                var n, r, o = e.node,
                    i = t.entering,
                    s = o.attrs,
                    a = s.title,
                    l = s.rawHTML,
                    c = s.linkUrl.replace(/&amp;/g, "&"),
                    u = a ? ' title="' + Hs(a) + '"' : "";
                return i ? {
                    delim: "[",
                    rawHTML: l ? "<" + l + ' href="' + Hs(c) + '"' + u + ">" : null
                } : {
                    delim: "](" + c + (a ? " " + (n = _s(a), (r = -1 === n.indexOf('"') ? '""' : -1 === n.indexOf("'") ? "''" : "()")[0] + n + r[1]) : "") + ")",
                    rawHTML: Gg(l)
                }
            },
            code: function(e, t) {
                var n = e.node,
                    r = e.parent,
                    o = e.index,
                    i = void 0 === o ? 0 : o,
                    s = t.entering;
                return {
                    delim: s ? Wg(r.child(i), -1) : Wg(r.child(i - 1), 1),
                    rawHTML: s ? Kg(n.attrs.rawHTML) : Gg(n.attrs.rawHTML)
                }
            },
            htmlComment: function(e) {
                return {
                    text: e.node.textContent
                }
            },
            html: function(e, t) {
                var n = e.node,
                    r = t.entering,
                    o = n.type.name,
                    i = n.attrs.htmlAttrs,
                    s = "<" + o,
                    a = "</" + o + ">";
                return Object.keys(i).forEach(function(e) {
                    s += " " + e + '="' + i[e].replace(/"/g, "'") + '"'
                }), s += ">", n.attrs.htmlInline ? {
                    rawHTML: r ? s : a
                } : {
                    text: "" + s + n.attrs.childrenHTML + a
                }
            }
        },
        Zg = {
            strong: {
                mixable: !0,
                removedEnclosingWhitespace: !0
            },
            emph: {
                mixable: !0,
                removedEnclosingWhitespace: !0
            },
            strike: {
                mixable: !0,
                removedEnclosingWhitespace: !0
            },
            code: {
                escape: !1
            },
            link: null,
            html: null
        };

    function Qg(e) {
        Object.keys(e).forEach(function(t) {
            var n = Xg[t],
                r = e[t];
            Xg[t] = n ? function(e, t) {
                return t.origin = function() {
                    return n(e, t)
                }, r(e, t)
            } : r, delete e[t]
        });
        var t = function(e) {
                var t = {};
                return Object.keys(Ug).forEach(function(n) {
                    t[n] = function(t, r) {
                        if (Ug[n]) {
                            var o = e[n],
                                i = o ? o(r, {
                                    inTable: t.inTable
                                }) : {};
                            ! function(e, t) {
                                var n = t.state,
                                    r = t.nodeInfo,
                                    o = t.params,
                                    i = o.rawHTML;
                                i ? ss(e, ["heading", "codeBlock"]) > -1 ? function(e, t, n) {
                                    var r = n[0],
                                        o = n[1];
                                    e.write(r), e.convertInline(t), e.write(o)
                                }(n, r.node, i) : ss(e, ["image", "thematicBreak"]) > -1 ? n.write(i) : function(e, t, n) {
                                    var r = t.node,
                                        o = t.parent,
                                        i = n[0],
                                        s = n[1];
                                    e.stopNewline = !0, e.write(i), e.convertNode(r), e.write(s), "doc" === (null == o ? void 0 : o.type.name) && (e.closeBlock(r), e.stopNewline = !1)
                                }(n, r, i) : Ug[e](n, r, o)
                            }(n, {
                                state: t,
                                nodeInfo: r,
                                params: i
                            })
                        }
                    }
                }), t
            }(Xg),
            n = function(e) {
                var t = {};
                return Object.keys(Zg).forEach(function(n) {
                    t[n] = function(t, r) {
                        var o = Zg[n],
                            i = e[n],
                            s = i && t && !as(r) ? i(t, {
                                entering: r
                            }) : {};
                        return $i($i({}, s), o)
                    }
                }), t
            }(Xg);
        return {
            nodeTypeConvertors: t,
            markTypeConvertors: n
        }
    }
    var Yg = function() {
            function e(e) {
                var t = e.nodeTypeConvertors,
                    n = e.markTypeConvertors;
                this.nodeTypeConvertors = t, this.markTypeConvertors = n, this.delim = "", this.result = "", this.closed = !1, this.tightList = !1, this.stopNewline = !1, this.inTable = !1
            }
            return e.prototype.getMarkConvertor = function(e) {
                var t = e.attrs.htmlInline ? "html" : e.type.name;
                return this.markTypeConvertors[t]
            }, e.prototype.isInBlank = function() {
                return /(^|\n)$/.test(this.result)
            }, e.prototype.markText = function(e, t, n, r) {
                var o = this.getMarkConvertor(e);
                if (o) {
                    var i = o({
                            node: e,
                            parent: n,
                            index: r
                        }, t),
                        s = i.delim;
                    return i.rawHTML || s
                }
                return ""
            }, e.prototype.setDelim = function(e) {
                this.delim = e
            }, e.prototype.getDelim = function() {
                return this.delim
            }, e.prototype.flushClose = function(e) {
                if (!this.stopNewline && this.closed) {
                    if (this.isInBlank() || (this.result += "\n"), e || (e = 2), e > 1) {
                        var t = this.delim,
                            n = /\s+$/.exec(t);
                        n && (t = t.slice(0, t.length - n[0].length));
                        for (var r = 1; r < e; r += 1) this.result += t + "\n"
                    }
                    this.closed = !1
                }
            }, e.prototype.wrapBlock = function(e, t, n, r) {
                var o = this.getDelim();
                this.write(t || e), this.setDelim(this.getDelim() + e), r(), this.setDelim(o), this.closeBlock(n)
            }, e.prototype.ensureNewLine = function() {
                this.isInBlank() || (this.result += "\n")
            }, e.prototype.write = function(e) {
                void 0 === e && (e = ""), this.flushClose(), this.delim && this.isInBlank() && (this.result += this.delim), e && (this.result += e)
            }, e.prototype.closeBlock = function(e) {
                this.closed = e
            }, e.prototype.text = function(e, t) {
                void 0 === t && (t = !0);
                for (var n = e.split("\n"), r = 0; r < n.length; r += 1) this.write(), this.result += t ? Us(n[r]) : n[r], r !== n.length - 1 && (this.result += "\n")
            }, e.prototype.convertBlock = function(e, t, n) {
                var r = e.type.name,
                    o = this.nodeTypeConvertors[r],
                    i = {
                        node: e,
                        parent: t,
                        index: n
                    };
                e.attrs.htmlBlock ? this.nodeTypeConvertors.html(this, i) : o && o(this, i)
            }, e.prototype.convertInline = function(e) {
                var t = this,
                    n = [],
                    r = "",
                    o = function(o, i, s) {
                        var a = o ? o.marks : [],
                            l = r;
                        r = "";
                        var c = o && o.isText && a.some(function(e) {
                            var n = t.getMarkConvertor(e),
                                r = n && n();
                            return r && r.removedEnclosingWhitespace
                        });
                        if (c && o && o.text) {
                            var u = /^(\s*)(.*?)(\s*)$/m.exec(o.text),
                                d = u[1],
                                p = u[2],
                                h = u[3];
                            l += d, r = h, (d || h) && ((o = p ? o.withText(p) : null) || (a = n))
                        }
                        for (var f = a.length && Ks(a), m = f && t.getMarkConvertor(f), g = m && m(), v = g && !1 === g.escape, y = a.length - (v ? 1 : 0), b = 0; b < y && (p = a[b], !g || g.mixable); b += 1)
                            for (var w = 0; w < n.length; w += 1) {
                                var k = n[w];
                                if (g && !g.mixable) break;
                                if (p.eq(k)) {
                                    b > w ? a = a.slice(0, w).concat(p).concat(a.slice(w, b)).concat(a.slice(b + 1, y)) : w > b && (a = a.slice(0, b).concat(a.slice(b + 1, w)).concat(p).concat(a.slice(w, y)));
                                    break
                                }
                            }
                        for (var x = 0; x < Math.min(n.length, y) && a[x].eq(n[x]);) x += 1;
                        for (; x < n.length;) {
                            var C = n.pop();
                            C && t.text(t.markText(C, !1, e, s), !1)
                        }
                        if (l && t.text(l), o) {
                            for (; n.length < y;) p = a[n.length], n.push(p), t.text(t.markText(p, !0, e, s), !1);
                            v && o.isText ? t.text(t.markText(f, !0, e, s) + o.text + t.markText(f, !1, e, s + 1), !1) : t.convertBlock(o, e, s)
                        }
                    };
                e.forEach(o), o(null, 0, e.childCount)
            }, e.prototype.convertList = function(e, t, n) {
                var r, o = this;
                this.closed && this.closed.type === e.type ? this.flushClose(3) : this.tightList && this.flushClose(1);
                var i = null === (r = e.attrs.tight) || void 0 === r || r,
                    s = this.tightList;
                this.tightList = i, e.forEach(function(r, s, a) {
                    a && i && o.flushClose(1), o.wrapBlock(t, n(a), e, function() {
                        return o.convertBlock(r, e, a)
                    })
                }), this.tightList = s
            }, e.prototype.convertTableCell = function(e) {
                var t = this;
                this.stopNewline = !0, this.inTable = !0, e.forEach(function(n, r, o) {
                    zs(["bulletList", "orderedList"], n.type.name) ? (t.convertBlock(n, e, o), t.closed = !1) : (t.convertInline(n), o < e.childCount - 1 && "paragraph" === e.child(o + 1).type.name && t.write("<br>"))
                }), this.stopNewline = !1, this.inTable = !1
            }, e.prototype.convertNode = function(e, t) {
                var n = this;
                return e.forEach(function(r, o, i) {
                    if (n.convertBlock(r, e, i), (null == t ? void 0 : t.node) === r) {
                        var s = n.result.split("\n");
                        t.setMappedPos([s.length, Ks(s).length + 1])
                    }
                }), this.result
            }, e
        }(),
        ev = function() {
            function e(e, t, n, r) {
                var o = this;
                this.setMappedPos = function(e) {
                    o.mappedPosWhenConverting = e
                }, this.schema = e, this.eventEmitter = r, this.focusedNode = null, this.mappedPosWhenConverting = null, this.toWwConvertors = function(e) {
                    var t = Object.keys(e),
                        n = $i({}, $g),
                        r = new kh({
                            gfm: !0,
                            nodeId: !0,
                            convertors: e
                        }).getConvertors();
                    return t.forEach(function(t) {
                        var o = $g[t];
                        o && !zs(["htmlBlock", "htmlInline"], t) && (n[t] = function(n, i, s) {
                            s.origin = function() {
                                return r[t](i, s, r)
                            };
                            var a, l = e[t](i, s);
                            if (l) {
                                var c = Array.isArray(l) ? l[0] : l;
                                a = {
                                    htmlAttrs: c.attributes,
                                    classNames: c.classNames
                                }
                            }
                            o(n, i, s, a)
                        })
                    }), n
                }(n), this.toMdConvertors = Qg(t || {}), this.eventEmitter.listen("setFocusedNode", function(e) {
                    return o.focusedNode = e
                })
            }
            return e.prototype.getMappedPos = function() {
                return this.mappedPosWhenConverting
            }, e.prototype.getInfoForPosSync = function() {
                return {
                    node: this.focusedNode,
                    setMappedPos: this.setMappedPos
                }
            }, e.prototype.toWysiwygModel = function(e) {
                return new _g(this.schema, this.toWwConvertors).convertNode(e, this.getInfoForPosSync())
            }, e.prototype.toMarkdownText = function(e) {
                var t = new Yg(this.toMdConvertors).convertNode(e, this.getInfoForPosSync());
                return this.eventEmitter.emitReduce("beforeConvertWysiwygToMarkdown", t)
            }, e
        }();

    function tv(e) {
        var t = e.plugins,
            n = e.eventEmitter,
            r = e.usageStatistics,
            o = e.instance;
        return n.listen("mixinTableOffsetMapPrototype", rm), (null != t ? t : []).reduce(function(e, t) {
            var i = function(e) {
                var t = e.plugin,
                    n = {
                        eventEmitter: e.eventEmitter,
                        usageStatistics: e.usageStatistics,
                        instance: e.instance,
                        pmState: {
                            Plugin: wt,
                            PluginKey: Ct,
                            Selection: tt,
                            TextSelection: it
                        },
                        pmView: {
                            Decoration: io,
                            DecorationSet: lo
                        },
                        pmModel: {
                            Fragment: l
                        },
                        pmRules: {
                            InputRule: vi,
                            inputRules: yi,
                            undoInputRule: wi
                        },
                        pmKeymap: {
                            keymap: Jo
                        },
                        i18n: wm
                    };
                if (Gi(t)) {
                    var r = t[0],
                        o = t[1];
                    return r(n, void 0 === o ? {} : o)
                }
                return t(n)
            }({
                plugin: t,
                eventEmitter: n,
                usageStatistics: r,
                instance: o
            });
            if (!i) throw new Error("The return value of the executed plugin is empty.");
            var s = i.markdownParsers,
                a = i.toHTMLRenderers,
                c = i.toMarkdownRenderers,
                u = i.markdownPlugins,
                d = i.wysiwygPlugins,
                p = i.wysiwygNodeViews,
                h = i.markdownCommands,
                f = i.wysiwygCommands,
                m = i.toolbarItems;
            return a && (e.toHTMLRenderers = Xs(e.toHTMLRenderers, a)), c && (e.toMarkdownRenderers = Xs(e.toMarkdownRenderers, c)), u && (e.mdPlugins = e.mdPlugins.concat(u)), d && (e.wwPlugins = e.wwPlugins.concat(d)), p && (e.wwNodeViews = $i($i({}, e.wwNodeViews), p)), h && (e.mdCommands = $i($i({}, e.mdCommands), h)), f && (e.wwCommands = $i($i({}, e.wwCommands), f)), m && (e.toolbarItems = e.toolbarItems.concat(m)), s && (e.markdownParsers = $i($i({}, e.markdownParsers), s)), e
        }, {
            toHTMLRenderers: {},
            toMarkdownRenderers: {},
            mdPlugins: [],
            wwPlugins: [],
            wwNodeViews: {},
            mdCommands: {},
            wwCommands: {},
            toolbarItems: [],
            markdownParsers: {}
        })
    }
    var nv = function() {
        function e(e) {
            var t = this;
            this.options = Ji({
                linkAttributes: null,
                extendedAutolinks: !1,
                customHTMLRenderer: null,
                referenceDefinition: !1,
                customHTMLSanitizer: null,
                frontMatter: !1,
                usageStatistics: !0,
                theme: "light"
            }, e), this.eventEmitter = new Ag;
            var n, r = js(this.options.linkAttributes),
                o = tv({
                    plugins: this.options.plugins,
                    eventEmitter: this.eventEmitter,
                    usageStatistics: this.options.usageStatistics,
                    instance: this
                }) || {},
                i = o.toHTMLRenderers,
                s = o.markdownParsers,
                a = this.options,
                l = a.customHTMLRenderer,
                c = a.extendedAutolinks,
                u = a.referenceDefinition,
                d = a.frontMatter,
                p = a.customHTMLSanitizer,
                h = {
                    linkAttributes: r,
                    customHTMLRenderer: $i($i({}, i), l),
                    extendedAutolinks: c,
                    referenceDefinition: u,
                    frontMatter: d,
                    sanitizer: p || wf
                };
            n = h.customHTMLRenderer, ["htmlBlock", "htmlInline"].forEach(function(e) {
                n[e] && Object.keys(n[e]).forEach(function(e) {
                    return bf(e)
                })
            }), this.options.events && Wi(this.options.events, function(e, n) {
                t.on(n, e)
            });
            var f = this.options,
                m = f.el,
                g = f.initialValue,
                v = f.theme,
                y = m.innerHTML;
            "light" !== v && m.classList.add(Qa(v)), m.innerHTML = "", this.toastMark = new fh("", {
                disallowedHtmlBlockTags: ["br", "img"],
                extendedAutolinks: c,
                referenceDefinition: u,
                disallowDeepHeading: !0,
                frontMatter: d,
                customParser: s
            }), this.preview = new qf(this.eventEmitter, $i($i({}, h), {
                isViewer: !0
            })), mu(this.preview.previewContent, "mousedown", this.toggleTask.bind(this)), g ? this.setMarkdown(g) : y && this.preview.setHTML(y), m.appendChild(this.preview.previewContent), this.eventEmitter.emit("load", this)
        }
        return e.prototype.toggleTask = function(e) {
            var t = e.target,
                n = getComputedStyle(t, ":before");
            !t.hasAttribute("data-task-disabled") && t.hasAttribute("data-task") && Xa(n, e.offsetX, e.offsetY) && (nl(t, "checked"), this.eventEmitter.emit("change", {
                source: "viewer",
                date: e
            }))
        }, e.prototype.setMarkdown = function(e) {
            var t = this.toastMark.getLineTexts(),
                n = [t.length, Ks(t).length + 1],
                r = this.toastMark.editMarkdown([1, 1], n, e || "");
            this.eventEmitter.emit("updatePreview", r)
        }, e.prototype.on = function(e, t) {
            this.eventEmitter.listen(e, t)
        }, e.prototype.off = function(e) {
            this.eventEmitter.removeEventHandler(e)
        }, e.prototype.addHook = function(e, t) {
            this.eventEmitter.removeEventHandler(e), this.eventEmitter.listen(e, t)
        }, e.prototype.destroy = function() {
            uu(this.preview.el, "mousedown", this.toggleTask.bind(this)), this.preview.destroy(), this.eventEmitter.emit("destroy")
        }, e.prototype.isViewer = function() {
            return !0
        }, e.prototype.isMarkdownMode = function() {
            return !1
        }, e.prototype.isWysiwygMode = function() {
            return !1
        }, e
    }();

    function rv(e) {
        return e instanceof L
    }

    function ov(e) {
        return zs(["document", "blockQuote", "bulletList", "orderedList", "listItem", "paragraph", "heading", "emph", "strong", "strike", "link", "image", "table", "tableHead", "tableBody", "tableRow", "tableHeadCell", "tableBodyCell"], e)
    }
    var iv = {
            openTag: function(e, t) {
                var n = e,
                    r = n.tagName,
                    o = n.classNames,
                    i = n.attributes,
                    s = document.createElement(r),
                    a = {};
                o && (s.className = o.join(" ")), i && (a = $i($i({}, a), i)), al(a, s), t.push(s)
            },
            closeTag: function(e, t) {
                if (t.length > 1) {
                    var n = t.pop();
                    Ks(t).appendChild(n)
                }
            },
            html: function(e, t) {
                Ks(t).insertAdjacentHTML("beforeend", e.content)
            },
            text: function(e, t) {
                var n = document.createTextNode(e.content);
                Ks(t).appendChild(n)
            }
        },
        sv = function() {
            function e(e, t) {
                var n = Nf(e, t),
                    r = $i($i({}, t.htmlBlock), t.htmlInline);
                this.customConvertorKeys = Object.keys(t).concat(Object.keys(r)), this.renderer = new kh({
                    gfm: !0,
                    convertors: $i($i({}, n), r)
                }), this.convertors = this.renderer.getConvertors()
            }
            return e.prototype.generateTokens = function(e) {
                var t = function(e) {
                        var t = e.attrs,
                            n = e.type.name,
                            r = {
                                type: n,
                                wysiwygNode: !0,
                                literal: !ov(n) && rv(e) ? e.textContent : null
                            },
                            o = {
                                heading: {
                                    level: t.level
                                },
                                link: {
                                    destination: t.linkUrl,
                                    title: t.title
                                },
                                image: {
                                    destination: t.imageUrl
                                },
                                codeBlock: {
                                    info: t.language
                                },
                                bulletList: {
                                    type: "list",
                                    listData: {
                                        type: "bullet"
                                    }
                                },
                                orderedList: {
                                    type: "list",
                                    listData: {
                                        type: "ordered",
                                        start: t.order
                                    }
                                },
                                listItem: {
                                    type: "item",
                                    listData: {
                                        task: t.task,
                                        checked: t.checked
                                    }
                                },
                                tableHeadCell: {
                                    type: "tableCell",
                                    cellType: "head",
                                    align: t.align
                                },
                                tableBodyCell: {
                                    type: "tableCell",
                                    cellType: "body",
                                    align: t.align
                                },
                                customBlock: {
                                    info: t.info
                                }
                            } [n],
                            i = $i($i({}, r), o),
                            s = e.attrs,
                            a = s.htmlAttrs,
                            l = s.childrenHTML;
                        return a ? $i($i({}, i), {
                            attrs: a,
                            childrenHTML: l
                        }) : i
                    }(e),
                    n = {
                        entering: !0,
                        leaf: !!rv(e) && e.isLeaf,
                        options: this.renderer.getOptions(),
                        getChildrenText: function() {
                            return rv(e) ? e.textContent : ""
                        },
                        skipChildren: function() {
                            return !1
                        }
                    },
                    r = this.convertors[e.type.name],
                    o = r(t, n, this.convertors),
                    i = Gi(o) ? o : [o];
                return (ov(e.type.name) || e.attrs.htmlInline) && (n.entering = !1, i.push({
                    type: "text",
                    content: rv(e) ? e.textContent : ""
                }), i = i.concat(r(t, n, this.convertors))), i
            }, e.prototype.toDOMNode = function(e) {
                var t = this.generateTokens(e),
                    n = [];
                return t.forEach(function(e) {
                    return iv[e.type](e, n)
                }), n[0]
            }, e.prototype.getToDOMNode = function(e) {
                return zs(this.customConvertorKeys, e) ? this.toDOMNode.bind(this) : null
            }, e
        }(),
        av = null,
        lv = null;

    function cv(e, t) {
        var n = t.syncScrollTop,
            r = t.releaseEventBlock;
        lv && clearTimeout(lv), n(e), lv = setTimeout(function() {
            r()
        }, 15)
    }
    var uv = function() {
            function e(e, t, n) {
                this.latestEditorScrollTop = null, this.latestPreviewScrollTop = null, this.blockedScroll = null, this.active = !0, this.timer = null;
                var r = t.previewContent,
                    o = t.el;
                this.previewRoot = r, this.previewEl = o, this.mdEditor = e, this.editorView = e.view, this.toastMark = e.getToastMark(), this.eventEmitter = n, this.addScrollSyncEvent()
            }
            return e.prototype.addScrollSyncEvent = function() {
                var e = this;
                this.eventEmitter.listen("afterPreviewRender", function() {
                    e.clearTimer(), e.timer = setTimeout(function() {
                        e.syncPreviewScrollTop(!0)
                    }, 200)
                }), this.eventEmitter.listen("scroll", function(t, n) {
                    e.active && ("editor" === t && "editor" !== e.blockedScroll ? e.syncPreviewScrollTop() : "preview" === t && "preview" !== e.blockedScroll && e.syncEditorScrollTop(n))
                }), this.eventEmitter.listen("toggleScrollSync", function(t) {
                    e.active = t
                })
            }, e.prototype.getMdNodeAtPos = function(e, t) {
                var n = e.content.findIndex(t.pos).index;
                return this.toastMark.findFirstNodeAtLine(n + 1)
            }, e.prototype.getScrollTopByCaretPos = function() {
                var e = this.mdEditor.getSelection(),
                    t = this.toastMark.findFirstNodeAtLine(e[0][0]),
                    n = this.previewEl.clientHeight,
                    r = Bf(this.previewRoot, t).el,
                    o = (Rf(r, this.previewRoot) || r.offsetTop) + r.clientHeight - .5 * n;
                return this.latestEditorScrollTop = null, r.getBoundingClientRect().top - this.previewEl.getBoundingClientRect().top < n ? null : o
            }, e.prototype.syncPreviewScrollTop = function(e) {
                void 0 === e && (e = !1);
                var t, n = this,
                    r = n.editorView,
                    o = n.previewEl,
                    i = n.previewRoot,
                    s = r.dom.getBoundingClientRect(),
                    a = s.left,
                    l = s.top,
                    c = r.posAtCoords({
                        left: a,
                        top: l
                    }),
                    u = r.state.doc,
                    d = this.getMdNodeAtPos(u, c);
                if (d && ("htmlBlock" !== (t = d.type) && "htmlInline" !== t)) {
                    var p = o.scrollTop,
                        h = r.dom,
                        f = h.scrollTop,
                        m = h.scrollHeight,
                        g = h.clientHeight,
                        v = h.children,
                        y = m - f <= g + 18,
                        b = y ? o.scrollHeight : 0;
                    if (f && !y) {
                        if (e) {
                            var w = this.getScrollTopByCaretPos();
                            if (!w) return;
                            b = w
                        } else {
                            var k = Bf(this.previewRoot, d),
                                x = k.el,
                                C = Lf(u, k.mdNode, v),
                                T = C.height,
                                M = C.rect;
                            b = (Rf(x, i) || x.offsetTop) + x.clientHeight * (l > M.top ? Math.min((l - M.top) / T, 1) : 0)
                        }
                        b = this.getResolvedScrollTop("editor", f, b, p), this.latestEditorScrollTop = f
                    }
                    b !== p && this.run("editor", b, p)
                }
            }, e.prototype.syncEditorScrollTop = function(e) {
                var t = this,
                    n = t.toastMark,
                    r = t.editorView,
                    o = t.previewRoot,
                    i = t.previewEl,
                    s = r.dom,
                    a = r.state,
                    l = i.scrollTop,
                    c = i.clientHeight,
                    u = i.scrollHeight - l <= c,
                    d = s.scrollTop,
                    p = u ? s.scrollHeight : 0;
                if (l && e && !u) {
                    if (e = function(e, t) {
                            for (; !e.getAttribute("data-nodeid") && e.parentElement !== t;) e = e.parentElement;
                            return e
                        }(e, o), !e.getAttribute("data-nodeid")) return;
                    var h = s.children,
                        f = Number(e.getAttribute("data-nodeid")),
                        m = Bf(this.previewRoot, n.findNodeById(f)),
                        g = m.mdNode,
                        v = m.el;
                    p = h[ca(g) - 1].offsetTop;
                    var y = Lf(a.doc, g, h).height,
                        b = function(e, t, n) {
                            var r, o = Ff[r = n] && Ff[r].height,
                                i = function(e) {
                                    return Ff[e] && Ff[e].offsetTop
                                }(n),
                                s = o || e.clientHeight,
                                a = i || Rf(e, t) || e.offsetTop;
                            return o || function(e, t) {
                                Ff[e] = Ff[e] || {}, Ff[e].height = t
                            }(n, s), i || function(e, t) {
                                Ff[e] = Ff[e] || {}, Ff[e].offsetTop = t
                            }(n, a), {
                                nodeHeight: s,
                                offsetTop: a
                            }
                        }(v, o, f),
                        w = b.nodeHeight;
                    p += function(e, t, n, r) {
                        return Math.min((e - t) / n, 1) * r
                    }(l, b.offsetTop, w, y), p = this.getResolvedScrollTop("preview", l, p, d), this.latestPreviewScrollTop = l
                }
                p !== d && this.run("preview", p, d)
            }, e.prototype.getResolvedScrollTop = function(e, t, n, r) {
                var o = "editor" === e ? this.latestEditorScrollTop : this.latestPreviewScrollTop;
                return null === o ? n : o < t ? Math.max(n, r) : Math.min(n, r)
            }, e.prototype.run = function(e, t, n) {
                var r, o = this;
                "editor" === e ? (r = this.previewEl, this.blockedScroll = "preview") : (r = this.editorView.dom, this.blockedScroll = "editor"),
                    function(e, t, n) {
                        var r = t - e,
                            o = Date.now(),
                            i = function() {
                                var s, a = (Date.now() - o) / 100;
                                av && clearTimeout(av), a < 1 ? (s = e + r * Math.cos((1 - a) * Math.PI / 2), cv(Math.ceil(s), n), av = setTimeout(i, 1)) : (cv(t, n), av = null)
                            };
                        i()
                    }(n, t, {
                        syncScrollTop: function(e) {
                            return r.scrollTop = e
                        },
                        releaseEventBlock: function() {
                            return o.blockedScroll = null
                        }
                    })
            }, e.prototype.clearTimer = function() {
                this.timer && (clearTimeout(this.timer), this.timer = null)
            }, e.prototype.destroy = function() {
                this.clearTimer(), this.eventEmitter.removeEventHandler("scroll"), this.eventEmitter.removeEventHandler("afterPreviewRender")
            }, e
        }(),
        dv = {
            getPopupInitialValues: function(e, t) {
                return "link" === t.popupName ? {
                    linkText: e.getSelectedText()
                } : {}
            }
        },
        pv = function() {
            function e(e) {
                var t = this;
                this.initialHTML = e.el.innerHTML, e.el.innerHTML = "", this.options = Ji({
                    previewStyle: "tab",
                    previewHighlight: !0,
                    initialEditType: "markdown",
                    height: "300px",
                    minHeight: "200px",
                    language: "en-US",
                    useCommandShortcut: !0,
                    usageStatistics: !0,
                    toolbarItems: [
                        ["heading", "bold", "italic", "strike"],
                        ["hr", "quote"],
                        ["ul", "ol", "task", "indent", "outdent"],
                        ["table", "image", "link"],
                        ["code", "codeblock"],
                        ["scrollSync"]
                    ],
                    hideModeSwitch: !1,
                    linkAttributes: null,
                    extendedAutolinks: !1,
                    customHTMLRenderer: null,
                    customMarkdownRenderer: null,
                    referenceDefinition: !1,
                    customHTMLSanitizer: null,
                    frontMatter: !1,
                    widgetRules: [],
                    theme: "light",
                    autofocus: !0
                }, e);
                var n = this.options,
                    r = n.customHTMLRenderer,
                    o = n.extendedAutolinks,
                    i = n.referenceDefinition,
                    s = n.frontMatter,
                    a = n.customMarkdownRenderer,
                    l = n.useCommandShortcut,
                    c = n.initialEditType,
                    u = n.widgetRules,
                    d = n.customHTMLSanitizer;
                this.mode = c || "markdown", this.mdPreviewStyle = this.options.previewStyle, this.i18n = wm, this.i18n.setCode(this.options.language), this.eventEmitter = new Ag, Da(u);
                var p = js(this.options.linkAttributes);
                this.pluginInfo = tv({
                    plugins: this.options.plugins,
                    eventEmitter: this.eventEmitter,
                    usageStatistics: this.options.usageStatistics,
                    instance: this
                });
                var h, f = this.pluginInfo,
                    m = f.toHTMLRenderers,
                    g = f.toMarkdownRenderers,
                    v = f.mdPlugins,
                    y = f.wwPlugins,
                    b = f.wwNodeViews,
                    w = f.mdCommands,
                    k = f.wwCommands,
                    x = f.markdownParsers,
                    C = {
                        linkAttributes: p,
                        customHTMLRenderer: Xs(m, r),
                        extendedAutolinks: o,
                        referenceDefinition: i,
                        frontMatter: s,
                        sanitizer: d || wf
                    },
                    T = new sv(p, C.customHTMLRenderer),
                    M = function(e, t, n) {
                        var r = {
                            nodes: {},
                            marks: {}
                        };
                        return ["htmlBlock", "htmlInline"].forEach(function(o) {
                            e[o] && Object.keys(e[o]).forEach(function(e) {
                                var i = "htmlBlock" === o ? "nodes" : "marks";
                                bf(e), r[i][e] = Mf[o](e, t, n)
                            })
                        }), r
                    }(C.customHTMLRenderer, C.sanitizer, T);
                this.toastMark = new fh("", {
                    disallowedHtmlBlockTags: ["br", "img"],
                    extendedAutolinks: o,
                    referenceDefinition: i,
                    disallowDeepHeading: !0,
                    frontMatter: s,
                    customParser: x
                }), this.mdEditor = new nu(this.eventEmitter, {
                    toastMark: this.toastMark,
                    useCommandShortcut: l,
                    mdPlugins: v
                }), this.preview = new qf(this.eventEmitter, $i($i({}, C), {
                    isViewer: !1,
                    highlight: this.options.previewHighlight
                })), this.wwEditor = new Sg(this.eventEmitter, {
                    toDOMAdaptor: T,
                    useCommandShortcut: l,
                    htmlSchemaMap: M,
                    linkAttributes: p,
                    wwPlugins: y,
                    wwNodeViews: b
                }), this.convertor = new ev(this.wwEditor.getSchema(), $i($i({}, g), a), Nf(p, C.customHTMLRenderer), this.eventEmitter), this.setMinHeight(this.options.minHeight), this.setHeight(this.options.height), this.setMarkdown(this.options.initialValue, !1), this.options.placeholder && this.setPlaceholder(this.options.placeholder), this.options.initialValue || this.setHTML(this.initialHTML, !1), this.commandManager = new Lg(this.eventEmitter, this.mdEditor.commands, this.wwEditor.commands, function() {
                    return t.mode
                }), this.options.usageStatistics && Es("editor", "UA-129966929-1"), this.scrollSync = new uv(this.mdEditor, this.preview, this.eventEmitter), this.addInitEvent(), this.addInitCommand(w, k), (h = this).eventEmitter.listen("query", function(e, t) {
                    return dv[e](h, t)
                }), this.options.hooks && Wi(this.options.hooks, function(e, n) {
                    return t.addHook(n, e)
                }), this.options.events && Wi(this.options.events, function(e, n) {
                    return t.on(n, e)
                }), this.eventEmitter.emit("load", this), this.moveCursorToStart(this.options.autofocus)
            }
            return e.prototype.addInitEvent = function() {
                var e = this;
                this.on("needChangeMode", this.changeMode.bind(this)), this.on("loadUI", function() {
                    if ("auto" !== e.height) {
                        var t = Math.min(parseInt(e.minHeight, 10), parseInt(e.height, 10) - 75) + "px";
                        e.setMinHeight(t)
                    }
                }), this.eventEmitter.listen("addImageBlobHook", function(e, t) {
                    var n = new FileReader;
                    n.onload = function(e) {
                        var n = e.target;
                        return t(n.result)
                    }, n.readAsDataURL(e)
                })
            }, e.prototype.addInitCommand = function(e, t) {
                var n = this,
                    r = function(e, t) {
                        Object.keys(t).forEach(function(r) {
                            n.addCommand(e, r, t[r])
                        })
                    };
                this.addCommand("markdown", "toggleScrollSync", function(e) {
                    return n.eventEmitter.emit("toggleScrollSync", e.active), !0
                }), r("markdown", e), r("wysiwyg", t)
            }, e.prototype.getCurrentModeEditor = function() {
                return this.isMarkdownMode() ? this.mdEditor : this.wwEditor
            }, e.factory = function(t) {
                return t.viewer ? new nv(t) : new e(t)
            }, e.setLanguage = function(e, t) {
                wm.setLanguage(e, t)
            }, e.prototype.changePreviewStyle = function(e) {
                this.mdPreviewStyle !== e && (this.mdPreviewStyle = e, this.eventEmitter.emit("changePreviewStyle", e))
            }, e.prototype.exec = function(e, t) {
                this.commandManager.exec(e, t)
            }, e.prototype.addCommand = function(e, t, n) {
                var r = this;
                this.commandManager.addCommand(e, t, function(t) {
                    void 0 === t && (t = {});
                    var o = ("markdown" === e ? r.mdEditor : r.wwEditor).view;
                    n(t, o.state, o.dispatch, o)
                })
            }, e.prototype.on = function(e, t) {
                this.eventEmitter.listen(e, t)
            }, e.prototype.off = function(e) {
                this.eventEmitter.removeEventHandler(e)
            }, e.prototype.addHook = function(e, t) {
                this.eventEmitter.removeEventHandler(e), this.eventEmitter.listen(e, t)
            }, e.prototype.removeHook = function(e) {
                this.eventEmitter.removeEventHandler(e)
            }, e.prototype.focus = function() {
                this.getCurrentModeEditor().focus()
            }, e.prototype.blur = function() {
                this.getCurrentModeEditor().blur()
            }, e.prototype.moveCursorToEnd = function(e) {
                void 0 === e && (e = !0), this.getCurrentModeEditor().moveCursorToEnd(e)
            }, e.prototype.moveCursorToStart = function(e) {
                void 0 === e && (e = !0), this.getCurrentModeEditor().moveCursorToStart(e)
            }, e.prototype.setMarkdown = function(e, t) {
                if (void 0 === e && (e = ""), void 0 === t && (t = !0), this.mdEditor.setMarkdown(e, t), this.isWysiwygMode()) {
                    var n = this.toastMark.getRootNode(),
                        r = this.convertor.toWysiwygModel(n);
                    this.wwEditor.setModel(r, t)
                }
            }, e.prototype.setHTML = function(e, t) {
                void 0 === e && (e = ""), void 0 === t && (t = !0);
                var n = document.createElement("div");
                n.innerHTML = function(e) {
                    var t = e.replace(/<p><br\s*\/*><\/p>/gi, "<p></p>"),
                        n = new RegExp(Ua, "ig"),
                        r = t.match(n);
                    return null == r || r.forEach(function(e, n) {
                        if (Ja.test(e)) {
                            var o = Ga;
                            if (n) {
                                var i = r[n - 1].match(_a);
                                if (i && !/br/i.test(i[1])) {
                                    var s = i[1];
                                    o = "</" + s + "><" + s + ">"
                                }
                            }
                            t = t.replace(Ja, o)
                        }
                    }), t
                }(e);
                var r = Y.fromSchema(this.wwEditor.schema).parse(n);
                this.isMarkdownMode() ? this.mdEditor.setMarkdown(this.convertor.toMarkdownText(r), t) : this.wwEditor.setModel(r, t)
            }, e.prototype.getMarkdown = function() {
                return this.isMarkdownMode() ? this.mdEditor.getMarkdown() : this.convertor.toMarkdownText(this.wwEditor.getModel())
            }, e.prototype.getHTML = function() {
                var e = this;
                this.eventEmitter.holdEventInvoke(function() {
                    if (e.isMarkdownMode()) {
                        var t = e.toastMark.getRootNode(),
                            n = e.convertor.toWysiwygModel(t);
                        e.wwEditor.setModel(n)
                    }
                });
                var t = ll(this.wwEditor.view.dom.innerHTML);
                if (this.placeholder) {
                    var n = new RegExp('<span class="placeholder[^>]+>' + this.placeholder + "</span>", "i");
                    return t.replace(n, "")
                }
                return t
            }, e.prototype.insertText = function(e) {
                this.getCurrentModeEditor().replaceSelection(e)
            }, e.prototype.setSelection = function(e, t) {
                this.getCurrentModeEditor().setSelection(e, t)
            }, e.prototype.replaceSelection = function(e, t, n) {
                this.getCurrentModeEditor().replaceSelection(e, t, n)
            }, e.prototype.deleteSelection = function(e, t) {
                this.getCurrentModeEditor().deleteSelection(e, t)
            }, e.prototype.getSelectedText = function(e, t) {
                return this.getCurrentModeEditor().getSelectedText(e, t)
            }, e.prototype.getRangeInfoOfNode = function(e) {
                return this.getCurrentModeEditor().getRangeInfoOfNode(e)
            }, e.prototype.addWidget = function(e, t, n) {
                this.getCurrentModeEditor().addWidget(e, t, n)
            }, e.prototype.replaceWithWidget = function(e, t, n) {
                this.getCurrentModeEditor().replaceWithWidget(e, t, n)
            }, e.prototype.setHeight = function(e) {
                var t = this.options.el;
                Ki(e) && ("auto" === e ? vs(t, "auto-height") : xs(t, "auto-height"), this.setMinHeight(this.getMinHeight())), rs(t, {
                    height: e
                }), this.height = e
            }, e.prototype.getHeight = function() {
                return this.height
            }, e.prototype.setMinHeight = function(e) {
                if (e !== this.minHeight) {
                    var t = this.height || this.options.height;
                    "auto" !== t && this.options.el.querySelector("." + Qa("main")) && (e = Math.min(parseInt(e, 10), parseInt(t, 10) - 75) + "px");
                    var n = parseInt(e, 10);
                    this.minHeight = e, this.wwEditor.setMinHeight(n), this.mdEditor.setMinHeight(n), this.preview.setMinHeight(n)
                }
            }, e.prototype.getMinHeight = function() {
                return this.minHeight
            }, e.prototype.isMarkdownMode = function() {
                return "markdown" === this.mode
            }, e.prototype.isWysiwygMode = function() {
                return "wysiwyg" === this.mode
            }, e.prototype.isViewer = function() {
                return !1
            }, e.prototype.getCurrentPreviewStyle = function() {
                return this.mdPreviewStyle
            }, e.prototype.changeMode = function(e, t) {
                if (this.mode !== e) {
                    if (this.mode = e, this.isWysiwygMode()) {
                        var n = this.toastMark.getRootNode(),
                            r = this.convertor.toWysiwygModel(n);
                        this.wwEditor.setModel(r)
                    } else r = this.wwEditor.getModel(), this.mdEditor.setMarkdown(this.convertor.toMarkdownText(r), !t);
                    if (this.eventEmitter.emit("removePopupWidget"), this.eventEmitter.emit("changeMode", e), !t) {
                        var o = this.convertor.getMappedPos();
                        this.focus(), this.isWysiwygMode() && Cs(o) ? this.wwEditor.setSelection(o) : Array.isArray(o) && this.mdEditor.setSelection(o)
                    }
                }
            }, e.prototype.destroy = function() {
                var e = this;
                this.wwEditor.destroy(), this.mdEditor.destroy(), this.preview.destroy(), this.scrollSync.destroy(), this.eventEmitter.emit("destroy"), this.eventEmitter.getEvents().forEach(function(t, n) {
                    return e.off(n)
                })
            }, e.prototype.hide = function() {
                this.eventEmitter.emit("hide")
            }, e.prototype.show = function() {
                this.eventEmitter.emit("show")
            }, e.prototype.setScrollTop = function(e) {
                this.getCurrentModeEditor().setScrollTop(e)
            }, e.prototype.getScrollTop = function() {
                return this.getCurrentModeEditor().getScrollTop()
            }, e.prototype.reset = function() {
                this.wwEditor.setModel([]), this.mdEditor.setMarkdown("")
            }, e.prototype.getSelection = function() {
                return this.getCurrentModeEditor().getSelection()
            }, e.prototype.setPlaceholder = function(e) {
                this.placeholder = e, this.mdEditor.setPlaceholder(e), this.wwEditor.setPlaceholder(e)
            }, e.prototype.getEditorElements = function() {
                return {
                    mdEditor: this.mdEditor.getElement(),
                    mdPreview: this.preview.getElement(),
                    wwEditor: this.wwEditor.getElement()
                }
            }, e.prototype.convertPosToMatchEditorMode = function(e, t, n) {
                var r, o;
                void 0 === t && (t = e), void 0 === n && (n = this.mode);
                var i = this.mdEditor.view.state.doc,
                    s = Array.isArray(e),
                    a = Array.isArray(t),
                    l = e,
                    c = t;
                if (s !== a) throw new Error("Types of arguments must be same");
                return "markdown" !== n || s || a ? "wysiwyg" === n && s && a && (l = (o = Nl(i, e, t))[0], c = o[1]) : (l = (r = Sl(i, e, t))[0], c = r[1]), [l, c]
            }, e
        }(),
        hv = function() {
            function e(e) {
                this.current = e, this.root = e, this.entering = !0
            }
            return e.prototype.walk = function() {
                var e = this.entering,
                    t = this.current;
                return t ? (e ? t.firstChild ? (this.current = t.firstChild, this.entering = !0) : this.entering = !1 : t === this.root ? this.current = null : t.next ? (this.current = t.next, this.entering = !0) : (this.current = t.parent, this.entering = !1), {
                    vnode: t,
                    entering: e
                }) : null
            }, e
        }(),
        fv = function() {
            function e(e, t, n) {
                this.parent = null, this.old = null, this.firstChild = null, this.next = null, this.skip = !1, this.type = e, this.props = t, this.children = n, this.props.children = n, t.ref && (this.ref = t.ref, delete t.ref), t.key && (this.key = t.key, delete t.key)
            }
            return e.prototype.walker = function() {
                return new hv(this)
            }, e.removalNodes = [], e
        }();

    function mv(e, t) {
        var n, r, o = e;
        "boolean" == typeof(r = e) || r instanceof Boolean || null == e ? o = null : (Ki(e) || Cs(e)) && (n = String(e), o = new fv("TEXT_NODE", {
            nodeValue: n
        }, [])), o && t.push(o)
    }
    var gv = function(e) {
        for (var t, n, r = arguments, o = 1, i = "", s = "", a = [0], l = function(e) {
                1 === o && (e || (i = i.replace(/^\s*\n\s*|\s*\n\s*$/g, ""))) ? a.push(e ? r[e] : i) : 3 === o && (e || i) ? (a[1] = e ? r[e] : i, o = 2) : 2 === o && "..." === i && e ? a[2] = Ys(a[2] || {}, r[e]) : 2 === o && i && !e ? (a[2] = a[2] || {})[i] = !0 : o >= 5 && (5 === o ? ((a[2] = a[2] || {})[n] = e ? i ? i + r[e] : r[e] : i, o = 6) : (e || i) && (a[2][n] += e ? i + r[e] : i)), i = ""
            }, c = 0; c < e.length; c++) {
            c && (1 === o && l(), l(c));
            for (let r = 0; r < e[c].length; r++) t = e[c][r], 1 === o ? "<" === t ? (l(), a = [a, "", null], o = 3) : i += t : 4 === o ? "--" === i && ">" === t ? (o = 1, i = "") : i = t + i[0] : s ? t === s ? s = "" : i += t : '"' === t || "'" === t ? s = t : ">" === t ? (l(), o = 1) : o && ("=" === t ? (o = 5, n = i, i = "") : "/" === t && (o < 5 || ">" === e[c][r + 1]) ? (l(), 3 === o && (a = a[0]), o = a, (a = a[0]).push(this.apply(null, o.slice(1))), o = 0) : " " === t || "\t" === t || "\n" === t || "\r" === t ? (l(), o = 2) : i += t), 3 === o && "!--" === i && (o = 4, a = a[0])
        }
        return l(), a.length > 2 ? a.slice(1) : a[1]
    }.bind(function(e, t) {
        for (var n = [], r = 2; r < arguments.length; r++) n[r - 2] = arguments[r];
        var o = [];
        return n.forEach(function(e) {
            Array.isArray(e) ? e.forEach(function(e) {
                mv(e, o)
            }) : mv(e, o)
        }), new fv(e, t || {}, o)
    });

    function vv(e) {
        var t;
        return "TEXT_NODE" === e.type ? t = document.createTextNode(e.props.nodeValue) : wv(t = document.createElement(e.type), {}, e.props), t
    }

    function yv(e, t) {
        e.node ? t.removeChild(e.node) : yv(e.firstChild, t)
    }
    var bv = /acit|ex(?:s|g|n|p|$)|rph|ows|mnc|ntw|ine[ch]|zoo|^ord/i;

    function wv(e, t, n, r) {
        Object.keys(n).forEach(function(o) {
            if (!r || r(o))
                if (/^on/.test(o)) {
                    var i = o.slice(2).toLowerCase();
                    e.addEventListener(i, n[o])
                } else "nodeValue" === o ? e[o] = n[o] : "style" === o && (s = n[o]) === Object(s) ? function(e, t, n) {
                    t && Object.keys(t).forEach(function(t) {
                        e.style[t] = ""
                    }), Object.keys(n).forEach(function(t) {
                        var r = n[t];
                        e.style[t] = Cs(r) && !bv.test(t) ? r + "px" : r
                    })
                }(e, t[o], n[o]) : "children" !== o && (!1 === n[o] ? e.removeAttribute(o) : e.setAttribute(o, n[o]));
            var s
        })
    }

    function kv(e) {
        if (fv.removalNodes.forEach(function(e) {
                return Cv(e)
            }), e)
            for (var t = void 0, n = e.walker(); t = n.walk();)
                if (e = t.vnode, t.entering) Cv(e);
                else if (bl(e.type)) {
            var r = e.component;
            if (!e.old && r.mounted && r.mounted(), e.old && r.updated) {
                var o = r.prevProps || {};
                r.updated(o)
            }
        }
    }

    function xv(e) {
        for (var t = e.parent; !t.node;) t = t.parent;
        return t.node
    }

    function Cv(e) {
        if (e && e.parent) {
            if (e.node) {
                var t = xv(e);
                "A" === e.effect ? t.appendChild(e.node) : "U" === e.effect && (i = e.node, s = e.old.props, a = e.props, Object.keys(s).forEach(function(e) {
                    if (/^on/.test(e)) {
                        if (!a[e] || s[e] !== a[e]) {
                            var t = e.slice(2).toLowerCase();
                            i.removeEventListener(t, s[e])
                        }
                    } else "children" === e || a[e] || function(e) {
                        return (null == e ? void 0 : e.nodeType) === Node.TEXT_NODE
                    }(i) || i.removeAttribute(e)
                }), wv(i, s, a, function(e) {
                    return !Js(s[e], a[e])
                }))
            }
            if ("D" === e.effect)
                for (var n = void 0, r = e.walker(); n = r.walk();)
                    if (e = n.vnode, !n.entering)
                        if (bl(e.type)) {
                            var o = e.component;
                            o.beforeDestroy && o.beforeDestroy()
                        } else yv(e, t = xv(e));
            e.ref && (e.component ? e.ref(e.component) : e.node && e.ref(e.node))
        }
        var i, s, a
    }

    function Tv(e, t) {
        var n = t.props,
            r = t.component;
        return r ? (r.prevProps = r.props, r.props = t.props, r) : new e(n)
    }

    function Mv(e) {
        for (var t = e; e && !e.skip;) {
            if (bl(e.type)) {
                var n = Tv(e.type, e);
                n.vnode = e, e.component = n, e.props.children = e.children = [n.render()], Sv(e)
            } else e.node || (e.node = vv(e)), Sv(e);
            if (e.firstChild) e = e.firstChild;
            else {
                for (; e && e.parent && !e.next && (e = e.parent) !== t;);
                e = e.next
            }
        }
    }

    function Sv(e) {
        var t = e.children,
            n = e.old ? e.old.firstChild : null,
            r = null;
        t.forEach(function(t, o) {
            var i = function(e, t) {
                return e && t && t.type === e.type && (!t.key || t.key === e.key)
            }(n, t);
            i && (t.old = n, t.parent = e, t.node = n.node, t.component = n.component, t.effect = "U"), t && !i && (t.old = null, t.parent = e, t.node = null, t.effect = "A"), n && !i && (fv.removalNodes.push(n), n.effect = "D"), n && (n = n.next), 0 === o ? e.firstChild = t : t && (r.next = t), r = t
        });
        var o = Ks(t);
        if (!t.length)
            for (; n;) fv.removalNodes.push(n), n.effect = "D", n = n.next;
        for (; n && o;) n && o.old !== n && (fv.removalNodes.push(n), n.effect = "D", n = n.next)
    }
    var Ev, Nv = function() {
            function e(e) {
                this.props = e, this.state = {}, this.refs = {}
            }
            return e.prototype.setState = function(e) {
                var t, n = $i($i({}, this.state), e);
                Js(this.state, n) || (this.state = n, (t = this.vnode).effect = "U", t.old = t, t.next && (t.next.skip = !0), fv.removalNodes = [], Mv(t), kv(t), t.next && (t.next.skip = !1))
            }, e
        }(),
        Ov = function(e) {
            function t(t) {
                var n = e.call(this, t) || this;
                return n.state = {
                    hide: !1
                }, n
            }
            return ji(t, e), t.prototype.show = function() {
                this.setState({
                    hide: !1
                })
            }, t.prototype.hide = function() {
                this.setState({
                    hide: !0
                })
            }, t.prototype.render = function() {
                var e = this.props,
                    t = e.editorType,
                    n = e.eventEmitter;
                return gv(Ev || (Ev = Ui(['\n      <div class="', '" style="display: ', '">\n        <div\n          class="tab-item', '"\n          onClick=', "\n        >\n          ", '\n        </div>\n        <div\n          class="tab-item', '"\n          onClick=', "\n        >\n          ", "\n        </div>\n      </div>\n    "], ['\n      <div class="', '" style="display: ', '">\n        <div\n          class="tab-item', '"\n          onClick=', "\n        >\n          ", '\n        </div>\n        <div\n          class="tab-item', '"\n          onClick=', "\n        >\n          ", "\n        </div>\n      </div>\n    "])), Qa("mode-switch"), this.state.hide ? "none" : "block", "markdown" === t ? " active" : "", function() {
                    n.emit("needChangeMode", "markdown")
                }, wm.get("Markdown"), "wysiwyg" === t ? " active" : "", function() {
                    n.emit("needChangeMode", "wysiwyg")
                }, wm.get("WYSIWYG"))
            }, t
        }(Nv),
        Dv = function(e, t) {
            var n, r, o, i, s = !0,
                a = function(t) {
                    e.apply(null, t), n = null
                };

            function l() {
                if (i = Array.prototype.slice.call(arguments), s) return a(i), void(s = !1);
                o = Number(new Date), n = n || o, r(i), o - n >= t && a(i)
            }
            return r = function(e, t) {
                var n, r;
                return t = t || 0,
                    function() {
                        r = Array.prototype.slice.call(arguments), window.clearTimeout(n), n = window.setTimeout(function() {
                            e.apply(null, r)
                        }, t)
                    }
            }(a, t = t || 0), l.reset = function() {
                s = !0, n = null
            }, l
        },
        Av = function() {
            if ("undefined" != typeof Map) return Map;

            function e(e, t) {
                var n = -1;
                return e.some(function(e, r) {
                    return e[0] === t && (n = r, !0)
                }), n
            }
            return function() {
                function t() {
                    this.__entries__ = []
                }
                return Object.defineProperty(t.prototype, "size", {
                    get: function() {
                        return this.__entries__.length
                    },
                    enumerable: !0,
                    configurable: !0
                }), t.prototype.get = function(t) {
                    var n = e(this.__entries__, t),
                        r = this.__entries__[n];
                    return r && r[1]
                }, t.prototype.set = function(t, n) {
                    var r = e(this.__entries__, t);
                    ~r ? this.__entries__[r][1] = n : this.__entries__.push([t, n])
                }, t.prototype.delete = function(t) {
                    var n = this.__entries__,
                        r = e(n, t);
                    ~r && n.splice(r, 1)
                }, t.prototype.has = function(t) {
                    return !!~e(this.__entries__, t)
                }, t.prototype.clear = function() {
                    this.__entries__.splice(0)
                }, t.prototype.forEach = function(e, t) {
                    void 0 === t && (t = null);
                    for (var n = 0, r = this.__entries__; n < r.length; n++) {
                        var o = r[n];
                        e.call(t, o[1], o[0])
                    }
                }, t
            }()
        }(),
        Lv = "undefined" != typeof window && "undefined" != typeof document && window.document === document,
        Iv = void 0 !== e.g && e.g.Math === Math ? e.g : "undefined" != typeof self && self.Math === Math ? self : "undefined" != typeof window && window.Math === Math ? window : Function("return this")(),
        Rv = "function" == typeof requestAnimationFrame ? requestAnimationFrame.bind(Iv) : function(e) {
            return setTimeout(function() {
                return e(Date.now())
            }, 1e3 / 60)
        },
        Pv = ["top", "right", "bottom", "left", "width", "height", "size", "weight"],
        Bv = "undefined" != typeof MutationObserver,
        Fv = function() {
            function e() {
                this.connected_ = !1, this.mutationEventsAdded_ = !1, this.mutationsObserver_ = null, this.observers_ = [], this.onTransitionEnd_ = this.onTransitionEnd_.bind(this), this.refresh = function(e) {
                    var t = !1,
                        n = !1,
                        r = 0;

                    function o() {
                        t && (t = !1, e()), n && s()
                    }

                    function i() {
                        Rv(o)
                    }

                    function s() {
                        var e = Date.now();
                        if (t) {
                            if (e - r < 2) return;
                            n = !0
                        } else t = !0, n = !1, setTimeout(i, 20);
                        r = e
                    }
                    return s
                }(this.refresh.bind(this))
            }
            return e.prototype.addObserver = function(e) {
                ~this.observers_.indexOf(e) || this.observers_.push(e), this.connected_ || this.connect_()
            }, e.prototype.removeObserver = function(e) {
                var t = this.observers_,
                    n = t.indexOf(e);
                ~n && t.splice(n, 1), !t.length && this.connected_ && this.disconnect_()
            }, e.prototype.refresh = function() {
                this.updateObservers_() && this.refresh()
            }, e.prototype.updateObservers_ = function() {
                var e = this.observers_.filter(function(e) {
                    return e.gatherActive(), e.hasActive()
                });
                return e.forEach(function(e) {
                    return e.broadcastActive()
                }), e.length > 0
            }, e.prototype.connect_ = function() {
                Lv && !this.connected_ && (document.addEventListener("transitionend", this.onTransitionEnd_), window.addEventListener("resize", this.refresh), Bv ? (this.mutationsObserver_ = new MutationObserver(this.refresh), this.mutationsObserver_.observe(document, {
                    attributes: !0,
                    childList: !0,
                    characterData: !0,
                    subtree: !0
                })) : (document.addEventListener("DOMSubtreeModified", this.refresh), this.mutationEventsAdded_ = !0), this.connected_ = !0)
            }, e.prototype.disconnect_ = function() {
                Lv && this.connected_ && (document.removeEventListener("transitionend", this.onTransitionEnd_), window.removeEventListener("resize", this.refresh), this.mutationsObserver_ && this.mutationsObserver_.disconnect(), this.mutationEventsAdded_ && document.removeEventListener("DOMSubtreeModified", this.refresh), this.mutationsObserver_ = null, this.mutationEventsAdded_ = !1, this.connected_ = !1)
            }, e.prototype.onTransitionEnd_ = function(e) {
                var t = e.propertyName,
                    n = void 0 === t ? "" : t;
                Pv.some(function(e) {
                    return !!~n.indexOf(e)
                }) && this.refresh()
            }, e.getInstance = function() {
                return this.instance_ || (this.instance_ = new e), this.instance_
            }, e.instance_ = null, e
        }(),
        Hv = function(e, t) {
            for (var n = 0, r = Object.keys(t); n < r.length; n++) {
                var o = r[n];
                Object.defineProperty(e, o, {
                    value: t[o],
                    enumerable: !1,
                    writable: !1,
                    configurable: !0
                })
            }
            return e
        },
        zv = function(e) {
            return e && e.ownerDocument && e.ownerDocument.defaultView || Iv
        },
        qv = Uv(0, 0, 0, 0);

    function Vv(e) {
        return parseFloat(e) || 0
    }

    function jv(e) {
        for (var t = [], n = 1; n < arguments.length; n++) t[n - 1] = arguments[n];
        return t.reduce(function(t, n) {
            return t + Vv(e["border-" + n + "-width"])
        }, 0)
    }
    var $v = "undefined" != typeof SVGGraphicsElement ? function(e) {
        return e instanceof zv(e).SVGGraphicsElement
    } : function(e) {
        return e instanceof zv(e).SVGElement && "function" == typeof e.getBBox
    };

    function _v(e) {
        return Lv ? $v(e) ? function(e) {
            var t = e.getBBox();
            return Uv(0, 0, t.width, t.height)
        }(e) : function(e) {
            var t = e.clientWidth,
                n = e.clientHeight;
            if (!t && !n) return qv;
            var r = zv(e).getComputedStyle(e),
                o = function(e) {
                    for (var t = {}, n = 0, r = ["top", "right", "bottom", "left"]; n < r.length; n++) {
                        var o = r[n],
                            i = e["padding-" + o];
                        t[o] = Vv(i)
                    }
                    return t
                }(r),
                i = o.left + o.right,
                s = o.top + o.bottom,
                a = Vv(r.width),
                l = Vv(r.height);
            if ("border-box" === r.boxSizing && (Math.round(a + i) !== t && (a -= jv(r, "left", "right") + i), Math.round(l + s) !== n && (l -= jv(r, "top", "bottom") + s)), ! function(e) {
                    return e === zv(e).document.documentElement
                }(e)) {
                var c = Math.round(a + i) - t,
                    u = Math.round(l + s) - n;
                1 !== Math.abs(c) && (a -= c), 1 !== Math.abs(u) && (l -= u)
            }
            return Uv(o.left, o.top, a, l)
        }(e) : qv
    }

    function Uv(e, t, n, r) {
        return {
            x: e,
            y: t,
            width: n,
            height: r
        }
    }
    var Wv = function() {
            function e(e) {
                this.broadcastWidth = 0, this.broadcastHeight = 0, this.contentRect_ = Uv(0, 0, 0, 0), this.target = e
            }
            return e.prototype.isActive = function() {
                var e = _v(this.target);
                return this.contentRect_ = e, e.width !== this.broadcastWidth || e.height !== this.broadcastHeight
            }, e.prototype.broadcastRect = function() {
                var e = this.contentRect_;
                return this.broadcastWidth = e.width, this.broadcastHeight = e.height, e
            }, e
        }(),
        Jv = function(e, t) {
            var n, r, o, i, s, a, l, c = (r = (n = t).x, o = n.y, i = n.width, s = n.height, a = "undefined" != typeof DOMRectReadOnly ? DOMRectReadOnly : Object, l = Object.create(a.prototype), Hv(l, {
                x: r,
                y: o,
                width: i,
                height: s,
                top: o,
                right: r + i,
                bottom: s + o,
                left: r
            }), l);
            Hv(this, {
                target: e,
                contentRect: c
            })
        },
        Kv = function() {
            function e(e, t, n) {
                if (this.activeObservations_ = [], this.observations_ = new Av, "function" != typeof e) throw new TypeError("The callback provided as parameter 1 is not a function.");
                this.callback_ = e, this.controller_ = t, this.callbackCtx_ = n
            }
            return e.prototype.observe = function(e) {
                if (!arguments.length) throw new TypeError("1 argument required, but only 0 present.");
                if ("undefined" != typeof Element && Element instanceof Object) {
                    if (!(e instanceof zv(e).Element)) throw new TypeError('parameter 1 is not of type "Element".');
                    var t = this.observations_;
                    t.has(e) || (t.set(e, new Wv(e)), this.controller_.addObserver(this), this.controller_.refresh())
                }
            }, e.prototype.unobserve = function(e) {
                if (!arguments.length) throw new TypeError("1 argument required, but only 0 present.");
                if ("undefined" != typeof Element && Element instanceof Object) {
                    if (!(e instanceof zv(e).Element)) throw new TypeError('parameter 1 is not of type "Element".');
                    var t = this.observations_;
                    t.has(e) && (t.delete(e), t.size || this.controller_.removeObserver(this))
                }
            }, e.prototype.disconnect = function() {
                this.clearActive(), this.observations_.clear(), this.controller_.removeObserver(this)
            }, e.prototype.gatherActive = function() {
                var e = this;
                this.clearActive(), this.observations_.forEach(function(t) {
                    t.isActive() && e.activeObservations_.push(t)
                })
            }, e.prototype.broadcastActive = function() {
                if (this.hasActive()) {
                    var e = this.callbackCtx_,
                        t = this.activeObservations_.map(function(e) {
                            return new Jv(e.target, e.broadcastRect())
                        });
                    this.callback_.call(e, t, e), this.clearActive()
                }
            }, e.prototype.clearActive = function() {
                this.activeObservations_.splice(0)
            }, e.prototype.hasActive = function() {
                return this.activeObservations_.length > 0
            }, e
        }(),
        Gv = "undefined" != typeof WeakMap ? new WeakMap : new Av,
        Xv = function e(t) {
            if (!(this instanceof e)) throw new TypeError("Cannot call a class as a function.");
            if (!arguments.length) throw new TypeError("1 argument required, but only 0 present.");
            var n = Fv.getInstance(),
                r = new Kv(t, n, this);
            Gv.set(this, r)
        };
    ["observe", "unobserve", "disconnect"].forEach(function(e) {
        Xv.prototype[e] = function() {
            var t;
            return (t = Gv.get(this))[e].apply(t, arguments)
        }
    });
    var Zv, Qv, Yv, ey, ty, ny, ry, oy, iy, sy, ay, ly, cy, uy, dy, py, hy = void 0 !== Iv.ResizeObserver ? Iv.ResizeObserver : Xv,
        fy = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), t.prototype.execCommand = function(e) {
                var t = il(e.target, "li");
                this.props.execCommand("heading", {
                    level: Number(t.getAttribute("data-level"))
                })
            }, t.prototype.render = function() {
                var e = this;
                return gv(Qv || (Qv = Ui(["\n      <ul\n        onClick=", '\n        aria-role="menu"\n        aria-label="', '"\n      >\n        ', '\n        <li data-type="Paragraph" aria-role="menuitem">\n          <div>', "</div>\n        </li>\n      </ul>\n    "], ["\n      <ul\n        onClick=", '\n        aria-role="menu"\n        aria-label="', '"\n      >\n        ', '\n        <li data-type="Paragraph" aria-role="menuitem">\n          <div>', "</div>\n        </li>\n      </ul>\n    "])), function(t) {
                    return e.execCommand(t)
                }, wm.get("Headings"), [1, 2, 3, 4, 5, 6].map(function(e) {
                    return gv(Zv || (Zv = Ui(['\n              <li data-level="', '" data-type="Heading" aria-role="menuitem">\n                <', ">", " ", "</$>\n              </li>\n            "], ['\n              <li data-level="', '" data-type="Heading" aria-role="menuitem">\n                <', ">", " ", "</$>\n              </li>\n            "])), e, "h" + e, wm.get("Heading"), e)
                }), wm.get("Paragraph"))
            }, t
        }(Nv),
        my = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), t.prototype.toggleTab = function(e, t) {
                this.props.onClick(e, t)
            }, t.prototype.render = function() {
                var e = this;
                return gv(ey || (ey = Ui(['\n      <div class="', '" aria-role="tabpanel">\n        ', "\n      </div>\n    "], ['\n      <div class="', '" aria-role="tabpanel">\n        ', "\n      </div>\n    "])), Qa("tabs"), this.props.tabs.map(function(t) {
                    var n = t.name,
                        r = t.text,
                        o = e.props.activeTab === n;
                    return gv(Yv || (Yv = Ui(['\n            <div\n              class="tab-item', '"\n              onClick=', '\n              aria-role="tab"\n              aria-label="', '"\n              aria-selected="', '"\n              tabindex="', '"\n            >\n              ', "\n            </div>\n          "], ['\n            <div\n              class="tab-item', '"\n              onClick=', '\n              aria-role="tab"\n              aria-label="', '"\n              aria-selected="', '"\n              tabindex="', '"\n            >\n              ', "\n            </div>\n          "])), o ? " active" : "", function(t) {
                        return e.toggleTab(t, n)
                    }, wm.get(r), o ? "true" : "false", o ? "0" : "-1", wm.get(r))
                }))
            }, t
        }(Nv),
        gy = function(e) {
            function t(t) {
                var n = e.call(this, t) || this;
                return n.initialize = function(e) {
                    void 0 === e && (e = "file");
                    var t = n.refs.url;
                    t.value = "", n.refs.altText.value = "", n.refs.file.value = "", xs(t, "wrong"), n.setState({
                        activeTab: e,
                        file: null,
                        fileNameElClassName: ""
                    })
                }, n.execCommand = function() {
                    "file" === n.state.activeTab ? n.emitAddImageBlob() : n.emitAddImage()
                }, n.toggleTab = function(e, t) {
                    t !== n.state.activeTab && n.initialize(t)
                }, n.showFileSelectBox = function() {
                    n.refs.file.click()
                }, n.changeFile = function(e) {
                    var t = e.target.files;
                    (null == t ? void 0 : t.length) && n.setState({
                        file: t[0]
                    })
                }, n.state = {
                    activeTab: "file",
                    file: null,
                    fileNameElClassName: ""
                }, n.tabs = [{
                    name: "file",
                    text: "File"
                }, {
                    name: "url",
                    text: "URL"
                }], n
            }
            return ji(t, e), t.prototype.emitAddImageBlob = function() {
                var e = this,
                    t = this.refs.file.files,
                    n = this.refs.altText,
                    r = " wrong";
                if (null == t ? void 0 : t.length) {
                    r = "";
                    var o = t.item(0);
                    this.props.eventEmitter.emit("addImageBlobHook", o, function(t, r) {
                        return e.props.execCommand("addImage", {
                            imageUrl: t,
                            altText: r || n.value
                        })
                    }, "ui")
                }
                this.setState({
                    fileNameElClassName: r
                })
            }, t.prototype.emitAddImage = function() {
                var e = this.refs.url,
                    t = this.refs.altText,
                    n = e.value,
                    r = t.value || "image";
                xs(e, "wrong"), n.length ? n && this.props.execCommand("addImage", {
                    imageUrl: n,
                    altText: r
                }) : vs(e, "wrong")
            }, t.prototype.preventSelectStart = function(e) {
                e.preventDefault()
            }, t.prototype.updated = function() {
                this.props.show || this.initialize()
            }, t.prototype.render = function() {
                var e = this,
                    t = this.state,
                    n = t.activeTab,
                    r = t.file,
                    o = t.fileNameElClassName;
                return gv(ty || (ty = Ui(['\n      <div aria-label="', '">\n        <', " tabs=", " activeTab=", " onClick=", ' />\n        <div style="display:', '">\n          <label for="toastuiImageUrlInput">', '</label>\n          <input\n            id="toastuiImageUrlInput"\n            type="text"\n            ref=', '\n          />\n        </div>\n        <div style="display:', ';position: relative;">\n          <label for="toastuiImageFileInput">', '</label>\n          <span\n            class="', "", '"\n            onClick=', "\n            onSelectstart=", "\n          >\n            ", '\n          </span>\n          <button\n            type="button"\n            class="', '"\n            onClick=', "\n          >\n            ", '\n          </button>\n          <input\n            id="toastuiImageFileInput"\n            type="file"\n            accept="image/*"\n            onChange=', "\n            ref=", '\n          />\n        </div>\n        <label for="toastuiAltTextInput">', '</label>\n        <input\n          id="toastuiAltTextInput"\n          type="text"\n          ref=', '\n        />\n        <div class="', '">\n          <button type="button" class="', '" onClick=', ">\n            ", '\n          </button>\n          <button type="button" class="', '" onClick=', ">\n            ", "\n          </button>\n        </div>\n      </div>\n    "], ['\n      <div aria-label="', '">\n        <', " tabs=", " activeTab=", " onClick=", ' />\n        <div style="display:', '">\n          <label for="toastuiImageUrlInput">', '</label>\n          <input\n            id="toastuiImageUrlInput"\n            type="text"\n            ref=', '\n          />\n        </div>\n        <div style="display:', ';position: relative;">\n          <label for="toastuiImageFileInput">', '</label>\n          <span\n            class="', "", '"\n            onClick=', "\n            onSelectstart=", "\n          >\n            ", '\n          </span>\n          <button\n            type="button"\n            class="', '"\n            onClick=', "\n          >\n            ", '\n          </button>\n          <input\n            id="toastuiImageFileInput"\n            type="file"\n            accept="image/*"\n            onChange=', "\n            ref=", '\n          />\n        </div>\n        <label for="toastuiAltTextInput">', '</label>\n        <input\n          id="toastuiAltTextInput"\n          type="text"\n          ref=', '\n        />\n        <div class="', '">\n          <button type="button" class="', '" onClick=', ">\n            ", '\n          </button>\n          <button type="button" class="', '" onClick=', ">\n            ", "\n          </button>\n        </div>\n      </div>\n    "])), wm.get("Insert image"), my, this.tabs, n, this.toggleTab, "url" === n ? "block" : "none", wm.get("Image URL"), function(t) {
                    return e.refs.url = t
                }, "file" === n ? "block" : "none", wm.get("Select image file"), Qa("file-name"), r ? " has-file" : o, this.showFileSelectBox, this.preventSelectStart, r ? r.name : wm.get("No file"), Qa("file-select-button"), this.showFileSelectBox, wm.get("Choose a file"), this.changeFile, function(t) {
                    return e.refs.file = t
                }, wm.get("Description"), function(t) {
                    return e.refs.altText = t
                }, Qa("button-container"), Qa("close-button"), this.props.hidePopup, wm.get("Cancel"), Qa("ok-button"), this.execCommand, wm.get("OK"))
            }, t
        }(Nv),
        vy = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.execCommand = function() {
                    var e = t.refs.url,
                        n = t.refs.text;
                    xs(e, "wrong"), xs(n, "wrong"), e.value.length < 1 ? vs(e, "wrong") : as(t.props.initialValues.linkUrl) && n.value.length < 1 ? vs(n, "wrong") : t.props.execCommand("addLink", {
                        linkUrl: e.value,
                        linkText: n.value
                    })
                }, t
            }
            return ji(t, e), t.prototype.initialize = function() {
                var e = this.props.initialValues,
                    t = e.linkUrl,
                    n = e.linkText,
                    r = this.refs.url,
                    o = this.refs.text;
                xs(r, "wrong"), xs(o, "wrong", "disabled"), o.removeAttribute("disabled"), t && (vs(o, "disabled"), o.setAttribute("disabled", "disabled")), r.value = t || "", o.value = n || ""
            }, t.prototype.mounted = function() {
                this.initialize()
            }, t.prototype.updated = function(e) {
                !e.show && this.props.show && this.initialize()
            }, t.prototype.render = function() {
                var e = this;
                return gv(ny || (ny = Ui(['\n      <div aria-label="', '">\n        <label for="toastuiLinkUrlInput">', '</label>\n        <input\n          id="toastuiLinkUrlInput"\n          type="text"\n          ref=', '\n        />\n        <label for="toastuiLinkTextInput">', '</label>\n        <input\n          id="toastuiLinkTextInput"\n          type="text"\n          ref=', '\n        />\n        <div class="', '">\n          <button type="button" class="', '" onClick=', ">\n            ", '\n          </button>\n          <button type="button" class="', '" onClick=', ">\n            ", "\n          </button>\n        </div>\n      </div>\n    "], ['\n      <div aria-label="', '">\n        <label for="toastuiLinkUrlInput">', '</label>\n        <input\n          id="toastuiLinkUrlInput"\n          type="text"\n          ref=', '\n        />\n        <label for="toastuiLinkTextInput">', '</label>\n        <input\n          id="toastuiLinkTextInput"\n          type="text"\n          ref=', '\n        />\n        <div class="', '">\n          <button type="button" class="', '" onClick=', ">\n            ", '\n          </button>\n          <button type="button" class="', '" onClick=', ">\n            ", "\n          </button>\n        </div>\n      </div>\n    "])), wm.get("Insert link"), wm.get("URL"), function(t) {
                    return e.refs.url = t
                }, wm.get("Link text"), function(t) {
                    return e.refs.text = t
                }, Qa("button-container"), Qa("close-button"), this.props.hidePopup, wm.get("Cancel"), Qa("ok-button"), this.execCommand, wm.get("OK"))
            }, t
        }(Nv),
        yy = function(e) {
            function t(t) {
                var n = e.call(this, t) || this;
                return n.extendSelectionRange = function(e) {
                    var t = e.pageX,
                        r = e.pageY,
                        o = t - n.offsetRect.left,
                        i = r - n.offsetRect.top,
                        s = n.getSelectionRangeByOffset(o, i);
                    n.setState($i({}, s))
                }, n.execCommand = function() {
                    n.props.execCommand("addTable", {
                        rowCount: n.state.rowIdx + 1,
                        columnCount: n.state.colIdx + 1
                    })
                }, n.state = {
                    rowIdx: -1,
                    colIdx: -1
                }, n
            }
            return ji(t, e), t.prototype.getDescription = function() {
                return -1 === this.state.colIdx ? "" : this.state.colIdx + 1 + " x " + (this.state.rowIdx + 1)
            }, t.prototype.getBoundByRange = function(e, t) {
                return {
                    width: 20 * (e + 1),
                    height: 20 * (t + 1)
                }
            }, t.prototype.getRangeByOffset = function(e, t) {
                return {
                    colIdx: Math.floor(e / 20),
                    rowIdx: Math.floor(t / 20)
                }
            }, t.prototype.getTableRange = function() {
                var e = this.state,
                    t = e.colIdx,
                    n = e.rowIdx,
                    r = Math.max(t, 5),
                    o = Math.max(n, 5);
                return t >= 5 && r < 9 && (r += 1), n >= 5 && o < 14 && (o += 1), {
                    colIdx: r + 1,
                    rowIdx: o + 1
                }
            }, t.prototype.getSelectionAreaBound = function() {
                var e = this.getBoundByRange(this.state.colIdx, this.state.rowIdx),
                    t = e.width,
                    n = e.height;
                return t || n ? {
                    width: t - 1,
                    height: n - 1,
                    display: "block"
                } : {
                    display: "none"
                }
            }, t.prototype.getSelectionRangeByOffset = function(e, t) {
                var n = this.getRangeByOffset(e, t);
                return n.rowIdx = Math.min(Math.max(n.rowIdx, 1), 14), n.colIdx = Math.min(Math.max(n.colIdx, 1), 9), n
            }, t.prototype.updated = function() {
                if (this.props.show) {
                    if (-1 === this.state.colIdx && -1 === this.state.rowIdx) {
                        var e = this.refs.tableEl.getBoundingClientRect(),
                            t = e.left,
                            n = e.top;
                        this.offsetRect = {
                            left: window.pageXOffset + t,
                            top: window.pageYOffset + n
                        }
                    }
                } else this.setState({
                    colIdx: -1,
                    rowIdx: -1
                })
            }, t.prototype.createTableArea = function(e) {
                for (var t = e.colIdx, n = e.rowIdx, r = [], o = 0; o < n; o += 1) {
                    for (var i = [], s = 0; s < t; s += 1) {
                        var a = Qa("table-cell") + (o > 0 ? "" : " header");
                        i.push(gv(ry || (ry = Ui(['<div class="', '"></div>'], ['<div class="', '"></div>'])), a))
                    }
                    r.push(gv(oy || (oy = Ui(['<div class="', '">', "</div>"], ['<div class="', '">', "</div>"])), Qa("table-row"), i))
                }
                return gv(iy || (iy = Ui(['<div class="', '">', "</div>"], ['<div class="', '">', "</div>"])), Qa("table"), r)
            }, t.prototype.render = function() {
                var e = this,
                    t = this.getTableRange(),
                    n = this.getSelectionAreaBound();
                return gv(sy || (sy = Ui(['\n      <div aria-label="', '">\n        <div\n          class="', '"\n          ref=', "\n          onMousemove=", "\n          onClick=", "\n        >\n          ", '\n          <div class="', '" style=', '></div>\n        </div>\n        <p class="', '">', "</p>\n      </div>\n    "], ['\n      <div aria-label="', '">\n        <div\n          class="', '"\n          ref=', "\n          onMousemove=", "\n          onClick=", "\n        >\n          ", '\n          <div class="', '" style=', '></div>\n        </div>\n        <p class="', '">', "</p>\n      </div>\n    "])), wm.get("Insert table"), Qa("table-selection"), function(t) {
                    return e.refs.tableEl = t
                }, this.extendSelectionRange, this.execCommand, this.createTableArea(t), Qa("table-selection-layer"), n, Qa("table-description"), this.getDescription())
            }, t
        }(Nv),
        by = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), t.prototype.mounted = function() {
                this.refs.el.appendChild(this.props.body)
            }, t.prototype.updated = function(e) {
                this.refs.el.replaceChild(this.props.body, e.body)
            }, t.prototype.render = function() {
                var e = this;
                return gv(ay || (ay = Ui(["<div ref=", "></div>"], ["<div ref=", "></div>"])), function(t) {
                    return e.refs.el = t
                })
            }, t
        }(Nv);

    function wy(e) {
        return Ki(e) ? function(e) {
            var t;
            switch (e) {
                case "heading":
                    t = {
                        name: "heading",
                        className: "heading",
                        tooltip: wm.get("Headings"),
                        state: "heading"
                    };
                    break;
                case "bold":
                    t = {
                        name: "bold",
                        className: "bold",
                        command: "bold",
                        tooltip: wm.get("Bold"),
                        state: "strong"
                    };
                    break;
                case "italic":
                    t = {
                        name: "italic",
                        className: "italic",
                        command: "italic",
                        tooltip: wm.get("Italic"),
                        state: "emph"
                    };
                    break;
                case "strike":
                    t = {
                        name: "strike",
                        className: "strike",
                        command: "strike",
                        tooltip: wm.get("Strike"),
                        state: "strike"
                    };
                    break;
                case "hr":
                    t = {
                        name: "hr",
                        className: "hrline",
                        command: "hr",
                        tooltip: wm.get("Line"),
                        state: "thematicBreak"
                    };
                    break;
                case "quote":
                    t = {
                        name: "quote",
                        className: "quote",
                        command: "blockQuote",
                        tooltip: wm.get("Blockquote"),
                        state: "blockQuote"
                    };
                    break;
                case "ul":
                    t = {
                        name: "ul",
                        className: "bullet-list",
                        command: "bulletList",
                        tooltip: wm.get("Unordered list"),
                        state: "bulletList"
                    };
                    break;
                case "ol":
                    t = {
                        name: "ol",
                        className: "ordered-list",
                        command: "orderedList",
                        tooltip: wm.get("Ordered list"),
                        state: "orderedList"
                    };
                    break;
                case "task":
                    t = {
                        name: "task",
                        className: "task-list",
                        command: "taskList",
                        tooltip: wm.get("Task"),
                        state: "taskList"
                    };
                    break;
                case "table":
                    t = {
                        name: "table",
                        className: "table",
                        tooltip: wm.get("Insert table"),
                        state: "table"
                    };
                    break;
                case "image":
                    t = {
                        name: "image",
                        className: "image",
                        tooltip: wm.get("Insert image")
                    };
                    break;
                case "link":
                    t = {
                        name: "link",
                        className: "link",
                        tooltip: wm.get("Insert link")
                    };
                    break;
                case "code":
                    t = {
                        name: "code",
                        className: "code",
                        command: "code",
                        tooltip: wm.get("Code"),
                        state: "code"
                    };
                    break;
                case "codeblock":
                    t = {
                        name: "codeblock",
                        className: "codeblock",
                        command: "codeBlock",
                        tooltip: wm.get("Insert CodeBlock"),
                        state: "codeBlock"
                    };
                    break;
                case "indent":
                    t = {
                        name: "indent",
                        className: "indent",
                        command: "indent",
                        tooltip: wm.get("Indent"),
                        state: "indent"
                    };
                    break;
                case "outdent":
                    t = {
                        name: "outdent",
                        className: "outdent",
                        command: "outdent",
                        tooltip: wm.get("Outdent"),
                        state: "outdent"
                    };
                    break;
                case "scrollSync":
                    t = function() {
                        var e = document.createElement("label"),
                            t = document.createElement("input"),
                            n = document.createElement("span");
                        e.className = "scroll-sync active", t.type = "checkbox", t.checked = !0, n.className = "switch";
                        return e.appendChild(t), e.appendChild(n), {
                            name: "scrollSync",
                            el: e,
                            onMounted: function(n) {
                                return t.addEventListener("change", function(t) {
                                    var r = t.target.checked;
                                    r ? vs(e, "active") : xs(e, "active"), n("toggleScrollSync", {
                                        active: r
                                    })
                                })
                            }
                        }
                    }();
                    break;
                case "more":
                    t = {
                        name: "more",
                        className: "more",
                        tooltip: wm.get("More")
                    }
            }
            return "scrollSync" !== t.name && (t.className += " " + Qa("toolbar-icons")), t
        }(e) : e
    }

    function ky(e, t) {
        var n = t.el,
            r = t.pos,
            o = t.popup,
            i = t.initialValues;
        switch (e) {
            case "heading":
                return {
                    render: function(e) {
                        return gv(ly || (ly = Ui(["<", " ...", " />"], ["<", " ...", " />"])), fy, e)
                    }, className: Qa("popup-add-heading"), fromEl: n, pos: r
                };
            case "link":
                return {
                    render: function(e) {
                        return gv(cy || (cy = Ui(["<", " ...", " />"], ["<", " ...", " />"])), vy, e)
                    }, className: Qa("popup-add-link"), fromEl: n, pos: r, initialValues: i
                };
            case "image":
                return {
                    render: function(e) {
                        return gv(uy || (uy = Ui(["<", " ...", " />"], ["<", " ...", " />"])), gy, e)
                    }, className: Qa("popup-add-image"), fromEl: n, pos: r
                };
            case "table":
                return {
                    render: function(e) {
                        return gv(dy || (dy = Ui(["<", " ...", " />"], ["<", " ...", " />"])), yy, e)
                    }, className: Qa("popup-add-table"), fromEl: n, pos: r
                };
            case "customPopupBody":
                return o ? $i({
                    render: function(e) {
                        return gv(py || (py = Ui(["<", " ...", " body=", " />"], ["<", " ...", " body=", " />"])), by, e, o.body)
                    },
                    fromEl: n,
                    pos: r
                }, o) : null;
            default:
                return null
        }
    }

    function xy(e) {
        e.hidden = e.length === e.filter(function(e) {
            return e.hidden
        }).length
    }
    var Cy, Ty, My = function(e) {
        function t() {
            var t = null !== e && e.apply(this, arguments) || this;
            return t.handleMousedown = function(e) {
                il(e.target, "." + Qa("popup")) || il(e.target, t.props.info.fromEl) || t.props.hidePopup()
            }, t
        }
        return ji(t, e), t.prototype.mounted = function() {
            document.addEventListener("mousedown", this.handleMousedown), this.props.eventEmitter.listen("closePopup", this.props.hidePopup)
        }, t.prototype.beforeDestroy = function() {
            document.removeEventListener("mousedown", this.handleMousedown)
        }, t.prototype.updated = function(e) {
            var t = this.props,
                n = t.show,
                r = t.info;
            if (n && r.pos && e.show !== n) {
                var o = $i({}, r.pos),
                    i = this.refs.el.offsetWidth,
                    s = il(this.refs.el, "." + Qa("toolbar")).offsetWidth;
                o.left + i >= s && (o.left = s - i - 20), Js(this.state.popupPos, o) || this.setState({
                    popupPos: o
                })
            }
        }, t.prototype.render = function() {
            var e = this,
                t = this.props,
                n = t.info,
                r = t.show,
                o = t.hidePopup,
                i = t.eventEmitter,
                s = t.execCommand,
                a = n || {},
                l = a.className,
                c = void 0 === l ? "" : l,
                u = a.style,
                d = a.render,
                p = a.initialValues,
                h = void 0 === p ? {} : p,
                f = $i($i({
                    display: r ? "block" : "none"
                }, u), this.state.popupPos);
            return gv(Cy || (Cy = Ui(['\n      <div\n        class="', " ", '"\n        style=', "\n        ref=", '\n        aria-role="dialog"\n      >\n        <div class="', '">\n          ', "\n        </div>\n      </div>\n    "], ['\n      <div\n        class="', " ", '"\n        style=', "\n        ref=", '\n        aria-role="dialog"\n      >\n        <div class="', '">\n          ', "\n        </div>\n      </div>\n    "])), Qa("popup"), c, f, function(t) {
                return e.refs.el = t
            }, Qa("popup-body"), d && d({
                eventEmitter: i,
                show: r,
                hidePopup: o,
                execCommand: s,
                initialValues: h
            }))
        }, t
    }(Nv);

    function Sy(e) {
        return function(t) {
            function n(e) {
                var n = t.call(this, e) || this;
                return n.showTooltip = function(e) {
                    var t = n.props.item.tooltip;
                    if (!n.props.disabled && t) {
                        var r = n.getBound(e),
                            o = r.left + 6 + "px",
                            i = r.top + 6 + "px";
                        rs(n.props.tooltipRef.current, {
                            display: "block",
                            left: o,
                            top: i
                        }), n.props.tooltipRef.current.querySelector(".text").textContent = t
                    }
                }, n.hideTooltip = function() {
                    rs(n.props.tooltipRef.current, "display", "none")
                }, n.state = {
                    active: !1,
                    disabled: e.disabled
                }, n.addEvent(), n
            }
            return ji(n, t), n.prototype.addEvent = function() {
                var e = this,
                    t = this.props,
                    n = t.item,
                    r = t.eventEmitter;
                n.state && r.listen("changeToolbarState", function(t) {
                    var r, o = null !== (r = t.toolbarState[n.state]) && void 0 !== r ? r : {},
                        i = o.active,
                        s = o.disabled;
                    e.setState({
                        active: !!i,
                        disabled: null != s ? s : e.props.disabled
                    })
                })
            }, n.prototype.getBound = function(e) {
                var t = sl(e, il(e, "." + Qa("toolbar"))),
                    n = t.offsetLeft,
                    r = t.offsetTop;
                return {
                    left: n,
                    top: e.offsetHeight + r
                }
            }, n.prototype.render = function() {
                return gv(Ty || (Ty = Ui(["\n        <", "\n          ...", "\n          active=", "\n          showTooltip=", "\n          hideTooltip=", "\n          getBound=", "\n          disabled=", "\n        />\n      "], ["\n        <", "\n          ...", "\n          active=", "\n          showTooltip=", "\n          hideTooltip=", "\n          getBound=", "\n          disabled=", "\n        />\n      "])), e, this.props, this.state.active, this.showTooltip, this.hideTooltip, this.getBound, this.state.disabled || this.props.disabled)
            }, n
        }(Nv)
    }
    var Ey, Ny, Oy, Dy, Ay, Ly, Iy, Ry, Py, By, Fy, Hy, zy, qy, Vy = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.showTooltip = function() {
                    t.props.showTooltip(t.refs.el)
                }, t.execCommand = function() {
                    var e = t.props,
                        n = e.item,
                        r = e.execCommand,
                        o = e.setPopupInfo,
                        i = e.getBound,
                        s = e.eventEmitter,
                        a = n.command,
                        l = n.name,
                        c = n.popup;
                    if (a) r(a);
                    else {
                        var u = c ? "customPopupBody" : l,
                            d = s.emit("query", "getPopupInitialValues", {
                                popupName: u
                            })[0],
                            p = ky(u, {
                                el: t.refs.el,
                                pos: i(t.refs.el),
                                popup: c,
                                initialValues: d
                            });
                        p && o(p)
                    }
                }, t
            }
            return ji(t, e), t.prototype.mounted = function() {
                this.setItemWidth()
            }, t.prototype.updated = function(e) {
                e.item.name !== this.props.item.name && this.setItemWidth()
            }, t.prototype.setItemWidth = function() {
                var e = this.props,
                    t = e.setItemWidth,
                    n = e.item;
                t && t(n.name, ol(this.refs.el) + (n.hidden ? 80 : 0))
            }, t.prototype.render = function() {
                var e = this,
                    t = this.props,
                    n = t.hideTooltip,
                    r = t.disabled,
                    o = t.item,
                    i = t.active,
                    s = $i({
                        display: o.hidden ? "none" : null
                    }, o.style),
                    a = (o.className || "") + (i ? " active" : "");
                return gv(Ey || (Ey = Ui(["\n      <button\n        ref=", '\n        type="button"\n        style=', "\n        class=", "\n        onClick=", "\n        onMouseover=", "\n        onMouseout=", "\n        disabled=", "\n        aria-label=", "\n      >\n        ", "\n      </button>\n    "], ["\n      <button\n        ref=", '\n        type="button"\n        style=', "\n        class=", "\n        onClick=", "\n        onMouseover=", "\n        onMouseout=", "\n        disabled=", "\n        aria-label=", "\n      >\n        ", "\n      </button>\n    "])), function(t) {
                    return e.refs.el = t
                }, s, a, this.execCommand, this.showTooltip, n, !!r, o.text || o.tooltip || "", o.text || "")
            }, t
        }(Nv),
        jy = Sy(Vy),
        $y = function(e) {
            function t() {
                var t = null !== e && e.apply(this, arguments) || this;
                return t.showTooltip = function() {
                    t.props.showTooltip(t.refs.el)
                }, t.showPopup = function() {
                    var e = ky("customPopupBody", {
                        el: t.refs.el,
                        pos: t.props.getBound(t.refs.el),
                        popup: t.props.item.popup
                    });
                    e && t.props.setPopupInfo(e)
                }, t
            }
            return ji(t, e), t.prototype.mounted = function() {
                var e = this.props,
                    t = e.setItemWidth,
                    n = e.item;
                this.refs.el.appendChild(n.el), t && t(n.name, ol(this.refs.el)), n.onMounted && n.onMounted(this.props.execCommand)
            }, t.prototype.updated = function(e) {
                var t, n = this.props,
                    r = n.item,
                    o = n.active,
                    i = n.disabled;
                e.active === o && e.disabled === i || null === (t = r.onUpdated) || void 0 === t || t.call(r, {
                    active: o,
                    disabled: i
                })
            }, t.prototype.render = function() {
                var e = this,
                    t = this.props,
                    n = t.disabled,
                    r = {
                        display: t.item.hidden ? "none" : "inline-block"
                    },
                    o = function(e) {
                        return n ? null : e
                    };
                return gv(Ny || (Ny = Ui(["\n      <div\n        ref=", "\n        style=", "\n        class=", "\n        onClick=", "\n        onMouseover=", "\n        onMouseout=", "\n      ></div>\n    "], ["\n      <div\n        ref=", "\n        style=", "\n        class=", "\n        onClick=", "\n        onMouseover=", "\n        onMouseout=", "\n      ></div>\n    "])), function(t) {
                    return e.refs.el = t
                }, r, Qa("toolbar-item-wrapper"), o(this.showPopup), o(this.showTooltip), o(this.props.hideTooltip))
            }, t
        }(Nv),
        _y = Sy($y),
        Uy = function(e) {
            function t() {
                return null !== e && e.apply(this, arguments) || this
            }
            return ji(t, e), t.prototype.render = function() {
                var e = this,
                    t = this.props,
                    n = t.group,
                    r = t.hiddenDivider,
                    o = n.hidden ? {
                        display: "none"
                    } : null,
                    i = r ? {
                        display: "none"
                    } : null;
                return gv(Dy || (Dy = Ui(['\n      <div class="', '" style=', ">\n        ", '\n        <div class="', '" style=', "></div>\n      </div>\n    "], ['\n      <div class="', '" style=', ">\n        ", '\n        <div class="', '" style=', "></div>\n      </div>\n    "])), Qa("toolbar-group"), o, n.map(function(t) {
                    var n = t.el ? _y : jy;
                    return gv(Oy || (Oy = Ui(["<", " key=", " ...", " item=", " />"], ["<", " key=", " ...", " item=", " />"])), n, t.name, e.props, t)
                }), Qa("toolbar-divider"), i)
            }, t
        }(Nv),
        Wy = function(e) {
            function t(t) {
                var n = e.call(this, t) || this;
                return n.handleClickDocument = function(e) {
                    var t = e.target;
                    il(t, "." + Qa("dropdown-toolbar")) || il(t, ".more") || n.setState({
                        showDropdown: !1,
                        dropdownPos: null
                    })
                }, n.showTooltip = function() {
                    n.props.showTooltip(n.refs.el)
                }, n.state = {
                    showDropdown: !1,
                    dropdownPos: null
                }, n
            }
            return ji(t, e), t.prototype.getBound = function() {
                var e = this.props.getBound(this.refs.el);
                return e.top += 4, $i($i({}, e), {
                    left: null,
                    right: 10
                })
            }, t.prototype.mounted = function() {
                document.addEventListener("click", this.handleClickDocument)
            }, t.prototype.updated = function() {
                this.state.showDropdown && !this.state.dropdownPos && this.setState({
                    dropdownPos: this.getBound()
                })
            }, t.prototype.beforeDestroy = function() {
                document.removeEventListener("click", this.handleClickDocument)
            }, t.prototype.render = function() {
                var e = this,
                    t = this.state,
                    n = t.showDropdown,
                    r = t.dropdownPos,
                    o = this.props,
                    i = o.disabled,
                    s = o.item,
                    a = o.items,
                    l = o.hideTooltip,
                    c = a.filter(function(e) {
                        return !e.hidden
                    }),
                    u = c.length ? null : {
                        display: "none"
                    },
                    d = n ? null : {
                        display: "none"
                    };
                return gv(Ly || (Ly = Ui(['\n      <div class="', '" style=', ">\n        <button\n          ref=", '\n          type="button"\n          class=', "\n          onClick=", "\n          onMouseover=", "\n          onMouseout=", "\n          disabled=", '\n        ></button>\n        <div\n          class="', '"\n          style=', "\n          ref=", "\n        >\n          ", "\n        </div>\n      </div>\n    "], ['\n      <div class="', '" style=', ">\n        <button\n          ref=", '\n          type="button"\n          class=', "\n          onClick=", "\n          onMouseover=", "\n          onMouseout=", "\n          disabled=", '\n        ></button>\n        <div\n          class="', '"\n          style=', "\n          ref=", "\n        >\n          ", "\n        </div>\n      </div>\n    "])), Qa("toolbar-group"), u, function(t) {
                    return e.refs.el = t
                }, s.className, function() {
                    return e.setState({
                        showDropdown: !0
                    })
                }, this.showTooltip, l, i, Qa("dropdown-toolbar"), $i($i({}, d), r), function(t) {
                    return e.refs.dropdownEl = t
                }, c.length ? c.map(function(t, n) {
                    var r;
                    return gv(Ay || (Ay = Ui(["\n                  <", "\n                    group=", "\n                    hiddenDivider=", "\n                    ...", "\n                  />\n                "], ["\n                  <", "\n                    group=", "\n                    hiddenDivider=", "\n                    ...", "\n                  />\n                "])), Uy, t, n === c.length - 1 || (null === (r = c[n + 1]) || void 0 === r ? void 0 : r.hidden), e.props)
                }) : null)
            }, t
        }(Nv),
        Jy = Sy(Wy),
        Ky = function(e) {
            function t(t) {
                var n, r, o = e.call(this, t) || this;
                return o.toggleTab = function(e, t) {
                    var n = o.props.eventEmitter;
                    if (o.state.activeTab !== t) {
                        var r = "write" === t ? "changePreviewTabWrite" : "changePreviewTabPreview";
                        n.emit(r), o.setState({
                            activeTab: t
                        })
                    }
                }, o.setItemWidth = function(e, t) {
                    o.itemWidthMap[e] = t
                }, o.setPopupInfo = function(e) {
                    o.setState({
                        showPopup: !0,
                        popupInfo: e
                    })
                }, o.openPopup = function(e, t) {
                    void 0 === t && (t = {});
                    var n = o.refs.el.querySelector("." + Qa("toolbar-group") + " ." + e);
                    if (n) {
                        var r = sl(n, il(n, "." + Qa("toolbar"))),
                            i = r.offsetLeft,
                            s = r.offsetTop,
                            a = ky(e, {
                                el: n,
                                pos: {
                                    left: i,
                                    top: n.offsetHeight + s
                                },
                                initialValues: t
                            });
                        a && o.setPopupInfo(a)
                    }
                }, o.hidePopup = function() {
                    o.state.showPopup && o.setState({
                        showPopup: !1
                    })
                }, o.execCommand = function(e, t) {
                    o.props.eventEmitter.emit("command", e, t), o.hidePopup()
                }, o.tabs = [{
                    name: "write",
                    text: "Write"
                }, {
                    name: "preview",
                    text: "Preview"
                }], o.itemWidthMap = {}, o.initialItems = (n = t.toolbarItems || [], r = o.hiddenScrollSync(), n.reduce(function(e, t) {
                    e.push(t.map(function(e) {
                        return function(e) {
                            return e.hidden = "scrollSync" === e.name && r, e
                        }(wy(e))
                    }));
                    var n = e[(e.length || 1) - 1];
                    return n && xy(n), e
                }, [])), o.state = {
                    items: o.initialItems,
                    dropdownItems: [],
                    showPopup: !1,
                    popupInfo: {},
                    activeTab: "write"
                }, o.tooltipRef = {
                    current: null
                }, o.resizeObserver = new hy(function() {
                    return o.handleResize()
                }), o.addEvent(), o
            }
            return ji(t, e), t.prototype.insertToolbarItem = function(e, t) {
                var n = e.groupIndex,
                    r = e.itemIndex,
                    o = this.initialItems[n];
                t = wy(t), o ? o.splice(r, 0, t) : this.initialItems.push([t]), this.setState(this.classifyToolbarItems())
            }, t.prototype.removeToolbarItem = function(e) {
                var t = this;
                Xi(this.initialItems, function(n) {
                    var r = !1;
                    return Xi(n, function(o, i) {
                        return o.name !== e || (r = !0, n.splice(i, 1), t.setState(t.classifyToolbarItems()), !1)
                    }), !r
                })
            }, t.prototype.addEvent = function() {
                var e = this,
                    t = this.props.eventEmitter;
                this.handleResize = Dv(function() {
                    e.setState({
                        items: e.initialItems,
                        dropdownItems: []
                    }), e.setState(e.classifyToolbarItems())
                }, 200), t.listen("openPopup", this.openPopup)
            }, t.prototype.appendTooltipToRoot = function() {
                var e = '<div class="' + Qa("tooltip") + '" style="display:none">\n        <div class="arrow"></div>\n        <span class="text"></span>\n      </div>';
                this.tooltipRef.current = rl(e, this.refs.el)
            }, t.prototype.hiddenScrollSync = function() {
                return "wysiwyg" === this.props.editorType || "tab" === this.props.previewStyle
            }, t.prototype.movePrevItemToDropdownToolbar = function(e, t, n, r) {
                var o = function(e) {
                    var t = e.pop();
                    t && r.push(t)
                };
                if (e > 1) o(n);
                else {
                    var i = Ks(t);
                    i && o(i)
                }
            }, t.prototype.classifyToolbarItems = function() {
                var e = this,
                    t = 0,
                    n = this.refs.el.clientWidth,
                    r = this.refs.el.querySelector("." + Qa("toolbar-divider")),
                    o = r ? ol(r) : 0,
                    i = [],
                    s = [],
                    a = !1;
                return this.initialItems.forEach(function(r, l) {
                    var c = [],
                        u = [];
                    r.forEach(function(r, o) {
                        r.hidden || ((t += e.itemWidthMap[r.name]) > n - 50 ? (a || (e.movePrevItemToDropdownToolbar(o, i, c, u), a = !0), u.push(r)) : c.push(r))
                    }), c.length && (xy(c), i.push(c)), u.length && (xy(u), s.push(u)), l < e.state.items.length - 1 && (t += o)
                }), {
                    items: i,
                    dropdownItems: s
                }
            }, t.prototype.mounted = function() {
                "tab" === this.props.previewStyle && this.props.eventEmitter.emit("changePreviewTabWrite", !0), this.setState(this.classifyToolbarItems()), this.appendTooltipToRoot(), this.resizeObserver.observe(this.refs.el)
            }, t.prototype.updated = function(e) {
                var t, n, r = this.props,
                    o = r.editorType,
                    i = r.previewStyle,
                    s = r.eventEmitter,
                    a = i !== e.previewStyle,
                    l = o !== e.editorType;
                if (a || l) {
                    t = this.initialItems, n = this.hiddenScrollSync(), t.forEach(function(e) {
                        e.forEach(function(e) {
                            return e.hidden = "scrollSync" === e.name && n
                        }), xy(e)
                    });
                    var c = this.classifyToolbarItems();
                    (a || "tab" === i && "markdown" === o) && (s.emit("changePreviewTabWrite"), c.activeTab = "write"), this.setState(c)
                }
            }, t.prototype.beforeDestroy = function() {
                window.removeEventListener("resize", this.handleResize), this.resizeObserver.disconnect(), tl(this.tooltipRef.current)
            }, t.prototype.render = function() {
                var e = this,
                    t = this.props,
                    n = t.previewStyle,
                    r = t.eventEmitter,
                    o = t.editorType,
                    i = this.state,
                    s = i.popupInfo,
                    a = i.showPopup,
                    l = i.activeTab,
                    c = i.items,
                    u = i.dropdownItems,
                    d = {
                        eventEmitter: r,
                        tooltipRef: this.tooltipRef,
                        disabled: "markdown" === o && "tab" === n && "preview" === l,
                        execCommand: this.execCommand,
                        setPopupInfo: this.setPopupInfo
                    },
                    p = "tab" === n ? {
                        borderTopLeftRadius: 0
                    } : null;
                return gv(Ry || (Ry = Ui(['\n      <div class="', '">\n        <div\n          class="', '"\n          style="display: ', '"\n        >\n          <', " tabs=", " activeTab=", " onClick=", ' />\n        </div>\n        <div\n          class="', '"\n          ref=', "\n          style=", "\n        >\n          ", "\n          <", "\n            item=", "\n            items=", "\n            ...", "\n          />\n        </div>\n        <", "\n          info=", "\n          show=", "\n          eventEmitter=", "\n          hidePopup=", "\n          execCommand=", "\n        />\n      </div>\n    "], ['\n      <div class="', '">\n        <div\n          class="', '"\n          style="display: ', '"\n        >\n          <', " tabs=", " activeTab=", " onClick=", ' />\n        </div>\n        <div\n          class="', '"\n          ref=', "\n          style=", "\n        >\n          ", "\n          <", "\n            item=", "\n            items=", "\n            ...", "\n          />\n        </div>\n        <", "\n          info=", "\n          show=", "\n          eventEmitter=", "\n          hidePopup=", "\n          execCommand=", "\n        />\n      </div>\n    "])), Qa("toolbar"), Qa("md-tab-container"), "wysiwyg" === o || "vertical" === n ? "none" : "block", my, this.tabs, l, this.toggleTab, Qa("defaultUI-toolbar"), function(t) {
                    return e.refs.el = t
                }, p, c.map(function(t, n) {
                    var r;
                    return gv(Iy || (Iy = Ui(["\n              <", "\n                group=", "\n                hiddenDivider=", "\n                setItemWidth=", "\n                ...", "\n              />\n            "], ["\n              <", "\n                group=", "\n                hiddenDivider=", "\n                setItemWidth=", "\n                ...", "\n              />\n            "])), Uy, t, n === c.length - 1 || (null === (r = c[n + 1]) || void 0 === r ? void 0 : r.hidden), e.setItemWidth, d)
                }), Jy, wy("more"), u, d, My, s, a, r, this.hidePopup, this.execCommand)
            }, t
        }(Nv),
        Gy = function(e) {
            function t(t) {
                var n = e.call(this, t) || this;
                return n.handleClickDocument = function(e) {
                    il(e.target, "." + Qa("context-menu")) || n.setState({
                        pos: null
                    })
                }, n.state = {
                    pos: null,
                    menuGroups: []
                }, n.addEvent(), n
            }
            return ji(t, e), t.prototype.addEvent = function() {
                var e = this;
                this.props.eventEmitter.listen("contextmenu", function(t) {
                    var n = t.pos,
                        r = t.menuGroups;
                    e.setState({
                        pos: n,
                        menuGroups: r
                    })
                })
            }, t.prototype.mounted = function() {
                document.addEventListener("click", this.handleClickDocument)
            }, t.prototype.beforeDestroy = function() {
                document.removeEventListener("click", this.handleClickDocument)
            }, t.prototype.getMenuGroupElements = function() {
                var e = this,
                    t = this.state,
                    n = t.pos,
                    r = t.menuGroups;
                return n ? r.reduce(function(t, n) {
                    var r = [];
                    return n.forEach(function(t) {
                        var n = t.label,
                            o = t.className,
                            i = void 0 !== o && o,
                            s = t.disabled,
                            a = t.onClick;
                        r.push(gv(Py || (Py = Ui(["\n                <li\n                  onClick=", '\n                  class="menu-item', '"\n                  aria-role="menuitem"\n                >\n                  <span class="', '">', "</span>\n                </li>\n              "], ["\n                <li\n                  onClick=", '\n                  class="menu-item', '"\n                  aria-role="menuitem"\n                >\n                  <span class="', '">', "</span>\n                </li>\n              "])), function() {
                            s || (a(), e.setState({
                                pos: null
                            }))
                        }, s ? " disabled" : "", i, n))
                    }), t.push(gv(By || (By = Ui(['<ul class="menu-group">\n              ', "\n            </ul>"], ['<ul class="menu-group">\n              ', "\n            </ul>"])), r)), t
                }, []) : []
            }, t.prototype.render = function() {
                var e = $i({
                    display: this.state.pos ? "block" : "none"
                }, this.state.pos);
                return gv(Fy || (Fy = Ui(['<div class="', '" style=', ' aria-role="menu">\n      ', "\n    </div>"], ['<div class="', '" style=', ' aria-role="menu">\n      ', "\n    </div>"])), Qa("context-menu"), e, this.getMenuGroupElements())
            }, t
        }(Nv),
        Xy = function(e) {
            function t(t) {
                var n = e.call(this, t) || this;
                n.changeMode = function(e) {
                    e !== n.state.editorType && n.setState({
                        editorType: e
                    })
                }, n.changePreviewStyle = function(e) {
                    e !== n.state.previewStyle && n.setState({
                        previewStyle: e
                    })
                }, n.hide = function() {
                    n.setState({
                        hide: !0
                    })
                }, n.show = function() {
                    n.setState({
                        hide: !1
                    })
                };
                var r = t.editorType,
                    o = t.previewStyle;
                return n.state = {
                    editorType: r,
                    previewStyle: o,
                    hide: !1
                }, n.addEvent(), n
            }
            return ji(t, e), t.prototype.mounted = function() {
                var e = this.props.slots,
                    t = e.wwEditor,
                    n = e.mdEditor,
                    r = e.mdPreview;
                this.refs.wwContainer.appendChild(t), this.refs.mdContainer.insertAdjacentElement("afterbegin", n), this.refs.mdContainer.appendChild(r)
            }, t.prototype.insertToolbarItem = function(e, t) {
                this.toolbar.insertToolbarItem(e, t)
            }, t.prototype.removeToolbarItem = function(e) {
                this.toolbar.removeToolbarItem(e)
            }, t.prototype.render = function() {
                var e = this,
                    t = this.props,
                    n = t.eventEmitter,
                    r = t.hideModeSwitch,
                    o = t.toolbarItems,
                    i = t.theme,
                    s = this.state,
                    a = s.hide,
                    l = s.previewStyle,
                    c = s.editorType,
                    u = a ? " hidden" : "",
                    d = Qa("markdown" === c ? "md-mode" : "ww-mode"),
                    p = Qa("md") + "-" + l + "-style",
                    h = Qa(["light" !== i, i + " "]);
                return gv(zy || (zy = Ui(['\n      <div\n        class="', "", "", '"\n        ref=', "\n      >\n        <", "\n          ref=", "\n          eventEmitter=", "\n          previewStyle=", "\n          toolbarItems=", "\n          editorType=", '\n        />\n        <div\n          class="', " ", '"\n          ref=', '\n        >\n          <div class="', '">\n            <div\n              class="', " ", '"\n              ref=', '\n            >\n              <div class="', '"></div>\n            </div>\n            <div\n              class="', '"\n              ref=', "\n            />\n          </div>\n        </div>\n        ", "\n        <", " eventEmitter=", " />\n      </div>\n    "], ['\n      <div\n        class="', "", "", '"\n        ref=', "\n      >\n        <", "\n          ref=", "\n          eventEmitter=", "\n          previewStyle=", "\n          toolbarItems=", "\n          editorType=", '\n        />\n        <div\n          class="', " ", '"\n          ref=', '\n        >\n          <div class="', '">\n            <div\n              class="', " ", '"\n              ref=', '\n            >\n              <div class="', '"></div>\n            </div>\n            <div\n              class="', '"\n              ref=', "\n            />\n          </div>\n        </div>\n        ", "\n        <", " eventEmitter=", " />\n      </div>\n    "])), h, Qa("defaultUI"), u, function(t) {
                    return e.refs.el = t
                }, Ky, function(t) {
                    return e.toolbar = t
                }, n, l, o, c, Qa("main"), d, function(t) {
                    return e.refs.editorSection = t
                }, Qa("main-container"), Qa("md-container"), p, function(t) {
                    return e.refs.mdContainer = t
                }, Qa("md-splitter"), Qa("ww-container"), function(t) {
                    return e.refs.wwContainer = t
                }, !r && gv(Hy || (Hy = Ui(["<", " eventEmitter=", " editorType=", " />"], ["<", " eventEmitter=", " editorType=", " />"])), Ov, n, c), Gy, n)
            }, t.prototype.addEvent = function() {
                var e = this.props.eventEmitter;
                e.listen("hide", this.hide), e.listen("show", this.show), e.listen("changeMode", this.changeMode), e.listen("changePreviewStyle", this.changePreviewStyle)
            }, t
        }(Nv),
        Zy = function(e) {
            function t(t) {
                var n, r, o, i, s, a = e.call(this, t) || this,
                    l = (o = a.options.el, i = gv(qy || (qy = Ui(["\n        <", "\n          ref=", "\n          eventEmitter=", "\n          slots=", "\n          hideModeSwitch=", "\n          toolbarItems=", "\n          previewStyle=", "\n          editorType=", "\n          theme=", "\n        />\n      "], ["\n        <", "\n          ref=", "\n          eventEmitter=", "\n          slots=", "\n          hideModeSwitch=", "\n          toolbarItems=", "\n          previewStyle=", "\n          editorType=", "\n          theme=", "\n        />\n      "])), Xy, function(e) {
                        return r = e
                    }, a.eventEmitter, a.getEditorElements(), a.options.hideModeSwitch, a.options.toolbarItems, a.options.previewStyle, a.options.initialEditType, a.options.theme), (s = new fv(o.tagName.toLowerCase(), {}, [i])).node = o, fv.removalNodes = [], Mv(s), kv(s), function() {
                        return function(e) {
                            e.effect = "D", fv.removalNodes = [e], kv(), fv.removalNodes = []
                        }(s.firstChild)
                    });
                return a.setMinHeight(a.options.minHeight), a.setHeight(a.options.height), a.defaultUI = {
                    insertToolbarItem: r.insertToolbarItem.bind(r),
                    removeToolbarItem: r.removeToolbarItem.bind(r),
                    destroy: l
                }, null === (n = a.pluginInfo.toolbarItems) || void 0 === n || n.forEach(function(e) {
                    var t = e.groupIndex,
                        n = e.itemIndex,
                        r = e.item;
                    a.defaultUI.insertToolbarItem({
                        groupIndex: t,
                        itemIndex: n
                    }, r)
                }), a.eventEmitter.emit("loadUI", a), a
            }
            return ji(t, e), t.factory = function(e) {
                return e.viewer ? new nv(e) : new t(e)
            }, t.prototype.insertToolbarItem = function(e, t) {
                this.defaultUI.insertToolbarItem(e, t)
            }, t.prototype.removeToolbarItem = function(e) {
                this.defaultUI.removeToolbarItem(e)
            }, t.prototype.destroy = function() {
                e.prototype.destroy.call(this), this.defaultUI.destroy()
            }, t
        }(pv);
    pv.setLanguage(["en", "en-US"], {
        Markdown: "Markdown",
        WYSIWYG: "WYSIWYG",
        Write: "Write",
        Preview: "Preview",
        Headings: "Headings",
        Paragraph: "Paragraph",
        Bold: "Bold",
        Italic: "Italic",
        Strike: "Strike",
        Code: "Inline code",
        Line: "Line",
        Blockquote: "Blockquote",
        "Unordered list": "Unordered list",
        "Ordered list": "Ordered list",
        Task: "Task",
        Indent: "Indent",
        Outdent: "Outdent",
        "Insert link": "Insert link",
        "Insert CodeBlock": "Insert codeBlock",
        "Insert table": "Insert table",
        "Insert image": "Insert image",
        Heading: "Heading",
        "Image URL": "Image URL",
        "Select image file": "Select image file",
        "Choose a file": "Choose a file",
        "No file": "No file",
        Description: "Description",
        OK: "OK",
        More: "More",
        Cancel: "Cancel",
        File: "File",
        URL: "URL",
        "Link text": "Link text",
        "Add row to up": "Add row to up",
        "Add row to down": "Add row to down",
        "Add column to left": "Add column to left",
        "Add column to right": "Add column to right",
        "Remove row": "Remove row",
        "Remove column": "Remove column",
        "Align column to left": "Align column to left",
        "Align column to center": "Align column to center",
        "Align column to right": "Align column to right",
        "Remove table": "Remove table",
        "Would you like to paste as table?": "Would you like to paste as table?",
        "Text color": "Text color",
        "Auto scroll enabled": "Auto scroll enabled",
        "Auto scroll disabled": "Auto scroll disabled",
        "Choose language": "Choose language"
    }), window.tui = window.tui || {}, window.tui.usageStatistics = !1, window.toastui = {
        Editor: Zy
    }, self.toastui = t
})();
/**
 * Mini Calendar Component
 *
 * @copyright Copyright (c) 2025, Phillips Data, Inc.
 * @license http://www.blesta.com/license/ The Blesta License Agreement
 * @link http://www.blesta.com/ Blesta
 */
class MiniCalendar {
    constructor(elementSelector, options = {}) {
        this.element = document.querySelector(elementSelector);
        if (!this.element) {
            console.error('Mini calendar element not found:', elementSelector);
            return;
        }

        this.options = {
            calendarPageUrl: options.calendarPageUrl || 'calendar.html',
            ...options
        };

        this.currentDate = new Date();
        this.eventCounts = {};

        this.init();
    }

    /**
     * Initialize the mini calendar
     */
    async init() {
        await this.fetchEventCounts();
        this.render();
        this.attachEventListeners();
    }

    /**
     * Fetch event counts from server for the current month
     */
    async fetchEventCounts() {
        const year = this.currentDate.getFullYear();
        const month = this.currentDate.getMonth();

        const firstDay = new Date(year, month, 1);
        const lastDay = new Date(year, month + 1, 0);

        const startDate = this.formatDate(firstDay);
        const endDate = this.formatDate(lastDay);

        try {
            const response = await fetch(`${base_uri}main/geteventcounts/?start_date=${startDate}&end_date=${endDate}`);
            const data = await response.json();
            this.eventCounts = data || {};
        } catch (e) {
            console.error('Error fetching event counts:', e);
            this.eventCounts = {};
        }
    }

    /**
     * Render the calendar
     */
    render() {
        const year = this.currentDate.getFullYear();
        const month = this.currentDate.getMonth();
        const today = new Date();

        // Get month info
        const firstDay = new Date(year, month, 1);
        const lastDay = new Date(year, month + 1, 0);
        const daysInMonth = lastDay.getDate();
        const startingDayOfWeek = firstDay.getDay(); // 0 = Sunday

        // Build header
        const monthNames = ['January', 'February', 'March', 'April', 'May', 'June',
            'July', 'August', 'September', 'October', 'November', 'December'
        ];

        let html = `
            <div class="mini-calendar-header">
                <button class="mini-calendar-nav" data-action="prev">
                    <i class="bi bi-chevron-left"></i>
                </button>
                <div class="mini-calendar-month">${monthNames[month]} ${year}</div>
                <button class="mini-calendar-nav" data-action="next">
                    <i class="bi bi-chevron-right"></i>
                </button>
            </div>
            <div class="mini-calendar-grid">
                <!-- Day headers -->
                <div class="mini-calendar-day-header">Su</div>
                <div class="mini-calendar-day-header">Mo</div>
                <div class="mini-calendar-day-header">Tu</div>
                <div class="mini-calendar-day-header">We</div>
                <div class="mini-calendar-day-header">Th</div>
                <div class="mini-calendar-day-header">Fr</div>
                <div class="mini-calendar-day-header">Sa</div>
        `;

        // Add empty cells for days before month starts
        for (let i = 0; i < startingDayOfWeek; i++) {
            html += '<div class="mini-calendar-day empty"></div>';
        }

        // Add day cells
        for (let day = 1; day <= daysInMonth; day++) {
            const currentDateStr = this.formatDate(new Date(year, month, day));
            const eventCount = this.getEventCountForDate(currentDateStr);
            const isToday = today.getDate() === day &&
                today.getMonth() === month &&
                today.getFullYear() === year;

            const classes = ['mini-calendar-day'];
            if (isToday) classes.push('today');
            if (eventCount > 0) classes.push('has-events');

            html += `
                <div class="${classes.join(' ')}" data-date="${currentDateStr}">
                    <span class="mini-calendar-day-number">${day}</span>
                    ${eventCount > 0 ? `<span class="mini-calendar-event-badge">${eventCount > 9 ? '9+' : eventCount}</span>` : ''}
                </div>
            `;
        }

        html += '</div>'; // Close grid

        this.element.innerHTML = html;
    }

    /**
     * Attach event listeners (only called once in init)
     */
    attachEventListeners() {
        // Use event delegation - listen on the parent element
        this.element.addEventListener('click', (e) => {
            const navBtn = e.target.closest('[data-action]');
            if (navBtn) {
                const action = navBtn.dataset.action;
                if (action === 'prev') {
                    this.previousMonth();
                } else if (action === 'next') {
                    this.nextMonth();
                }
                return;
            }

            // Day clicks
            const dayCell = e.target.closest('.mini-calendar-day:not(.empty)');
            if (dayCell) {
                const date = dayCell.dataset.date;
                if (date) {
                    this.handleDayClick(date);
                }
            }
        });
    }

    /**
     * Handle day click
     */
    handleDayClick(date) {
        window.location.href = base_uri + `main/calendar/day/${date}`;
    }

    /**
     * Go to previous month
     */
    async previousMonth() {
        // Create new date to avoid mutation issues
        this.currentDate = new Date(this.currentDate.getFullYear(), this.currentDate.getMonth() - 1, 1);
        await this.fetchEventCounts();
        this.render();
    }

    /**
     * Go to next month
     */
    async nextMonth() {
        // Create new date to avoid mutation issues
        this.currentDate = new Date(this.currentDate.getFullYear(), this.currentDate.getMonth() + 1, 1);
        await this.fetchEventCounts();
        this.render();
    }

    /**
     * Get event count for a specific date
     */
    getEventCountForDate(dateStr) {
        return this.eventCounts[dateStr] || 0;
    }

    /**
     * Format date as YYYY-MM-DD
     */
    formatDate(date) {
        const year = date.getFullYear();
        const month = String(date.getMonth() + 1).padStart(2, '0');
        const day = String(date.getDate()).padStart(2, '0');
        return `${year}-${month}-${day}`;
    }

    /**
     * Refresh calendar (useful after external event changes)
     */
    async refresh() {
        await this.fetchEventCounts();
        this.render();
    }
}

// Auto-initialize mini calendars on page load
document.addEventListener('DOMContentLoaded', () => {
    const miniCalendarElement = document.querySelector('.mini-calendar');
    if (miniCalendarElement) {
        window.miniCalendar = new MiniCalendar('.mini-calendar');
    }
});
(function() {
    'use strict';

    document.addEventListener('DOMContentLoaded', () => {
        /**
         * Initialize bookmark button functionality (works on all pages)
         */
        function initBookmarkButton() {
            var bookmarkBtn = document.getElementById('bookmark-btn');
            if (!bookmarkBtn) return;

            bookmarkBtn.addEventListener('click', function(e) {
                e.preventDefault();

                var isBookmarked = this.classList.contains('bookmarked');
                var action = isBookmarked ? 'remove' : 'add';

                var params = {
                    action: action,
                    title: document.title.split("|")[0],
                    uri: window.location.pathname + window.location.search
                };

                // Create form data
                var formData = new FormData();
                for (var key in params) {
                    formData.append(key, params[key]);
                }

                // Send AJAX request
                var xhr = new XMLHttpRequest();
                xhr.open('POST', this.getAttribute('href'), true);
                xhr.onreadystatechange = function() {
                    if (xhr.readyState === 4) {
                        if (xhr.status === 200) {
                            try {
                                var data = JSON.parse(xhr.responseText);
                                var icon = bookmarkBtn.querySelector('i');
                                if (data.added) {
                                    bookmarkBtn.classList.add('bookmarked');
                                    if (icon) {
                                        icon.className = 'bi bi-star-fill';
                                    }
                                } else {
                                    bookmarkBtn.classList.remove('bookmarked');
                                    if (icon) {
                                        icon.className = 'bi bi-star';
                                    }
                                }
                            } catch (e) {
                                console.error('Error parsing response:', e);
                            }
                        }
                    }
                };
                xhr.send(formData);
            });
        }

        // Initialize bookmark button on all pages
        initBookmarkButton();

        /**
         * Check if we're on a page with sortable quick links (dashboard only)
         */
        const sortableQuickLinks = document.getElementById('sortable-quick-links');
        if (!sortableQuickLinks) {
            return;
        }

        /**
         * Initialize SortableJS on the quick links container
         */
        const sortable = new Sortable(sortableQuickLinks, {
            animation: 200,
            handle: '.action-drag-handle',
            ghostClass: 'sortable-ghost',
            chosenClass: 'sortable-chosen',
            dragClass: 'sortable-drag',
            easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
            draggable: '.side-content-link',
            onEnd: (evt) => {
                const order = getQuickLinksOrder();
                try {
                    localStorage.setItem('blesta-dashboard-quicklinks-order', JSON.stringify(order));
                } catch (e) {
                    // Nothing to do
                }
            }
        });

        /**
         * Get the current quick links order as an array
         * @returns {Array} Array of bookmark IDs in current order
         */
        function getQuickLinksOrder() {
            const order = [];

            // Get all quick link elements
            const allLinks = sortableQuickLinks.querySelectorAll('.side-content-link[data-bookmark-id]');

            allLinks.forEach((link) => {
                const bookmarkId = link.getAttribute('data-bookmark-id');
                if (bookmarkId) {
                    order.push(bookmarkId);
                }
            });

            return order;
        }

        /**
         * Check if there are no quick links and show/hide the alert
         */
        function checkEmptyQuickLinks() {
            const links = sortableQuickLinks.querySelectorAll('.side-content-link');
            const noQuicklinksAlert = document.getElementById('no-quicklinks-alert');

            if (links.length === 0) {
                noQuicklinksAlert.style.display = 'block';
            } else {
                noQuicklinksAlert.style.display = 'none';
            }
        }

        /**
         * Load quick links order from localStorage and reorder DOM elements
         */
        function loadQuickLinksOrder() {
            try {
                const savedOrder = localStorage.getItem('blesta-dashboard-quicklinks-order');
                if (!savedOrder) {
                    return; // No saved order
                }

                const order = JSON.parse(savedOrder);
                if (!Array.isArray(order) || order.length === 0) {
                    return;
                }

                // Get all quick link elements
                const allLinks = sortableQuickLinks.querySelectorAll('.side-content-link[data-bookmark-id]');
                const linkMap = new Map();

                allLinks.forEach(link => {
                    const bookmarkId = link.getAttribute('data-bookmark-id');
                    if (bookmarkId) {
                        linkMap.set(bookmarkId, link);
                    }
                });

                // Reorder elements based on saved order
                // Insert from the end to preserve correct sequence
                let insertBeforeElement = null;

                for (let i = order.length - 1; i >= 0; i--) {
                    const bookmarkId = order[i];
                    const link = linkMap.get(bookmarkId);

                    if (link) {
                        // Remove from current position
                        link.remove();

                        if (insertBeforeElement) {
                            // Insert before the previous element
                            sortableQuickLinks.insertBefore(link, insertBeforeElement);
                        } else {
                            // Append to the end (first iteration)
                            sortableQuickLinks.appendChild(link);
                        }

                        insertBeforeElement = link;
                    }
                }
            } catch (e) {
                // Nothing to do
            }
        }

        /**
         * Attach event listeners to quick link actions
         */
        function attachQuickLinkEventListeners() {
            // Edit buttons
            const editButtons = sortableQuickLinks.querySelectorAll('.btn-bookmark-edit');
            editButtons.forEach(btn => {
                btn.addEventListener('click', handleEditClick);
            });

            // Delete buttons
            const deleteButtons = sortableQuickLinks.querySelectorAll('.btn-bookmark-delete');
            deleteButtons.forEach(btn => {
                btn.addEventListener('click', handleDeleteClick);
            });

            // Double-click on title to edit
            const titles = sortableQuickLinks.querySelectorAll('.bookmark-title');
            titles.forEach(title => {
                title.addEventListener('dblclick', function(e) {
                    e.preventDefault();
                    const link = this.closest('.side-content-link');
                    const editBtn = link.querySelector('.btn-bookmark-edit');
                    if (editBtn) {
                        editBtn.click();
                    }
                });
            });
        }

        /**
         * Handle edit button click
         */
        function handleEditClick(e) {
            e.preventDefault();
            e.stopPropagation();

            const link = e.target.closest('.side-content-link');
            const bookmarkId = link.dataset.bookmarkId;
            const titleSpan = link.querySelector('.bookmark-title');
            const currentTitle = titleSpan.textContent;

            // Create input field
            const input = document.createElement('input');
            input.type = 'text';
            input.className = 'bookmark-edit-input';
            input.value = currentTitle;

            // Create save/cancel buttons
            const saveBtn = document.createElement('button');
            saveBtn.className = 'btn-bookmark-save';
            saveBtn.innerHTML = '<i class="bi bi-check"></i>';

            const cancelBtn = document.createElement('button');
            cancelBtn.className = 'btn-bookmark-cancel';
            cancelBtn.innerHTML = '<i class="bi bi-x"></i>';

            // Replace title with input
            titleSpan.style.display = 'none';
            titleSpan.insertAdjacentElement('afterend', input);
            titleSpan.insertAdjacentElement('afterend', cancelBtn);
            titleSpan.insertAdjacentElement('afterend', saveBtn);

            // Hide action buttons and drag handle
            const actions = link.querySelector('.bookmark-actions');
            const dragHandle = link.querySelector('.action-drag-handle');
            actions.style.display = 'none';
            dragHandle.style.display = 'none';

            // Prevent link navigation while in edit mode by removing href
            const originalHref = link.getAttribute('href');
            link.removeAttribute('href');
            link.style.cursor = 'default';

            input.focus();
            input.select();

            // Save function
            const save = () => {
                const newTitle = input.value.trim();
                if (newTitle && newTitle !== currentTitle) {
                    updateBookmarkTitle(bookmarkId, newTitle);
                    titleSpan.textContent = newTitle;
                }
                cleanup();
            };

            // Cancel function
            const cleanup = () => {
                input.remove();
                saveBtn.remove();
                cancelBtn.remove();
                titleSpan.style.display = '';
                actions.style.display = '';
                dragHandle.style.display = '';
                link.setAttribute('href', originalHref);
                link.style.cursor = '';
            };

            // Event listeners
            saveBtn.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                save();
            });

            cancelBtn.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                cleanup();
            });

            input.addEventListener('keydown', (e) => {
                if (e.key === 'Enter') {
                    e.preventDefault();
                    save();
                } else if (e.key === 'Escape') {
                    e.preventDefault();
                    cleanup();
                }
            });

            input.addEventListener('click', (e) => {
                e.stopPropagation();
            });

            input.addEventListener('blur', () => {
                // Delay to allow button clicks to register
                setTimeout(cleanup, 200);
            });
        }

        /**
         * Handle delete button click
         */
        function handleDeleteClick(e) {
            e.preventDefault();
            e.stopPropagation();

            const link = e.target.closest('.side-content-link');
            const bookmarkId = link.dataset.bookmarkId;
            const title = link.querySelector('.bookmark-title').textContent;

            // Set modal message with the quicklink title
            const messageElement = document.getElementById('delete-quicklink-message');
            messageElement.textContent = link.dataset.deleteMessage;

            // Get the modal and confirm button
            const modal = new bootstrap.Modal(document.getElementById('delete-quicklink-modal'));
            const confirmBtn = document.getElementById('confirm-delete-quicklink');

            // Remove any existing event listeners by cloning the button
            const newConfirmBtn = confirmBtn.cloneNode(true);
            confirmBtn.parentNode.replaceChild(newConfirmBtn, confirmBtn);

            // Add click handler for confirm button
            newConfirmBtn.addEventListener('click', () => {
                deleteBookmark(bookmarkId);
                link.remove();
                loadQuickLinksOrder();
                checkEmptyQuickLinks();
                modal.hide();
            });

            // Show the modal
            modal.show();
        }

        /**
         * Delete a bookmark via AJAX
         */
        function deleteBookmark(uri) {
            fetch(base_uri + 'main/updatequicklink/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    'uri': uri,
                    'action': 'remove'
                })
            });
        }

        /**
         * Update a bookmark title via AJAX
         */
        function updateBookmarkTitle(uri, title) {
            fetch(base_uri + 'main/updatequicklink/', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    'uri': uri,
                    'title': title,
                    'action': 'add'
                })
            });
        }

        // Attach event listeners
        attachQuickLinkEventListeners();

        // Load saved order and reorder elements on page load
        loadQuickLinksOrder();

        // Check if there are no quick links on load
        checkEmptyQuickLinks();
    });
})();
(function() {
    document.addEventListener('DOMContentLoaded', function() {
        var sortableActions = document.getElementById('sortableActions');
        if (!sortableActions) return;

        var STORAGE_KEY = 'blesta-client-sidebar-actions';
        var VISIBLE_COUNT = 5;
        var expanded = false;

        /**
         * Get saved state from localStorage
         * @returns {Object} { order: [], expanded: false }
         */
        function getSavedState() {
            try {
                var saved = localStorage.getItem(STORAGE_KEY);
                if (saved) {
                    return JSON.parse(saved);
                }
            } catch (e) {
                // Storage not available
            }
            return {
                order: [],
                expanded: false
            };
        }

        /**
         * Save state to localStorage
         * @param {Array} order - Array of action IDs
         * @param {boolean} isExpanded - Whether actions are expanded
         */
        function saveState(order, isExpanded) {
            try {
                localStorage.setItem(STORAGE_KEY, JSON.stringify({
                    order: order,
                    expanded: isExpanded
                }));
            } catch (e) {
                // Storage not available
            }
        }

        /**
         * Get current order of action IDs
         * @returns {Array} Array of action IDs
         */
        function getCurrentOrder() {
            var order = [];
            var links = sortableActions.querySelectorAll('.side-content-link[data-action-id]');
            links.forEach(function(link) {
                var actionId = link.getAttribute('data-action-id');
                if (actionId) {
                    order.push(actionId);
                }
            });
            return order;
        }

        /**
         * Update visibility of actions based on position and expanded state
         */
        function updateVisibility() {
            var links = sortableActions.querySelectorAll('.side-content-link[data-action-id]');
            var toggleIcon = document.getElementById('toggleActionsIcon');
            var toggleText = document.getElementById('toggleActionsText');
            var toggleButton = document.getElementById('toggleActions');

            links.forEach(function(link, index) {
                if (index < VISIBLE_COUNT) {
                    // First 9 always visible
                    link.classList.remove('hidden-action');
                } else {
                    // Rest are hidden unless expanded
                    if (expanded) {
                        link.classList.remove('hidden-action');
                    } else {
                        link.classList.add('hidden-action');
                    }
                }
            });

            // Update toggle icon and text
            if (toggleIcon) {
                if (expanded) {
                    toggleIcon.classList.remove('bi-chevron-down');
                    toggleIcon.classList.add('bi-chevron-up');
                } else {
                    toggleIcon.classList.remove('bi-chevron-up');
                    toggleIcon.classList.add('bi-chevron-down');
                }
            }

            if (toggleText && toggleButton) {
                var textMore = toggleButton.getAttribute('data-text-more');
                var textLess = toggleButton.getAttribute('data-text-less');
                toggleText.textContent = expanded ? textLess : textMore;
            }
        }

        /**
         * Restore order from saved state
         */
        function restoreOrder() {
            var state = getSavedState();
            expanded = state.expanded;

            if (!state.order || state.order.length === 0) {
                updateVisibility();
                return;
            }

            // Build map of all action links
            var linkMap = new Map();
            var links = sortableActions.querySelectorAll('.side-content-link[data-action-id]');
            links.forEach(function(link) {
                var actionId = link.getAttribute('data-action-id');
                if (actionId) {
                    linkMap.set(actionId, link);
                }
            });

            // Find the toggle button to insert before
            var toggleButton = sortableActions.querySelector('.side-content-link-toggle');

            // Reorder elements
            state.order.forEach(function(actionId) {
                var link = linkMap.get(actionId);
                if (link) {
                    link.remove();
                    if (toggleButton) {
                        sortableActions.insertBefore(link, toggleButton);
                    } else {
                        sortableActions.appendChild(link);
                    }
                }
            });

            updateVisibility();
        }

        /**
         * Initialize SortableJS
         */
        new Sortable(sortableActions, {
            animation: 200,
            handle: '.action-drag-handle',
            ghostClass: 'sortable-ghost',
            chosenClass: 'sortable-chosen',
            dragClass: 'sortable-drag',
            easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
            draggable: '.side-content-link',
            filter: '.side-content-link-toggle',
            onEnd: function() {
                updateVisibility();
                saveState(getCurrentOrder(), expanded);
            }
        });

        /**
         * Toggle button click handler with slide animation
         */
        var toggleButton = document.getElementById('toggleActions');
        if (toggleButton) {
            toggleButton.addEventListener('click', function(e) {
                e.preventDefault();

                var willExpand = !expanded;

                // Capture current height
                var startHeight = sortableActions.scrollHeight;
                sortableActions.style.overflow = 'hidden';
                sortableActions.style.height = startHeight + 'px';

                if (willExpand) {
                    // Expanding: update visibility first, then animate
                    expanded = true;
                    updateVisibility();

                    // Measure target height
                    sortableActions.style.height = 'auto';
                    var endHeight = sortableActions.scrollHeight;
                    sortableActions.style.height = startHeight + 'px';

                    // Animate
                    sortableActions.style.transition = 'height 400ms ease';
                    requestAnimationFrame(function() {
                        sortableActions.style.height = endHeight + 'px';
                    });

                    setTimeout(function() {
                        sortableActions.style.height = '';
                        sortableActions.style.overflow = '';
                        sortableActions.style.transition = '';
                        saveState(getCurrentOrder(), expanded);
                    }, 400);
                } else {
                    // Collapsing: measure target height first, animate, then hide items
                    // Temporarily apply hidden classes to measure collapsed height
                    var links = sortableActions.querySelectorAll('.side-content-link[data-action-id]');
                    links.forEach(function(link, index) {
                        if (index >= VISIBLE_COUNT) {
                            link.classList.add('hidden-action');
                        }
                    });

                    // Measure collapsed height
                    sortableActions.style.height = 'auto';
                    var endHeight = sortableActions.scrollHeight;

                    // Restore visible state for animation
                    links.forEach(function(link, index) {
                        if (index >= VISIBLE_COUNT) {
                            link.classList.remove('hidden-action');
                        }
                    });
                    sortableActions.style.height = startHeight + 'px';

                    // Animate
                    sortableActions.style.transition = 'height 400ms ease';
                    requestAnimationFrame(function() {
                        sortableActions.style.height = endHeight + 'px';
                    });

                    setTimeout(function() {
                        // Now actually update the state and hide items
                        expanded = false;
                        updateVisibility();
                        sortableActions.style.height = '';
                        sortableActions.style.overflow = '';
                        sortableActions.style.transition = '';
                        saveState(getCurrentOrder(), expanded);
                    }, 400);
                }
            });
        }

        // Restore saved order on init
        restoreOrder();
    });
})();
/**
 * Notifications Component
 *
 * @copyright Copyright (c) 2025, Phillips Data, Inc.
 * @license http://www.blesta.com/license/ The Blesta License Agreement
 * @link http://www.blesta.com/ Blesta
 */
(function() {
    'use strict';

    /**
     * Initialize notifications polling functionality
     */
    function initNotificationsPolling() {
        var notificationsDropdown = document.getElementById('notifications-dropdown');
        if (!notificationsDropdown) return;

        // Function to fetch notifications
        function fetchNotifications() {
            // Check if notifications dropdown is open (has .show class)
            var notificationDropdown = notificationsDropdown.querySelector('.notification-dropdown');
            if (notificationDropdown && notificationDropdown.classList.contains('show')) {
                // Don't update if dropdown is open
                return;
            }

            var xhr = new XMLHttpRequest();
            xhr.open('GET', public_uri + 'api/notifications', true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        try {
                            var response = JSON.parse(xhr.responseText);
                            if (response.response && response.response.html) {
                                // Create a temporary div to parse the HTML
                                var tempDiv = document.createElement('div');
                                tempDiv.innerHTML = response.response.html;
                                var newDropdown = tempDiv.firstElementChild;

                                // Replace the notifications dropdown with the new one
                                notificationsDropdown.parentNode.replaceChild(newDropdown, notificationsDropdown);

                                // Update our reference to the new element
                                notificationsDropdown = newDropdown;

                                // Re-attach any event listeners if needed
                                attachNotificationEvents();
                            }
                        } catch (e) {
                            console.error('Error parsing notifications response:', e);
                        }
                    }
                }
            };
            xhr.send();
        }

        // Function to attach event listeners to notification elements
        function attachNotificationEvents() {
            // Re-attach any event listeners that might have been lost
            var notificationItems = document.querySelectorAll('.notification-item');
            var dismissButtons = document.querySelectorAll('.notification-dismiss');
            var markAllReadButton = document.querySelector('.notification-mark-all-read');
            if (!notificationItems || !dismissButtons || !markAllReadButton) return;

            // Add click handlers to notification items
            notificationItems.forEach(function(item) {
                item.addEventListener('click', function(e) {
                    e.stopPropagation();
                    var notificationId = this.dataset.notificationId || this.closest('.notification-item').dataset.notificationId;
                    if (notificationId) {
                        markNotificationRead(notificationId);
                    }
                });
            });

            // Add click handlers to dismiss buttons
            dismissButtons.forEach(function(button) {
                button.addEventListener('click', function(e) {
                    e.stopPropagation();
                    var notificationId = this.dataset.notificationId || this.closest('.notification-item').dataset.notificationId;
                    if (notificationId) {
                        this.closest('.notification-item').remove();
                        dismissNotification(notificationId);
                    }
                });
            });

            // Add click handler to mark all as read button
            markAllReadButton.addEventListener('click', function(e) {
                e.stopPropagation();
                markAllNotificationsRead();
            });
        }

        // Function to mark notification as read
        function markNotificationRead(notificationId) {
            var xhr = new XMLHttpRequest();
            xhr.open('POST', public_uri + 'api/notifications/' + notificationId + '/read', true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        // Open notification
                        openNotification(notificationId);

                        // Update only if it is unread
                        var item = document.querySelector('.notification-item[data-notification-id="' + notificationId + '"]');
                        if (item && !item.classList.contains('unread')) {
                            return;
                        }

                        // Update notification badge
                        updateNotificationBadge();

                        // Remove .unread class from notification
                        if (item) {
                            item.classList.remove('unread');
                        }
                    }
                }
            };
            xhr.send();
        }

        // Function to dismiss/delete notification
        function dismissNotification(notificationId) {
            var xhr = new XMLHttpRequest();
            xhr.open('DELETE', public_uri + 'api/notifications/' + notificationId + '/delete', true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        // Update notification badge
                        updateNotificationBadge();
                    }
                }
            };
            xhr.send();
        }

        // Function to mark all notifications as read
        function markAllNotificationsRead() {
            var xhr = new XMLHttpRequest();
            xhr.open('POST', public_uri + 'api/notifications/read-all', true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        // Remove unread class from all notification items
                        var notificationItems = document.querySelectorAll('.notification-item.unread');
                        notificationItems.forEach(function(item) {
                            item.classList.remove('unread');
                        });

                        // Update notification badge
                        updateNotificationBadge();

                        // Hide the mark all read button since there are no unread notifications
                        var markAllReadButton = document.querySelector('.notification-mark-all-read');
                        if (markAllReadButton) {
                            markAllReadButton.style.display = 'none';
                        }
                    }
                }
            };
            xhr.send();
        }

        // Function to open/fetch a specific notification
        function openNotification(notificationId) {
            var xhr = new XMLHttpRequest();
            xhr.open('GET', public_uri + 'api/notifications', true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        try {
                            var response = JSON.parse(xhr.responseText);

                            if (response.response && response.response.notifications) {
                                // Find notification with matching id
                                var notification = response.response.notifications.find(function(notif) {
                                    return notif.id == notificationId;
                                });

                                if (notification) {
                                    // Update modal label if it exists
                                    var modalLabel = document.getElementById('notification-modal-label');
                                    if (modalLabel && notification.title) {
                                        modalLabel.textContent = notification.title;
                                    }

                                    // Update modal body if it exists
                                    var modalBody = document.getElementById('notification-modal-body');
                                    if (modalBody && notification.message) {
                                        // Remove HTML tags, convert newlines to <br>, and linkify URLs
                                        var tempDiv = document.createElement('div');
                                        tempDiv.textContent = notification.message;
                                        var strippedMessage = tempDiv.textContent;
                                        var message = strippedMessage.replace(/\n/g, '<br>');

                                        // Linkify URLs (http and https only)
                                        message = message.replace(
                                            /(\bhttps?:\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim,
                                            '<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>'
                                        );

                                        modalBody.innerHTML = message;
                                    }

                                    // Set URL in footer, if available
                                    var modalFooter = document.getElementById('notification-modal-footer');
                                    if (modalFooter) {
                                        modalFooter.style.display = 'none';
                                    }

                                    // Prefer the company-aware link (a host-relative path that
                                    // stays on the current hostname, routing cross-company items
                                    // through the company switcher); fall back to the raw url.
                                    // Only honor absolute http(s) URLs or same-origin root-relative
                                    // paths (single leading slash, not protocol-relative //host or
                                    // /\host) so a stored javascript:/data: value can't become a
                                    // clickable XSS sink on the modal button.
                                    var notificationLink = notification.link || notification.url;
                                    var trimmedLink = notificationLink ? String(notificationLink).trim() : '';
                                    if (trimmedLink && (/^https?:\/\//i.test(trimmedLink) || /^\/(?![\/\\])/.test(trimmedLink))) {
                                        var modalLink = document.getElementById('notification-modal-link');
                                        if (modalFooter && modalLink) {
                                            modalFooter.style.display = '';
                                            modalLink.href = trimmedLink;
                                        }
                                    }

                                    // Show the modal
                                    var modal = new bootstrap.Modal(document.getElementById('notification-modal'));
                                    if (modal) {
                                        modal.show();
                                    }
                                }
                            }
                        } catch (e) {
                            console.error('Error parsing notification response:', e);
                        }
                    }
                }
            };
            xhr.send();
        }

        // Function to update notification badge count
        function updateNotificationBadge() {
            var badge = notificationsDropdown.querySelector('.notification-badge');
            if (!badge) return;

            var xhr = new XMLHttpRequest();
            xhr.open('GET', public_uri + 'api/notifications', true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        try {
                            var response = JSON.parse(xhr.responseText);
                            if (response.response && typeof response.response.unread_count !== 'undefined') {
                                var unread_count = parseInt(response.response.unread_count) || 0;

                                if (unread_count > 0) {
                                    badge.textContent = unread_count;
                                    badge.style.display = 'inline-block';
                                } else {
                                    badge.style.display = 'none';
                                }
                            }
                        } catch (e) {
                            console.error('Error parsing notifications response:', e);
                        }
                    }
                }
            };
            xhr.send();
        }

        // Attach events on initial load
        attachNotificationEvents();

        // Initial fetch
        fetchNotifications();

        // Set up polling every 60 seconds
        setInterval(fetchNotifications, 30 * 1000);
    }

    // Initialize notifications polling when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initNotificationsPolling);
    } else {
        initNotificationsPolling();
    }
})();
/**
 * Dashboard Widgets Component
 *
 * @copyright Copyright (c) 2026, Phillips Data, Inc.
 * @license http://www.blesta.com/license/ The Blesta License Agreement
 * @link http://www.blesta.com/ Blesta
 */
class DashboardWidgets {
    constructor(container_selector, options) {
        this.container = document.querySelector(container_selector);
        if (!this.container) {
            return;
        }

        var defaults = {
            fetch_uri: null,
            update_uri: null,
            toggle_uri: null,
            resize_uri: null
        };

        this.options = Object.assign({}, defaults, options);
        this.widgets_data = {};

        this.init();
    }

    /**
     * Initialize the dashboard
     */
    async init() {
        await this.loadWidgets();
        this.bindGuiEvents();
    }

    /**
     * Load widgets from server
     */
    async loadWidgets() {
        if (!this.options.fetch_uri) {
            return;
        }

        try {
            var response = await fetch(this.options.fetch_uri, {
                headers: {
                    'X-Requested-With': 'XMLHttpRequest'
                }
            });
            var widgets = await response.json();
            this.widgets_data = widgets;

            // Create placeholders and load each widget
            for (var widget_id in widgets) {
                if (!widgets.hasOwnProperty(widget_id)) {
                    continue;
                }

                var widget_info = widgets[widget_id];

                var placeholder = document.createElement('div');
                placeholder.id = 'widget-container-' + widget_id;
                this.container.appendChild(placeholder);

                this.fetchWidgetContent(widget_id, widget_info);
            }
        } catch (e) {
            console.error('Error loading widgets:', e);
        }
    }

    /**
     * Fetch individual widget content
     */
    async fetchWidgetContent(widget_id, widget_data) {
        try {
            var response = await fetch(widget_data.uri, {
                headers: {
                    'X-Requested-With': 'XMLHttpRequest'
                }
            });
            var text = await response.text();
            var html_content;

            // Try to parse as JSON first, fall back to raw HTML
            try {
                var data = JSON.parse(text);
                html_content = data.content;
            } catch (parse_error) {
                html_content = text;
            }

            var temp = document.createElement('div');
            temp.innerHTML = html_content;
            var widget_element = temp.querySelector('section.card');

            if (!widget_element) {
                return;
            }

            // Set data-width attribute from widget state
            var width = widget_data.width || 'full';
            widget_element.setAttribute('data-width', width);

            // Handle closed widget state
            if (!widget_data.open) {
                var header = widget_element.querySelector('div.card-header:last-of-type');
                if (header) {
                    header.classList.add('close');
                }
                widget_element.classList.add('collapsed');

                // Hide widget content
                this.hideWidgetContent(widget_element);

                // Toggle icons
                var arrow = widget_element.querySelector('div.card-header a.arrow');
                if (arrow) {
                    this.toggleIcons(arrow);
                }
            }

            // Toggle widget-width icons for half-width widgets
            if (width === 'half') {
                var resizeLink = widget_element.querySelector('div.card-header a.widget-width');
                if (resizeLink) {
                    this.toggleIcons(resizeLink);
                }
            }

            // Get badge value for closed widgets
            this.getWidgetBadge(widget_element);

            // Replace placeholder with entire widget content (including scripts)
            var placeholder = document.getElementById('widget-container-' + widget_id);
            if (placeholder) {
                // Collect scripts before moving nodes
                var scripts = [];
                temp.querySelectorAll('script').forEach(function(script) {
                    scripts.push(script.textContent);
                });

                // Replace with all content
                placeholder.replaceWith(...temp.childNodes);

                // Execute scripts (innerHTML doesn't execute them)
                scripts.forEach(function(script_content) {
                    var new_script = document.createElement('script');
                    new_script.textContent = script_content;
                    document.body.appendChild(new_script);
                });
            }
        } catch (e) {
            console.error('Error loading widget ' + widget_id + ':', e);
        }
    }

    /**
     * Hide widget content for closed widgets
     */
    hideWidgetContent(element) {
        var headers = element.querySelectorAll('.card-header.close');
        headers.forEach(function(header) {
            var tab_content = header.parentElement.querySelector('.card-content');
            if (tab_content) {
                tab_content.style.display = 'none';
            }
        });
    }

    /**
     * Toggle hidden class on icon elements
     */
    toggleIcons(element) {
        var icons = element.querySelectorAll('i');
        icons.forEach(function(icon) {
            if (icon.classList.contains('hidden')) {
                icon.classList.remove('hidden');
            } else {
                icon.classList.add('hidden');
            }
        });
    }

    /**
     * Fetch and display badge for closed widgets
     */
    async getWidgetBadge(widget) {
        // Remove any existing badge
        var existing_badge = widget.querySelector('.card-header .badge');
        if (existing_badge) {
            existing_badge.remove();
        }

        // Only fetch badge if widget is closed
        var header = widget.querySelector('div.card-header');
        if (!header || !header.classList.contains('close')) {
            return;
        }

        // Find badge URI
        var badge_input = widget.querySelector('input[name="badge_uri"]');
        if (!badge_input) {
            return;
        }

        var badge_uri = badge_input.value;
        if (!badge_uri) {
            return;
        }

        try {
            var response = await fetch(badge_uri, {
                headers: {
                    'X-Requested-With': 'XMLHttpRequest'
                }
            });
            var data = await response.text();

            if (data) {
                var h2 = widget.querySelector('h2');
                if (h2) {
                    var badge = document.createElement('strong');
                    badge.className = 'badge badge-danger';
                    badge.textContent = data;
                    h2.appendChild(badge);
                }
            }
        } catch (e) {
            console.error('Error fetching badge:', e);
        }
    }

    /**
     * Bind all GUI events
     */
    bindGuiEvents() {
        this.initSortable();

        // Use event delegation for all widget events
        this.container.addEventListener('click', this.handleClick.bind(this));

        // Cursor style on hover
        this.container.addEventListener('mouseover', function(e) {
            var header = e.target.closest('.card-header');
            if (header) {
                header.style.cursor = 'move';
            }
        });
    }

    /**
     * Handle click events via delegation
     */
    handleClick(e) {
        // AJAX link requests in widgets
        var ajax_link = e.target.closest('a.ajax');
        if (ajax_link) {
            e.preventDefault();
            this.handleAjaxLink(ajax_link);
            return;
        }

        // Expand/collapse toggle
        var arrow = e.target.closest('a.arrow');
        if (arrow) {
            e.preventDefault();
            this.handleToggle(arrow);
            return;
        }

        // Full screen toggle
        var full_screen = e.target.closest('a.full_screen');
        if (full_screen) {
            e.preventDefault();
            this.handleFullScreen(full_screen);
            return;
        }

        // Widget resize
        var resize = e.target.closest('a.widget-width');
        if (resize) {
            e.preventDefault();
            this.handleResize(resize);
            return;
        }
    }

    /**
     * Initialize Sortable.js for drag-drop
     */
    initSortable() {
        var self = this;

        if (typeof Sortable === 'undefined' || !this.options.update_uri) {
            return;
        }

        new Sortable(this.container, {
            animation: 200,
            handle: '.card-header',
            ghostClass: 'sortable-ghost',
            chosenClass: 'sortable-chosen',
            dragClass: 'sortable-drag',
            easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
            onEnd: function() {
                self.saveWidgetOrder();
            }
        });
    }

    /**
     * Handle expand/collapse toggle
     */
    handleToggle(arrow) {
        var self = this;
        var card = arrow.closest('.card');
        var tab_content = card.querySelector('.card-content');

        if (!tab_content) {
            return;
        }

        // Determine current state: widget is closed if card has 'collapsed' class
        var is_currently_closed = card.classList.contains('collapsed');
        var will_be_open = is_currently_closed;

        if (is_currently_closed) {
            // Remove collapsed class but set display none directly
            // so slideToggle can detect it properly and animate expand
            card.classList.remove('collapsed');
            tab_content.style.display = 'none';
        }

        // Slide toggle animation
        blestaSlideToggle(tab_content, 400, function() {
            self.toggleIcons(arrow);

            if (!will_be_open) {
                card.classList.add('collapsed');
            }

            // Save state to server (true = open, false = closed)
            if (self.options.toggle_uri) {
                var widget_id = card.id;
                self.ajaxRequest('POST', self.options.toggle_uri, widget_id + '=' + will_be_open);
            }

            // Update badge
            self.getWidgetBadge(card);
        });
    }

    /**
     * Handle full screen toggle
     */
    handleFullScreen(button) {
        var card = button.closest('div.card-header').parentElement;
        card.classList.toggle('full-screen');
        this.toggleIcons(button);
    }

    /**
     * Handle widget resize
     */
    handleResize(button) {
        var card = button.closest('.card');
        var current_width = card.getAttribute('data-width') || 'full';
        var new_width = current_width === 'full' ? 'half' : 'full';
        var widget_id = card.id;

        // Update data attribute
        card.setAttribute('data-width', new_width);

        // Toggle icons
        this.toggleIcons(button);

        // Save to server
        if (this.options.resize_uri && widget_id) {
            this.ajaxRequest('POST', this.options.resize_uri, {
                widget_id: widget_id,
                width: new_width
            });
        }
    }

    /**
     * Handle AJAX link requests
     */
    async handleAjaxLink(link) {
        var parent_box = link.closest('section.card');
        var url = link.getAttribute('href');

        // If not in a widget, continue as normal
        if (!parent_box) {
            return;
        }

        try {
            var response = await fetch(url, {
                headers: {
                    'X-Requested-With': 'XMLHttpRequest'
                }
            });

            var data = await response.json();

            // Replace content in the widget
            if (data.replacer == null) {
                // No specific replacer, replace entire box with parsed HTML
                var temp = document.createElement('div');
                temp.innerHTML = data.content;

                // If the content contains a single root element, replace with it
                if (temp.children.length === 1) {
                    parent_box.replaceWith(temp.children[0]);
                } else {
                    // Multiple elements or mixed content - replace parent_box with all content
                    parent_box.replaceWith(...temp.childNodes);
                }
            } else {
                // Replace specific element within the box
                var target = parent_box.querySelector(data.replacer);
                if (target) {
                    target.innerHTML = data.content;
                }
            }
        } catch (e) {
            console.error('AJAX request failed:', e);
        }
    }

    /**
     * Save widget order to server
     */
    saveWidgetOrder() {
        var widget_data = [];
        var widgets = this.container.querySelectorAll('section, .card');

        widgets.forEach(function(card, index) {
            var id = card.id;
            var width = card.getAttribute('data-width') || 'full';
            var column = null;

            if (width === 'half') {
                column = index % 2;
            }

            if (id) {
                widget_data.push({
                    id: id,
                    width: width,
                    column: column,
                    order: index
                });
            }
        });

        this.ajaxRequest('POST', this.options.update_uri, {
            widget: widget_data
        });
    }

    /**
     * Generic AJAX request helper
     */
    ajaxRequest(method, url, data) {
        var options = {
            method: method,
            headers: {
                'X-Requested-With': 'XMLHttpRequest'
            }
        };

        if (data) {
            if (typeof data === 'object') {
                options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
                options.body = this.serializeObject(data);
            } else {
                options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
                options.body = data;
            }
        }

        fetch(url, options).catch(function(e) {
            console.error('AJAX request failed:', e);
        });
    }

    /**
     * Serialize object to URL-encoded string
     */
    serializeObject(obj, prefix) {
        var pairs = [];
        for (var key in obj) {
            if (!obj.hasOwnProperty(key)) {
                continue;
            }

            var param_key = prefix ? prefix + '[' + key + ']' : key;
            var value = obj[key];

            if (typeof value === 'object' && value !== null) {
                pairs.push(this.serializeObject(value, param_key));
            } else {
                pairs.push(encodeURIComponent(param_key) + '=' + encodeURIComponent(value));
            }
        }
        return pairs.join('&');
    }
}

// Auto-initialize on page load
document.addEventListener('DOMContentLoaded', function() {
    // Main dashboard
    var main_dashboard_grid = document.getElementById('main-dashboard-grid');
    if (main_dashboard_grid) {
        window.dashboardWidgets = new DashboardWidgets('#main-dashboard-grid', {
            fetch_uri: base_uri + 'main/getwidgets/',
            update_uri: base_uri + 'main/reorderwidgets/',
            toggle_uri: base_uri + 'main/togglewidget/',
            resize_uri: base_uri + 'main/resizewidget/'
        });
    }

    // Billing dashboard
    var billing_dashboard_grid = document.getElementById('billing-dashboard-grid');
    if (billing_dashboard_grid) {
        window.billingDashboardWidgets = new DashboardWidgets('#billing-dashboard-grid', {
            fetch_uri: base_uri + 'billing/getwidgets/',
            update_uri: base_uri + 'billing/reorderwidgets/',
            toggle_uri: base_uri + 'billing/togglewidget/',
            resize_uri: base_uri + 'billing/resizewidget/'
        });
    }
});
/**
 * Expandable Table Rows with Interactive Elements
 * Handles Bootstrap collapse on table rows while preserving button/link/input functionality
 *
 * Usage:
 * Option 1 - Auto-target next row (recommended, no IDs needed):
 *   <tr data-collapse-row aria-expanded="false">...</tr>
 *   <tr class="collapse">...expanded content...</tr>
 *
 * Option 2 - Explicit target (when next row isn't the target):
 *   <tr data-collapse-target="#some-id" aria-expanded="false">...</tr>
 *   <tr class="collapse" id="some-id">...</tr>
 *
 * Chevron icons:
 *   If the row contains a bi-chevron-down or bi-chevron-up icon, it will automatically
 *   swap between them on expand/collapse (down = collapsed, up = expanded)
 *
 * No onclick handlers needed on buttons/links/inputs - they're automatically excluded
 */
(function() {
    'use strict';

    function initExpandableRows() {
        // Handle both patterns: data-collapse-row (next sibling) and data-collapse-target (explicit)
        // Only select rows not yet initialized to prevent duplicate handlers
        const rows = document.querySelectorAll('[data-collapse-row]:not([data-collapse-initialized]), [data-collapse-target]:not([data-collapse-initialized])');

        rows.forEach(row => {
            row.setAttribute('data-collapse-initialized', '');
            let targetElement;

            if (row.hasAttribute('data-collapse-row')) {
                // Auto-target: find next sibling row with .collapse class
                targetElement = row.nextElementSibling;
                if (!targetElement || !targetElement.classList.contains('collapse')) {
                    console.warn('Expandable row: next sibling is not a .collapse element', row);
                    return;
                }
            } else {
                // Explicit target: use selector from data-collapse-target
                const targetSelector = row.getAttribute('data-collapse-target');
                targetElement = document.querySelector(targetSelector);
                if (!targetElement) {
                    console.warn('Expandable row: target not found', targetSelector);
                    return;
                }
            }

            // Find chevron icon in the row (if any)
            const chevronIcon = row.querySelector('.bi-chevron-down, .bi-chevron-up');

            // Listen to Bootstrap collapse events for reliable state tracking
            if (chevronIcon) {
                targetElement.addEventListener('show.bs.collapse', function() {
                    chevronIcon.classList.remove('bi-chevron-down');
                    chevronIcon.classList.add('bi-chevron-up');
                    row.setAttribute('aria-expanded', 'true');
                });

                targetElement.addEventListener('hide.bs.collapse', function() {
                    chevronIcon.classList.remove('bi-chevron-up');
                    chevronIcon.classList.add('bi-chevron-down');
                    row.setAttribute('aria-expanded', 'false');
                });
            }

            // AJAX lazy-loading via data-collapse-src
            if (targetElement.hasAttribute('data-collapse-src')) {
                targetElement.addEventListener('show.bs.collapse', function() {
                    var src = this.getAttribute('data-collapse-src');
                    var container = this.querySelector('td > div');
                    if (!container || container.hasAttribute('data-loaded')) return;

                    container.setAttribute('data-loaded', '');
                    fetch(src, {
                            method: 'GET',
                            headers: {
                                'X-Requested-With': 'XMLHttpRequest'
                            }
                        })
                        .then(function(response) {
                            return response.text();
                        })
                        .then(function(data) {
                            container.innerHTML = data;
                        })
                        .catch(function(error) {
                            container.removeAttribute('data-loaded');
                            console.error('Error loading collapse content:', error);
                        });
                });
            }

            row.addEventListener('click', function(e) {
                // Check if click is on or inside an interactive element
                const isInteractive = e.target.closest('button, a, input, select, textarea, label');

                if (isInteractive) {
                    return; // Don't toggle collapse for interactive elements
                }

                // Toggle the collapse using Bootstrap's recommended API
                bootstrap.Collapse.getOrCreateInstance(targetElement).toggle();

                // Update aria-expanded if no chevron (chevron handler updates it otherwise)
                if (!chevronIcon) {
                    setTimeout(() => {
                        const isExpanded = targetElement.classList.contains('show');
                        row.setAttribute('aria-expanded', isExpanded);
                    }, 0);
                }
            });
        });
    }

    // Initialize on DOM ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initExpandableRows);
    } else {
        initExpandableRows();
    }

    // Re-initialize after AJAX updates (widget helper dispatches this event)
    document.addEventListener('blestaAjaxComplete', function(e) {
        initExpandableRows();
    });
})();
/**
 * Extension Filter
 *
 * Provides client-side filtering for extension lists (plugins, modules,
 * gateways, messengers) by matching typed text against item name, author,
 * and description.
 *
 * Usage:
 *   - Add a text input with class `extension-filter-input` inside a widget
 *   - Mark each filterable item with `data-extension-item`
 *   - Optionally wrap groups (e.g. gateway types) in `[data-extension-section]`
 *     so the section header hides when all its items are filtered out
 *   - Add a hidden `.extension-filter-no-results` element for empty-state messaging
 */
(function() {
    // Use event delegation on document so timing never matters
    document.addEventListener('input', function(e) {
        if (!e.target.classList.contains('extension-filter-input')) return;

        var query = e.target.value.toLowerCase().trim();
        var card = e.target.closest('.card');
        if (!card) return;

        var items = card.querySelectorAll('[data-extension-item]');
        var visibleCount = 0;

        items.forEach(function(item) {
            var text = item.textContent.toLowerCase();
            var match = !query || text.indexOf(query) !== -1;
            if (match) {
                item.style.removeProperty('display');
                visibleCount++;
            } else {
                item.style.setProperty('display', 'none', 'important');
            }
        });

        // Hide section wrappers when all items within are filtered out
        card.querySelectorAll('[data-extension-section]').forEach(function(section) {
            var anyVisible = false;
            section.querySelectorAll('[data-extension-item]').forEach(function(item) {
                if (item.style.getPropertyValue('display') !== 'none') anyVisible = true;
            });
            if (anyVisible) {
                section.style.removeProperty('display');
            } else {
                section.style.setProperty('display', 'none', 'important');
            }
        });

        // Toggle the "no results" message
        var noResults = card.querySelector('.extension-filter-no-results');
        if (noResults) {
            noResults.style.display = (visibleCount === 0 && query) ? '' : 'none';
        }
    });
})();
/**
 * Searchable Select
 * Progressively enhances a native <select> into a searchable/filterable combobox.
 *
 * No external libraries (no jQuery, no Select2). The native <select> is kept in the
 * DOM (visually hidden) so it retains its name and value for normal form submission;
 * if JavaScript is unavailable the native control still works.
 *
 * Usage:
 *   <select name="group_package" class="form-select" data-searchable
 *           data-placeholder="Select a package..."
 *           data-search-placeholder="Search...">
 *       <optgroup label="Group A">
 *           <option value="1">First</option>
 *           <option value="2" disabled>Second (unavailable)</option>
 *       </optgroup>
 *   </select>
 *
 * - optgroups render as non-selectable group headers
 * - disabled options (and disabled top-level options used as section headers,
 *   e.g. status labels) render muted and cannot be selected
 * - filtering is client-side over the option text already in the DOM
 *
 * Re-initializes on the `blestaAjaxComplete` event so it works inside AJAX-loaded
 * content (consistent with the other Paradigm enhancers).
 */
(function() {
    'use strict';

    const DEFAULT_PLACEHOLDER = 'Select...';
    const DEFAULT_SEARCH_PLACEHOLDER = 'Search...';
    const DEFAULT_NO_RESULTS = 'No matches found';
    let instanceCounter = 0;

    function initSearchableSelects() {
        const selects = document.querySelectorAll('select[data-searchable]:not([data-searchable-initialized])');
        selects.forEach(buildSearchableSelect);
    }

    function buildSearchableSelect(select) {
        select.setAttribute('data-searchable-initialized', '');

        const placeholder = select.getAttribute('data-placeholder') || DEFAULT_PLACEHOLDER;
        const searchPlaceholder = select.getAttribute('data-search-placeholder') || DEFAULT_SEARCH_PLACEHOLDER;
        const noResultsText = select.getAttribute('data-no-results') || DEFAULT_NO_RESULTS;
        const baseId = 'searchable-select-' + (++instanceCounter);

        // Wrapper inserted before the native select; the native select is moved inside
        // and hidden so it keeps submitting its value.
        const wrapper = document.createElement('div');
        wrapper.className = 'searchable-select';
        select.parentNode.insertBefore(wrapper, select);
        wrapper.appendChild(select);
        select.classList.add('searchable-select-native');
        // Keep it out of the tab order / a11y tree; the custom UI provides both.
        select.setAttribute('tabindex', '-1');
        select.setAttribute('aria-hidden', 'true');

        // Toggle button (mirrors .form-select styling)
        const toggle = document.createElement('button');
        toggle.type = 'button';
        toggle.className = 'form-select searchable-select-toggle';
        toggle.id = baseId + '-toggle';
        toggle.setAttribute('aria-haspopup', 'listbox');
        toggle.setAttribute('aria-expanded', 'false');
        if (select.disabled) {
            toggle.disabled = true;
        }
        const valueLabel = document.createElement('span');
        valueLabel.className = 'searchable-select-value';
        valueLabel.id = baseId + '-value';
        toggle.appendChild(valueLabel);
        wrapper.appendChild(toggle);

        // Dropdown panel
        const dropdown = document.createElement('div');
        dropdown.className = 'searchable-select-dropdown';
        dropdown.hidden = true;

        const searchWrap = document.createElement('div');
        searchWrap.className = 'searchable-select-search';
        const searchInput = document.createElement('input');
        searchInput.type = 'text';
        searchInput.className = 'form-control form-control-sm';
        searchInput.placeholder = searchPlaceholder;
        searchInput.autocomplete = 'off';
        searchInput.setAttribute('role', 'combobox');
        searchInput.setAttribute('aria-autocomplete', 'list');
        searchInput.setAttribute('aria-expanded', 'false');
        searchWrap.appendChild(searchInput);
        dropdown.appendChild(searchWrap);

        const list = document.createElement('div');
        list.className = 'searchable-select-options';
        list.id = baseId + '-list';
        list.setAttribute('role', 'listbox');
        dropdown.appendChild(list);
        searchInput.setAttribute('aria-controls', list.id);

        const noResults = document.createElement('div');
        noResults.className = 'searchable-select-no-results';
        noResults.textContent = noResultsText;
        noResults.hidden = true;
        dropdown.appendChild(noResults);

        wrapper.appendChild(dropdown);

        // Wire up the accessible label. The native <select> is now aria-hidden, so the
        // visible toggle and the search field must carry the label relationship instead.
        // If a <label for="..."> targets the select, re-point it at the toggle (a button
        // is a labelable element, so clicking the label still focuses the control) and
        // mirror the label text onto the search input.
        let labelText = '';
        const associatedLabel = select.id ?
            document.querySelector('label[for="' + select.id + '"]') :
            null;
        if (associatedLabel) {
            if (!associatedLabel.id) {
                associatedLabel.id = baseId + '-label';
            }
            associatedLabel.setAttribute('for', toggle.id);
            labelText = associatedLabel.textContent.trim();
            // Announce the label plus the current value when the toggle is focused.
            toggle.setAttribute('aria-labelledby', associatedLabel.id + ' ' + valueLabel.id);
        } else if (select.getAttribute('aria-label')) {
            labelText = select.getAttribute('aria-label');
        }
        if (labelText) {
            searchInput.setAttribute('aria-label', labelText);
        }

        // Build the option rows from the native select's structure.
        // entries types:
        //   'option'   - selectable package
        //   'disabled' - a real package that is unavailable (e.g. inactive/restricted);
        //                shown grayed and searchable, but not selectable
        //   'header'   - a non-selectable label (optgroup label, or a top-level
        //                disabled option used as a section/status heading)
        const entries = [];
        let optionIndex = 0;

        function addOptionRow(option) {
            const row = document.createElement('div');
            const disabled = option.disabled;
            // A disabled option at the top level (not inside an optgroup) is a section
            // header (e.g. a status label). A disabled option inside an optgroup is a
            // real package that simply isn't available for this client.
            const isSectionHeader = disabled && option.parentNode &&
                option.parentNode.tagName !== 'OPTGROUP';
            row.textContent = option.textContent;
            row.id = baseId + '-opt-' + (optionIndex++);

            if (isSectionHeader) {
                row.className = 'searchable-select-option searchable-select-header';
                row.setAttribute('aria-disabled', 'true');
                entries.push({
                    el: row,
                    type: 'header',
                    text: option.textContent.toLowerCase()
                });
            } else if (disabled) {
                row.className = 'searchable-select-option disabled';
                row.setAttribute('role', 'option');
                row.setAttribute('aria-disabled', 'true');
                entries.push({
                    el: row,
                    type: 'disabled',
                    text: option.textContent.toLowerCase()
                });
            } else {
                row.className = 'searchable-select-option';
                row.setAttribute('role', 'option');
                row.setAttribute('aria-selected', 'false');
                row.setAttribute('data-value', option.value);
                entries.push({
                    el: row,
                    type: 'option',
                    value: option.value,
                    text: option.textContent.toLowerCase()
                });
            }
            list.appendChild(row);
        }

        Array.prototype.forEach.call(select.children, function(child) {
            if (child.tagName === 'OPTGROUP') {
                const header = document.createElement('div');
                header.className = 'searchable-select-group';
                header.textContent = child.label;
                entries.push({
                    el: header,
                    type: 'header',
                    text: (child.label || '').toLowerCase()
                });
                list.appendChild(header);
                Array.prototype.forEach.call(child.children, addOptionRow);
            } else if (child.tagName === 'OPTION') {
                // Skip an empty placeholder option (no value, no text)
                if (child.value === '' && child.textContent.trim() === '') {
                    return;
                }
                addOptionRow(child);
            }
        });

        const optionRows = entries.filter(function(e) {
            return e.type === 'option';
        });
        let activeRow = null;

        function syncLabelFromSelect() {
            const selected = select.options[select.selectedIndex];
            // Match the native <select>: if the persisted value resolves to a real
            // option (even a disabled/unavailable one), show its name. Only fall back
            // to the placeholder when there is no concrete option selected.
            const hasOptionSelected = selected && selected.value !== '';
            const isSelectable = hasOptionSelected && !selected.disabled;
            if (hasOptionSelected) {
                valueLabel.textContent = selected.textContent;
                valueLabel.classList.remove('is-placeholder');
            } else {
                valueLabel.textContent = placeholder;
                valueLabel.classList.add('is-placeholder');
            }
            optionRows.forEach(function(e) {
                const isSel = isSelectable && e.value === selected.value;
                e.el.classList.toggle('selected', isSel);
                e.el.setAttribute('aria-selected', isSel ? 'true' : 'false');
            });
        }

        function setActive(row) {
            if (activeRow) {
                activeRow.classList.remove('active');
            }
            activeRow = row;
            if (activeRow) {
                activeRow.classList.add('active');
                searchInput.setAttribute('aria-activedescendant', activeRow.id);
                scrollIntoView(activeRow);
            } else {
                searchInput.removeAttribute('aria-activedescendant');
            }
        }

        function scrollIntoView(row) {
            const top = row.offsetTop;
            const bottom = top + row.offsetHeight;
            if (top < list.scrollTop) {
                list.scrollTop = top;
            } else if (bottom > list.scrollTop + list.clientHeight) {
                list.scrollTop = bottom - list.clientHeight;
            }
        }

        function visibleOptionRows() {
            return optionRows.filter(function(e) {
                return !e.el.hidden;
            });
        }

        function filter(query) {
            const q = query.toLowerCase().trim();
            let anyVisible = false;
            entries.forEach(function(e) {
                // Both selectable and disabled (unavailable) packages are searchable.
                const searchable = e.type === 'option' || e.type === 'disabled';
                if (q === '') {
                    // Restore the full grouped structure.
                    e.el.hidden = false;
                    if (searchable) {
                        anyVisible = true;
                    }
                } else if (searchable) {
                    // Flat results: show matching packages.
                    const match = e.text.indexOf(q) !== -1;
                    e.el.hidden = !match;
                    if (match) {
                        anyVisible = true;
                    }
                } else {
                    // Hide group/section labels during an active search.
                    e.el.hidden = true;
                }
            });
            noResults.hidden = anyVisible;
            list.hidden = !anyVisible;
            // Reset highlight to the first visible option.
            const visible = visibleOptionRows();
            setActive(visible.length ? visible[0].el : null);
            // Height may have changed; keep the dropdown anchored/flipped correctly.
            reposition();
        }

        // The dropdown uses position: fixed so it is never clipped by an
        // overflow:hidden ancestor (e.g. the card body). Anchor it to the toggle
        // and flip above when there isn't enough room below.
        function positionDropdown() {
            const rect = toggle.getBoundingClientRect();
            const margin = 2;
            dropdown.style.width = rect.width + 'px';
            dropdown.style.left = rect.left + 'px';
            const height = dropdown.offsetHeight;
            const spaceBelow = window.innerHeight - rect.bottom;
            const spaceAbove = rect.top;
            if (spaceBelow < height && spaceAbove > spaceBelow) {
                dropdown.style.top = Math.max(margin, rect.top - height - margin) + 'px';
            } else {
                dropdown.style.top = (rect.bottom + margin) + 'px';
            }
        }

        // If the surrounding DOM was replaced (e.g. an AJAX update) while the
        // dropdown was open, close() never got called and the document/window
        // listeners would otherwise stay attached to a detached wrapper. The
        // open-time listeners (onDocumentClick, reposition) each check this and
        // self-tear-down on the next event after the wrapper goes away.
        function isOrphaned() {
            return !document.contains(toggle);
        }

        function reposition() {
            if (isOrphaned()) {
                close();
                return;
            }
            if (!dropdown.hidden) {
                positionDropdown();
            }
        }

        function open() {
            if (dropdown.hidden === false || toggle.disabled) {
                return;
            }
            closeOthers();
            dropdown.hidden = false;
            toggle.setAttribute('aria-expanded', 'true');
            searchInput.setAttribute('aria-expanded', 'true');
            wrapper.classList.add('open');
            searchInput.value = '';
            filter('');
            // Highlight the currently selected option if there is one.
            const current = optionRows.find(function(e) {
                return e.el.classList.contains('selected');
            });
            if (current) {
                setActive(current.el);
            }
            positionDropdown();
            searchInput.focus();
            document.addEventListener('click', onDocumentClick, true);
            // Keep the dropdown anchored to the toggle while open.
            window.addEventListener('scroll', reposition, true);
            window.addEventListener('resize', reposition);
        }

        function close() {
            if (dropdown.hidden) {
                return;
            }
            dropdown.hidden = true;
            toggle.setAttribute('aria-expanded', 'false');
            searchInput.setAttribute('aria-expanded', 'false');
            wrapper.classList.remove('open');
            setActive(null);
            document.removeEventListener('click', onDocumentClick, true);
            window.removeEventListener('scroll', reposition, true);
            window.removeEventListener('resize', reposition);
        }

        // Allow only one open dropdown at a time by closing others on open.
        function closeOthers() {
            document.querySelectorAll('.searchable-select.open').forEach(function(other) {
                if (other !== wrapper && other._searchableSelectClose) {
                    other._searchableSelectClose();
                }
            });
        }
        wrapper._searchableSelectClose = close;

        function selectValue(value) {
            select.value = value;
            select.dispatchEvent(new Event('change', {
                bubbles: true
            }));
            syncLabelFromSelect();
            close();
            toggle.focus();
        }

        function onDocumentClick(e) {
            if (isOrphaned() || !wrapper.contains(e.target)) {
                close();
            }
        }

        // Events
        toggle.addEventListener('click', function() {
            if (dropdown.hidden) {
                open();
            } else {
                close();
            }
        });

        searchInput.addEventListener('input', function() {
            filter(this.value);
        });

        searchInput.addEventListener('keydown', function(e) {
            const visible = visibleOptionRows();
            switch (e.key) {
                case 'ArrowDown': {
                    e.preventDefault();
                    if (!visible.length) {
                        break;
                    }
                    const idx = activeRow ? visible.findIndex(function(v) {
                        return v.el === activeRow;
                    }) : -1;
                    setActive(visible[Math.min(idx + 1, visible.length - 1)].el);
                    break;
                }
                case 'ArrowUp': {
                    e.preventDefault();
                    if (!visible.length) {
                        break;
                    }
                    const idx = activeRow ? visible.findIndex(function(v) {
                        return v.el === activeRow;
                    }) : visible.length;
                    setActive(visible[Math.max(idx - 1, 0)].el);
                    break;
                }
                case 'Enter':
                    e.preventDefault();
                    if (activeRow) {
                        selectValue(activeRow.getAttribute('data-value'));
                    }
                    break;
                case 'Escape':
                    e.preventDefault();
                    close();
                    toggle.focus();
                    break;
                case 'Tab':
                    close();
                    break;
                default:
                    break;
            }
        });

        list.addEventListener('click', function(e) {
            const row = e.target.closest('.searchable-select-option');
            if (row && !row.classList.contains('disabled') && row.hasAttribute('data-value')) {
                selectValue(row.getAttribute('data-value'));
            }
        });

        list.addEventListener('mousemove', function(e) {
            const row = e.target.closest('.searchable-select-option');
            if (row && !row.classList.contains('disabled') && !row.hidden && row !== activeRow) {
                setActive(row);
            }
        });

        // Keep the custom UI in sync if the underlying select is changed elsewhere.
        select.addEventListener('change', syncLabelFromSelect);

        syncLabelFromSelect();
    }

    // Initialize on DOM ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initSearchableSelects);
    } else {
        initSearchableSelects();
    }

    // Re-initialize after AJAX updates (widget helper dispatches this event)
    document.addEventListener('blestaAjaxComplete', function() {
        initSearchableSelects();
    });
})();
/**
 * Step-Up Authentication Timer
 *
 * Manages the countdown timer for step-up authentication sessions,
 * handles session extension, and provides visual feedback as the
 * session approaches expiration.
 *
 * @copyright Copyright (c) 2025, Phillips Data, Inc.
 * @license http://www.blesta.com/license/ The Blesta License Agreement
 * @link http://www.blesta.com/ Blesta
 */
(function() {
    'use strict';

    var STORAGE_KEY = 'stepup_expires_at';
    var WARNING_THRESHOLD = 300; // 5 minutes
    var CRITICAL_THRESHOLD = 120; // 2 minutes
    var timerInterval = null;

    function initStepUpTimer() {
        var indicator = document.getElementById('stepupAuthIndicator');
        if (!indicator) return;

        var expiresAt = parseInt(indicator.getAttribute('data-expires-at'), 10);
        var extendUrl = indicator.getAttribute('data-extend-url');
        var endUrl = indicator.getAttribute('data-end-url');
        var csrfToken = indicator.getAttribute('data-csrf-token');

        // Sync with localStorage for cross-page persistence
        var storedExpiry = parseInt(localStorage.getItem(STORAGE_KEY), 10);
        if (storedExpiry && storedExpiry > expiresAt) {
            expiresAt = storedExpiry;
        } else {
            localStorage.setItem(STORAGE_KEY, expiresAt);
        }

        var extendBtn = document.getElementById('stepupExtendBtn');
        var endBtn = document.getElementById('stepupEndBtn');

        if (extendBtn) {
            extendBtn.addEventListener('click', function(e) {
                e.preventDefault();
                e.stopPropagation();
                extendSession(extendUrl, csrfToken, function(newExpiry) {
                    expiresAt = newExpiry;
                    localStorage.setItem(STORAGE_KEY, expiresAt);
                    updateTimerDisplay(expiresAt, indicator);
                });
            });
        }

        if (endBtn) {
            endBtn.addEventListener('click', function(e) {
                e.preventDefault();
                e.stopPropagation();
                endSession(endUrl);
            });
        }

        // Start the countdown
        updateTimerDisplay(expiresAt, indicator);
        timerInterval = setInterval(function() {
            // Check for updates from other tabs
            var currentStored = parseInt(localStorage.getItem(STORAGE_KEY), 10);
            if (currentStored && currentStored > expiresAt) {
                expiresAt = currentStored;
            }
            updateTimerDisplay(expiresAt, indicator);
        }, 1000);

        // Listen for storage changes from other tabs
        window.addEventListener('storage', function(e) {
            if (e.key === STORAGE_KEY) {
                var newVal = parseInt(e.newValue, 10);
                if (newVal) {
                    expiresAt = newVal;
                } else {
                    // Session was cleared in another tab
                    handleSessionEnd(indicator);
                }
            }
        });
    }

    /**
     * Update the timer display elements
     *
     * @param {number} expiresAt Unix timestamp when session expires
     * @param {HTMLElement} indicator The indicator element
     */
    function updateTimerDisplay(expiresAt, indicator) {
        var now = Math.floor(Date.now() / 1000);
        var remaining = expiresAt - now;

        var timerEl = document.getElementById('stepupTimer');
        var badgeEl = document.getElementById('stepupTimerBadge');

        if (remaining <= 0) {
            handleSessionEnd(indicator);
            return;
        }

        var minutes = Math.floor(remaining / 60);
        var seconds = remaining % 60;
        var display = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;

        // Update timer text in dropdown
        if (timerEl) {
            timerEl.textContent = display;

            // Update color class
            timerEl.className = '';
            if (remaining <= CRITICAL_THRESHOLD) {
                timerEl.className = 'timer-critical';
            } else if (remaining <= WARNING_THRESHOLD) {
                timerEl.className = 'timer-warning';
            } else {
                timerEl.className = 'timer-normal';
            }
        }

        // Show/hide badge on icon when under warning threshold
        if (badgeEl) {
            if (remaining <= WARNING_THRESHOLD) {
                badgeEl.textContent = display;
                badgeEl.style.display = '';
            } else {
                badgeEl.style.display = 'none';
            }
        }
    }

    /**
     * Extend the step-up session via AJAX
     *
     * @param {string} url The extend endpoint URL
     * @param {string} csrfToken The CSRF token
     * @param {function} onSuccess Callback with new expiry timestamp
     */
    function extendSession(url, csrfToken, onSuccess) {
        var xhr = new XMLHttpRequest();
        xhr.open('POST', url, true);
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4 && xhr.status === 200) {
                try {
                    var response = JSON.parse(xhr.responseText);
                    if (response.success && response.expires_at) {
                        onSuccess(response.expires_at);
                    }
                } catch (e) {
                    // Parse error -- ignore
                }
            }
        };
        xhr.send('_csrf_token=' + encodeURIComponent(csrfToken || ''));
    }

    /**
     * End the step-up session via AJAX
     *
     * @param {string} url The drop endpoint URL
     */
    function endSession(url) {
        var xhr = new XMLHttpRequest();
        xhr.open('GET', url, true);
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                handleSessionEnd(document.getElementById('stepupAuthIndicator'));
            }
        };
        xhr.send();
    }

    /**
     * Handle session expiration or end
     *
     * @param {HTMLElement} indicator The indicator element
     */
    function handleSessionEnd(indicator) {
        if (timerInterval) {
            clearInterval(timerInterval);
            timerInterval = null;
        }

        localStorage.removeItem(STORAGE_KEY);

        if (indicator) {
            indicator.style.display = 'none';
        }
    }

    // Initialize when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initStepUpTimer);
    } else {
        initStepUpTimer();
    }
})();
/**
 * Paradigm Declarative Visibility
 *
 * Show/hide a wrapper based on form-input state, declared via data attributes.
 * The wrapper carries the rule; the trigger input is targeted by CSS selector.
 *
 * Attributes (place on the wrapper being shown/hidden):
 *   data-show-when-checked="<selector>"   show when trigger.checked === true
 *   data-hide-when-checked="<selector>"   show when trigger.checked === false
 *   data-show-when-value="<selector>"     show when trigger.value is in data-values
 *   data-hide-when-value="<selector>"     show when trigger.value is NOT in data-values
 *   data-values="v1 v2 v3"                space-separated list, required with the *-value forms
 *
 * Multiple attributes on one wrapper combine with AND (any false rule -> hide).
 *
 * When hiding, inline style.display is set to 'none'. When showing, the inline
 * display property is removed so the wrapper's stylesheet decides (block for a
 * <div>, inline-block for a button, table-row for a <tr>, etc.).
 *
 * Initial state is evaluated on wire-up; no need to fire a change event manually.
 *
 * For AJAX-inserted markup: the framework's `blestaAjaxComplete` event triggers
 * a rescan automatically. To rescan manually, call:
 *     window.Paradigm.rescanVisibility(rootElement);
 *
 * @copyright Copyright (c) 2026, Phillips Data, Inc.
 * @license http://www.blesta.com/license/ The Blesta License Agreement
 * @link http://www.blesta.com/ Blesta
 */
(function() {
    'use strict';

    const INITIALIZED_ATTRIBUTE = 'data-visibility-initialized';

    const RULE_ATTRIBUTES = [
        'data-show-when-checked',
        'data-hide-when-checked',
        'data-show-when-value',
        'data-hide-when-value'
    ];

    function parseValueList(wrapper) {
        return (wrapper.getAttribute('data-values') || '').split(/\s+/).filter(Boolean);
    }

    function collectRules(wrapper) {
        const rules = [];
        const values = parseValueList(wrapper);

        const showCheckedSelector = wrapper.getAttribute('data-show-when-checked');
        if (showCheckedSelector) {
            rules.push({
                selector: showCheckedSelector,
                isSatisfied: function(trigger) {
                    return !!trigger.checked;
                }
            });
        }

        const hideCheckedSelector = wrapper.getAttribute('data-hide-when-checked');
        if (hideCheckedSelector) {
            rules.push({
                selector: hideCheckedSelector,
                isSatisfied: function(trigger) {
                    return !trigger.checked;
                }
            });
        }

        const showValueSelector = wrapper.getAttribute('data-show-when-value');
        if (showValueSelector) {
            rules.push({
                selector: showValueSelector,
                isSatisfied: function(trigger) {
                    return values.indexOf(trigger.value) !== -1;
                }
            });
        }

        const hideValueSelector = wrapper.getAttribute('data-hide-when-value');
        if (hideValueSelector) {
            rules.push({
                selector: hideValueSelector,
                isSatisfied: function(trigger) {
                    return values.indexOf(trigger.value) === -1;
                }
            });
        }

        return rules;
    }

    function applyVisibility(wrapper, rules, triggers) {
        const shouldHide = rules.some(function(rule, index) {
            const trigger = triggers[index];
            if (!trigger) {
                return false;
            }
            return !rule.isSatisfied(trigger);
        });

        if (shouldHide) {
            wrapper.style.display = 'none';
        } else {
            wrapper.style.removeProperty('display');
        }
    }

    function wireWrapper(wrapper) {
        const rules = collectRules(wrapper);
        if (rules.length === 0) {
            return;
        }

        const triggers = rules.map(function(rule) {
            const trigger = document.querySelector(rule.selector);
            if (!trigger) {
                console.warn(
                    'Paradigm visibility: trigger not found for selector',
                    rule.selector,
                    wrapper
                );
            }
            return trigger;
        });

        function evaluate() {
            applyVisibility(wrapper, rules, triggers);
        }

        triggers.forEach(function(trigger) {
            if (trigger) {
                trigger.addEventListener('change', evaluate);
            }
        });

        evaluate();
    }

    function buildScanSelector() {
        return RULE_ATTRIBUTES.map(function(attribute) {
            return '[' + attribute + ']:not([' + INITIALIZED_ATTRIBUTE + '])';
        }).join(',');
    }

    function initVisibility(root) {
        const scope = root || document;
        if (!scope || typeof scope.querySelectorAll !== 'function') {
            return;
        }

        const wrappers = scope.querySelectorAll(buildScanSelector());
        wrappers.forEach(function(wrapper) {
            wrapper.setAttribute(INITIALIZED_ATTRIBUTE, '');
            wireWrapper(wrapper);
        });
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function() {
            initVisibility();
        });
    } else {
        initVisibility();
    }

    document.addEventListener('blestaAjaxComplete', function(event) {
        const detail = event && event.detail ? event.detail : null;
        const root = detail && detail.card ? detail.card : document;
        initVisibility(root);
    });

    window.Paradigm = window.Paradigm || {};
    window.Paradigm.rescanVisibility = initVisibility;
})();
/**
 * Blesta Javascript Library
 *
 * @copyright Copyright (c) 2025, Phillips Data, Inc.
 * @license http://www.blesta.com/license/ The Blesta License Agreement
 * @link http://www.blesta.com/ Blesta
 */
(function() {
    'use strict';

    // Must stay in sync with the pre-paint theme script in
    // public_html/app/views/shared/theme_init.pdt
    const STORAGE_KEY_THEME = 'blesta-theme';
    const STORAGE_KEY_SIDEBAR = 'blesta-sidebar-collapsed';
    const THEME_DARK = 'dark';
    const THEME_LIGHT = 'light';

    /**
     * Get the current theme from localStorage or system preference
     */
    function getStoredTheme() {
        return localStorage.getItem(STORAGE_KEY_THEME);
    }

    /**
     * Save theme preference to localStorage
     */
    function setStoredTheme(theme) {
        localStorage.setItem(STORAGE_KEY_THEME, theme);
    }

    /**
     * Get system theme preference
     */
    function getSystemTheme() {
        if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
            return THEME_DARK;
        }
        return THEME_LIGHT;
    }

    /**
     * Get the theme to apply (stored > system > default dark)
     */
    function getPreferredTheme() {
        const storedTheme = getStoredTheme();
        if (storedTheme) {
            return storedTheme;
        }
        return getSystemTheme();
    }

    /**
     * Apply theme to the document
     */
    function setTheme(theme) {
        document.documentElement.setAttribute('data-bs-theme', theme);
        document.documentElement.setAttribute('data-theme', theme);
        updateThemeIcon(theme);
    }

    /**
     * Update the theme toggle button icon
     */
    function updateThemeIcon(theme) {
        const themeToggleBtn = document.getElementById('theme-toggle');
        if (!themeToggleBtn) return;

        const icon = themeToggleBtn.querySelector('i');
        if (!icon) return;

        // Remove existing icon classes
        icon.className = '';

        // Add appropriate icon based on current theme
        if (theme === THEME_DARK) {
            // Show sun icon in dark mode (clicking will switch to light)
            icon.classList.add('bi', 'bi-sun');
            themeToggleBtn.setAttribute('aria-label', 'Switch to light mode');
        } else {
            // Show moon icon in light mode (clicking will switch to dark)
            icon.classList.add('bi', 'bi-moon-stars');
            themeToggleBtn.setAttribute('aria-label', 'Switch to dark mode');
        }
    }

    /**
     * Toggle between light and dark themes
     */
    function toggleTheme() {
        const currentTheme = document.documentElement.getAttribute('data-theme') || THEME_DARK;
        const newTheme = currentTheme === THEME_DARK ? THEME_LIGHT : THEME_DARK;

        setTheme(newTheme);
        setStoredTheme(newTheme);
    }

    /**
     * Initialize theme on page load
     */
    function initTheme() {
        // The theme attributes are set before first paint by the shared script in
        // views/shared/theme_init.pdt; read the applied theme rather than recomputing it
        const theme = document.documentElement.getAttribute('data-theme') || getPreferredTheme();
        setTheme(theme);

        // Add event listener to toggle button
        const themeToggleBtn = document.getElementById('theme-toggle');
        if (themeToggleBtn) {
            themeToggleBtn.addEventListener('click', toggleTheme);
        }

        // Listen for system theme changes
        if (window.matchMedia) {
            window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
                // Only update if user hasn't manually set a preference
                if (!getStoredTheme()) {
                    const newTheme = e.matches ? THEME_DARK : THEME_LIGHT;
                    setTheme(newTheme);
                }
            });
        }
    }

    // Initialize when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initTheme);
    } else {
        initTheme();
    }

    // Expose toggle function globally if needed
    window.toggleTheme = toggleTheme;

    /**
     * Detect if user is on macOS
     */
    function isMacOS() {
        return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
    }

    /**
     * Initialize search shortcut
     */
    function initSearchShortcut() {
        var search_bar_shortcut = document.querySelector('.search-bar-shortcut');
        var smart_search = document.getElementById('smart-search');

        // Set shortcut text based on OS
        if (search_bar_shortcut) {
            if (isMacOS()) {
                search_bar_shortcut.textContent = 'Cmd + K';
            } else {
                search_bar_shortcut.textContent = 'Ctrl + K';
            }
        }

        // Add keyboard event listener
        if (smart_search) {
            document.addEventListener('keydown', function(e) {
                var is_mac = isMacOS();
                var modifier_pressed = is_mac ? e.metaKey : e.ctrlKey;

                if (modifier_pressed && e.key === 'k') {
                    e.preventDefault();
                    smart_search.focus();
                }
            });
        }
    }

    // Initialize search shortcut when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initSearchShortcut);
    } else {
        initSearchShortcut();
    }

    /**
     * Get sidebar state from localStorage
     */
    function getSidebarState() {
        return localStorage.getItem(STORAGE_KEY_SIDEBAR);
    }

    /**
     * Save sidebar state to localStorage
     */
    function setSidebarState(collapsed) {
        if (collapsed) {
            localStorage.setItem(STORAGE_KEY_SIDEBAR, 'true');
        } else {
            localStorage.removeItem(STORAGE_KEY_SIDEBAR);
        }
    }

    /**
     * Update mobile menu toggle icon
     */
    function updateMobileMenuIcon(sidebar) {
        var mobile_menu_toggle = document.querySelector('.mobile-menu-toggle');
        if (!mobile_menu_toggle) return;

        var icon = mobile_menu_toggle.querySelector('i');
        if (!icon) return;

        // Remove existing icon classes
        icon.className = '';

        // Add appropriate icon based on sidebar state
        if (sidebar.classList.contains('collapsed')) {
            // Sidebar is collapsed, show left indent icon (will expand when clicked)
            icon.classList.add('bi', 'bi-text-indent-left');
        } else {
            // Sidebar is open, show right indent icon (will collapse when clicked)
            icon.classList.add('bi', 'bi-text-indent-right');
        }

        // Check if screen width is 768px or less
        var is_mobile = window.innerWidth <= 768;

        if (is_mobile) {
            // Sidebar is open, show right indent icon (will collapse when clicked)
            icon.classList.add('bi', 'bi-text-indent-right');
        }
    }

    /**
     * Initialize mobile menu toggle
     */
    function initMobileMenu() {
        var mobile_menu_toggle = document.querySelector('.mobile-menu-toggle');
        var sidebar = document.querySelector('.sidebar');
        var iconbar = document.querySelector('.icon-bar');

        // Clear the pre-paint collapsed marker set by the inline script in
        // structure.pdt; the real state is applied below in the same frame, so the
        // hand-off can't animate
        document.documentElement.classList.remove('sidebar-collapsed-init');

        if (!mobile_menu_toggle || !sidebar || !iconbar) return;

        // Check if screen width is 992px or less
        var is_tablet = window.innerWidth <= 992;

        if (is_tablet) {
            // Force collapse on mobile screens, ignore localStorage
            sidebar.classList.add('collapsed');
        } else {
            // Apply saved sidebar state on larger screens
            var is_collapsed = getSidebarState() === 'true';
            if (is_collapsed) {
                sidebar.classList.add('collapsed');
            } else {
                sidebar.classList.remove('collapsed');
            }
        }

        // Set initial icon state
        updateMobileMenuIcon(sidebar);

        // Add click event listener
        mobile_menu_toggle.addEventListener('click', function(e) {
            e.preventDefault();

            // Check if screen width is 768px or less
            var is_mobile = window.innerWidth <= 768;

            if (is_mobile) {
                // Toggle show class on both sidebar and icon-bar for mobile
                sidebar.classList.toggle('show');
                iconbar.classList.toggle('show');
            }

            // Always keep the original behavior for larger screens
            sidebar.classList.toggle('collapsed');
            var collapsed = sidebar.classList.contains('collapsed');
            setSidebarState(collapsed);
            updateMobileMenuIcon(sidebar);
        });
    }

    /**
     * Initialize sidebar handle toggle for mobile view
     */
    function initSidebarHandle() {
        var sidebar_handle = document.querySelector('.sidebar-handle');
        var sidebar = document.querySelector('.sidebar');
        var icon_bar = document.querySelector('.icon-bar');

        if (!sidebar_handle || !sidebar) return;

        // Add click event listener to sidebar handle
        sidebar_handle.addEventListener('click', function(e) {
            e.preventDefault();

            // Toggle show class on sidebar
            sidebar.classList.toggle('show');

            // Toggle show class on icon-bar if it exists
            if (icon_bar) {
                icon_bar.classList.toggle('show');
            }
        });
    }

    /**
     * Initialize the settings side-content drawer for mobile view.
     *
     * On mobile the settings navigation (rendered as the .side-content panel) is an
     * off-canvas drawer that slides in from the right. A right-edge handle toggles it,
     * the dimmed overlay or a nav link tap closes it, as does the Escape key.
     */
    function initSideContentDrawer() {
        var handle = document.getElementById('sideContentHandle');
        var drawer = document.querySelector('.side-content.settings-side-content');
        var overlay = document.getElementById('sideContentOverlay');

        if (!handle || !drawer) return;

        var mobileQuery = window.matchMedia('(max-width: 767.98px)');

        // Keep the closed off-canvas drawer out of the tab order and the accessibility
        // tree. It is only ever offscreen (and thus only inert) on mobile — at larger
        // breakpoints the same element is the always-visible sidebar and must stay
        // interactive, so inert/aria-hidden are cleared whenever the panel isn't a
        // closed mobile drawer.
        function applyInertState() {
            var shouldBeInert = mobileQuery.matches && !drawer.classList.contains('show');
            drawer.inert = shouldBeInert;
            if (shouldBeInert) {
                drawer.setAttribute('aria-hidden', 'true');
            } else {
                drawer.removeAttribute('aria-hidden');
            }
        }

        function setOpen(open) {
            var willOpen = (typeof open === 'boolean') ? open : !drawer.classList.contains('show');
            drawer.classList.toggle('show', willOpen);
            handle.classList.toggle('open', willOpen);
            handle.setAttribute('aria-expanded', willOpen ? 'true' : 'false');
            if (overlay) overlay.classList.toggle('active', willOpen);
            applyInertState();

            // When closing, return focus to the handle so it doesn't get stranded on a
            // now-inert element (the browser would otherwise drop it to the body).
            if (!willOpen && drawer.contains(document.activeElement)) {
                handle.focus();
            }
        }

        handle.addEventListener('click', function(e) {
            e.preventDefault();
            setOpen();
        });

        if (overlay) {
            overlay.addEventListener('click', function() {
                setOpen(false);
            });
        }

        // Close the drawer when a navigation link is tapped (the page navigates anyway).
        // Group headers that merely toggle a collapse (data-bs-toggle) should not close it.
        drawer.addEventListener('click', function(e) {
            var link = e.target.closest('a[href]');
            if (link && !link.hasAttribute('data-bs-toggle')) {
                setOpen(false);
            }
        });

        document.addEventListener('keydown', function(e) {
            if (e.key === 'Escape' && drawer.classList.contains('show')) {
                setOpen(false);
            }
        });

        // Re-evaluate inert when crossing the mobile/desktop breakpoint so the desktop
        // sidebar never stays inert and the closed mobile drawer always is.
        if (mobileQuery.addEventListener) {
            mobileQuery.addEventListener('change', applyInertState);
        } else if (mobileQuery.addListener) {
            mobileQuery.addListener(applyInertState);
        }

        // Establish the initial state (closed drawer on mobile starts inert).
        applyInertState();
    }

    // Initialize mobile menu when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initMobileMenu);
    } else {
        initMobileMenu();
    }

    // Initialize sidebar handle when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initSidebarHandle);
    } else {
        initSidebarHandle();
    }

    // Initialize settings drawer handle when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initSideContentDrawer);
    } else {
        initSideContentDrawer();
    }


    /**
     * Initialize dropdown menu search
     */
    function initDropdownMenuSearch() {
        var dropdown_menu = document.querySelector('.dropdown-menu-search');
        if (!dropdown_menu) return;

        var search_options = dropdown_menu.querySelectorAll('.search-type-option');
        if (search_options.length === 0) return;

        var search_type_input = document.querySelector('input[name="search_type"]');
        var smart_search = document.getElementById('smart-search');
        var search_icon = document.querySelector('.search-bar-icon');

        search_options.forEach(function(option) {
            option.addEventListener('click', function(e) {
                e.preventDefault();

                var data_type = option.getAttribute('data-type');
                var data_placeholder = option.getAttribute('data-placeholder');
                var data_icon = option.getAttribute('data-icon');

                // Update hidden input value
                if (search_type_input && data_type) {
                    search_type_input.value = data_type;
                }

                // Update search input placeholder
                if (smart_search && data_placeholder) {
                    smart_search.setAttribute('placeholder', data_placeholder);
                }

                // Update search icon classes
                if (search_icon && data_icon) {
                    // Get current classes
                    var current_classes = Array.from(search_icon.classList);

                    // Remove all classes except search-bar-icon and dropdown-toggle
                    current_classes.forEach(function(class_name) {
                        if (class_name !== 'search-bar-icon' && class_name !== 'dropdown-toggle') {
                            search_icon.classList.remove(class_name);
                        }
                    });

                    // Add new icon classes from data-icon
                    var new_classes = data_icon.split(' ');
                    new_classes.forEach(function(class_name) {
                        if (class_name.trim() !== '') {
                            search_icon.classList.add(class_name.trim());
                        }
                    });
                }

                // Close the dropdown
                var dropdown = bootstrap.Dropdown.getInstance(search_icon);
                if (dropdown) {
                    dropdown.hide();
                }
            });
        });
    }

    // Initialize dropdown menu search when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initDropdownMenuSearch);
    } else {
        initDropdownMenuSearch();
    }

    /**
     * Initialize company selector redirect
     */
    function initCompanySelector() {
        var company_selector = document.getElementById('company-selector');

        if (!company_selector) return;

        company_selector.addEventListener('change', function() {
            var selected_value = this.value;
            var request_uri = window.location.pathname + window.location.search;

            if (selected_value && base_uri) {
                window.location.href = base_uri + 'login/index/' + selected_value + '/?uri=' + encodeURIComponent(request_uri);
            }
        });
    }

    // Initialize company selector when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initCompanySelector);
    } else {
        initCompanySelector();
    }

    /**
     * Performs an Ajax request and fills the given container in the
     * next table row (tr) of the element with the data returned by the request.
     * Also toggles the visibility of the expand_details row.
     *
     * @param {HTMLElement} element The element whose next sibling tr will be updated
     * @param {string} uri The URI to request
     * @param {string|HTMLElement} container The selector or element to fill with response data
     */
    function blestaUpdateRow(element, uri, container) {
        // Get the next sibling tr element
        var nextRow = element.nextElementSibling;
        while (nextRow && nextRow.tagName !== 'TR') {
            nextRow = nextRow.nextElementSibling;
        }

        if (!nextRow) {
            return;
        }

        // Check if row is currently visible
        var isVisible = nextRow.style.display === 'table-row';

        // Toggle visibility
        if (isVisible) {
            nextRow.style.display = 'none';
            element.classList.remove('expanded');
            return;
        }

        // Show the row
        nextRow.style.display = 'table-row';
        element.classList.add('expanded');

        // Only make the request if content hasn't been loaded yet
        var targetElement = container instanceof HTMLElement ?
            container :
            nextRow.querySelector(container);

        if (targetElement && targetElement.innerHTML.trim() !== '') {
            return;
        }

        // Make the GET request
        fetch(uri, {
                method: 'GET',
                headers: {
                    'X-Requested-With': 'XMLHttpRequest'
                }
            })
            .then(function(response) {
                return response.text();
            })
            .then(function(data) {
                if (targetElement) {
                    targetElement.innerHTML = data;
                }
            })
            .catch(function(error) {
                console.error('blestaUpdateRow error:', error);
            });
    }

    // Expose globally
    window.blestaUpdateRow = blestaUpdateRow;

    // =========================================================================
    // Vanilla JS versions of blesta.js functions (converted from jQuery)
    // =========================================================================

    /**
     * Scroll a DOM element from within its container element (i.e. scroll credits)
     *
     * @param {string} contentId The ID of the content element to scroll
     * @param {string} containerId The ID of the container element that holds content
     * @param {number} startDelay The number of milliseconds to wait before beginning the scroll
     * @param {number} endDelay The number of milliseconds to pause at the end of the scroll before repeating
     * @param {number} msPer100px The number of milliseconds it takes to scroll 100 px (default 3000)
     */
    function blestaScrollDom(contentId, containerId, startDelay, endDelay, msPer100px) {
        msPer100px = msPer100px || 3000;

        var content = document.getElementById(contentId);
        var container = document.getElementById(containerId);

        if (!content || !container) return;

        var contentHeight = parseInt(content.offsetHeight) || 700;
        var containerHeight = parseInt(container.offsetHeight);

        var totalTime = parseInt(msPer100px * containerHeight / 100);

        // Clear any existing timeout
        if (window._blestaScrollTimeout) {
            clearTimeout(window._blestaScrollTimeout);
            window._blestaScrollTimeout = null;
        }

        // Reset content position
        content.style.top = '0px';
        content.style.position = 'relative';

        // Set delay to begin animation
        setTimeout(function() {
            var startTime = null;
            var startTop = 0;
            var targetTop = -(contentHeight - containerHeight);

            function animate(currentTime) {
                if (!startTime) startTime = currentTime;
                var elapsed = currentTime - startTime;
                var progress = Math.min(elapsed / totalTime, 1);

                content.style.top = (startTop + (targetTop - startTop) * progress) + 'px';

                if (progress < 1) {
                    requestAnimationFrame(animate);
                } else {
                    // Animation complete, replay after delay if visible
                    if (content.offsetParent !== null) {
                        window._blestaScrollTimeout = setTimeout(function() {
                            blestaScrollDom(contentId, containerId, startDelay, endDelay, msPer100px);
                        }, endDelay);
                    }
                }
            }

            requestAnimationFrame(animate);
        }, startDelay);
    }

    window.blestaScrollDom = blestaScrollDom;

    /**
     * Serializes an object to URL-encoded string, handling nested objects and arrays
     *
     * @param {Object} obj The object to serialize
     * @param {string} prefix Optional prefix for nested keys
     * @return {string} URL-encoded string
     */
    function serializeObject(obj, prefix) {
        var pairs = [];
        for (var key in obj) {
            if (!obj.hasOwnProperty(key)) {
                continue;
            }

            var paramKey = prefix ? prefix + '[' + key + ']' : key;
            var value = obj[key];

            if (typeof value === 'object' && value !== null) {
                pairs.push(serializeObject(value, paramKey));
            } else {
                pairs.push(encodeURIComponent(paramKey) + '=' + encodeURIComponent(value));
            }
        }
        return pairs.join('&');
    }

    /**
     * Performs an Ajax request using fetch API
     *
     * @param {string} method The method of the request "GET", "POST", etc.
     * @param {string} uri The URI to request
     * @param {Object|string|FormData} params Data to be sent to the server
     * @param {Function} onSuccess The callback function to execute on success
     * @param {Function} onError The callback function to execute on error
     * @param {Object} options Additional options (dataType, etc.)
     */
    function blestaRequest(method, uri, params, onSuccess, onError, options) {
        options = options || {};

        var fetchOptions = {
            method: method,
            headers: {
                'X-Requested-With': 'XMLHttpRequest'
            }
        };

        // Handle params
        if (params) {
            if (method.toUpperCase() === 'GET') {
                var queryString = params instanceof FormData ?
                    new URLSearchParams(params).toString() :
                    (typeof params === 'string' ? params : serializeObject(params));
                uri += (uri.indexOf('?') === -1 ? '?' : '&') + queryString;
            } else {
                if (params instanceof FormData) {
                    fetchOptions.body = params;
                } else if (typeof params === 'string') {
                    fetchOptions.headers['Content-Type'] = 'application/x-www-form-urlencoded';
                    fetchOptions.body = params;
                } else {
                    fetchOptions.headers['Content-Type'] = 'application/x-www-form-urlencoded';
                    fetchOptions.body = serializeObject(params);
                }
            }
        }

        fetch(uri, fetchOptions)
            .then(function(response) {
                if (!response.ok) {
                    // Handle 401 and 406 errors like jQuery version
                    if (response.status === 401 || response.status === 406) {
                        window.location = window.location.href;
                        return;
                    }
                    throw new Error('Network response was not ok');
                }
                if (options.dataType === 'json') {
                    return response.json();
                }
                return response.text();
            })
            .then(function(data) {
                if (onSuccess) {
                    onSuccess(data);
                }
            })
            .catch(function(error) {
                if (onError) {
                    onError(error);
                }
            });
    }

    window.blestaRequest = blestaRequest;

    /**
     * Submits the given form when the given element is clicked
     *
     * @param {HTMLElement|string} element The element(s) to bind click to
     * @param {string} formId Optional form ID to submit, defaults to closest form
     */
    function blestaSubmitOnClick(element, formId) {
        var elements = typeof element === 'string' ?
            document.querySelectorAll(element) : [element];

        elements.forEach(function(el) {
            el.addEventListener('click', function(e) {
                e.preventDefault();
                if (formId) {
                    var form = document.getElementById(formId);
                    if (form) form.submit();
                } else {
                    var form = el.closest('form');
                    if (form) form.submit();
                }
                return false;
            });
        });
    }

    window.blestaSubmitOnClick = blestaSubmitOnClick;

    /**
     * Calculate contrast color for a given hex color
     *
     * @param {string} hex The hex color value
     * @returns {string} Either '000' or 'fff'
     */
    function blestaContrastColor(hex) {
        hex = hex.replace('#', '');
        if (hex.length === 3) {
            hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
        }
        return (parseInt(hex, 16) > 0xffffff / 2 ? '000' : 'fff');
    }

    window.blestaContrastColor = blestaContrastColor;

    /**
     * Convert RGB color to hex
     *
     * @param {string} rgb The RGB color string (e.g., "rgb(255, 255, 255)")
     * @returns {string} The hex color value
     */
    function blestaRgbToHex(rgb) {
        var color = rgb.replace(/\s/g, '').match(/^rgba?\((\d+),(\d+),(\d+)/i);

        return (color && color.length === 4) ? '#' +
            ('0' + parseInt(color[1], 10).toString(16)).slice(-2) +
            ('0' + parseInt(color[2], 10).toString(16)).slice(-2) +
            ('0' + parseInt(color[3], 10).toString(16)).slice(-2) : rgb;
    }

    window.blestaRgbToHex = blestaRgbToHex;

    /**
     * Vertically align an element within its container
     *
     * @param {HTMLElement|string} element The element to align
     * @param {Object} options Options including container and offset
     */
    function blestaVerticalAlign(element, options) {
        options = options || {};
        var elements = typeof element === 'string' ?
            document.querySelectorAll(element) : [element];

        elements.forEach(function(el) {
            var container = options.container || el.parentElement;
            var offset = options.offset || 2;

            var containerHeight = container.offsetHeight;
            var elementHeight = el.offsetHeight;

            el.style.top = Math.max(0, containerHeight / offset - elementHeight / 2) + 'px';
        });
    }

    window.blestaVerticalAlign = blestaVerticalAlign;

    /**
     * Makes an ajax request to the given URI to fetch the invoice line totals
     *
     * @param {HTMLElement|string} formElement The form element or selector
     * @param {string} uri The URI to POST to asynchronously
     */
    function blestaSetInvTotals(formElement, uri) {
        var form = typeof formElement === 'string' ?
            document.querySelector(formElement) :
            formElement.closest('form');

        if (!form) return;

        var formData = new FormData(form);

        blestaRequest('POST', uri, formData, function(data) {
            // Update subtotal
            if (data.subtotal && data.subtotal.amount_formatted) {
                var subtotalEm = document.querySelector('.totals_subtotal em');
                if (subtotalEm) subtotalEm.textContent = data.subtotal.amount_formatted;
            }

            // Update tax values
            var taxLevel = 0;
            document.querySelectorAll('.totals_tax').forEach(function(taxEl) {
                if (data.tax && data.tax[taxLevel] && data.tax[taxLevel].amount_formatted) {
                    taxEl.style.display = '';

                    var tax = data.tax[taxLevel];
                    var taxName = tax.description;

                    var span = taxEl.querySelector('span');
                    var em = taxEl.querySelector('em');
                    if (span) span.textContent = taxName;
                    if (em) em.textContent = tax.amount_formatted;
                } else {
                    taxEl.style.display = 'none';
                }
                taxLevel++;
            });

            // Update total
            if (data.total_w_tax && data.total_w_tax.amount_formatted) {
                var totalEm = document.querySelector('.totals_total em');
                if (totalEm) totalEm.textContent = data.total_w_tax.amount_formatted;
            }

            // Update amount due
            if (data.total_due && data.total_due.amount_formatted) {
                var dueEm = document.querySelector('.totals_due em');
                if (dueEm) dueEm.textContent = data.total_due.amount_formatted;
            }

            // Update amount paid
            if (data.total_paid && data.total_paid.amount_formatted) {
                var paidEm = document.querySelector('.totals_paid em');
                if (paidEm) paidEm.textContent = '-' + data.total_paid.amount_formatted;
            }
        }, null, {
            dataType: 'json'
        });
    }

    window.blestaSetInvTotals = blestaSetInvTotals;

    /**
     * Returns the position of the caret within the given element
     *
     * @param {HTMLElement} el The input element
     * @returns {number} The caret position
     */
    function blestaGetCaret(el) {
        if (el.selectionStart) {
            return el.selectionStart;
        } else if (document.selection) {
            el.focus();

            var r = document.selection.createRange();
            if (r === null) return 0;

            var re = el.createTextRange();
            var rc = re.duplicate();
            re.moveToBookmark(r.getBookmark());
            rc.setEndPoint('EndToStart', re);

            return rc.text.length;
        }
        return 0;
    }

    window.blestaGetCaret = blestaGetCaret;

    /**
     * Get the badge value for a widget
     *
     * @param {HTMLElement} widget The widget element
     */
    function blestaGetWidgetBadge(widget) {
        // Remove any badge displayed for this widget
        var existingBadge = widget.querySelector('.card-header .badge, .card-header strong.badge');
        if (existingBadge) existingBadge.remove();

        // Widget is closed, so fetch badge value
        var cardHeader = widget.querySelector('div.card-header');
        if (cardHeader && cardHeader.classList.contains('close')) {
            var badgeUriInput = widget.querySelector('input[name="badge_uri"]');
            var badgeUri = badgeUriInput ? badgeUriInput.value : null;

            if (badgeUri) {
                blestaRequest('GET', badgeUri, null, function(data) {
                    if (data) {
                        var h2 = widget.querySelector('h2');
                        if (h2) {
                            var badge = document.createElement('strong');
                            badge.className = 'badge badge-danger';
                            badge.textContent = data;
                            h2.appendChild(badge);
                        }
                    }
                });
            }
        }
    }

    window.blestaGetWidgetBadge = blestaGetWidgetBadge;

    /**
     * Hide closed widget content
     *
     * @param {HTMLElement} container The container element
     */
    function blestaHideWidgets(container) {
        container = container || document;
        container.querySelectorAll('.card-header.close').forEach(function(header) {
            var tabContent = header.parentElement.querySelector('.card-content');
            if (tabContent) tabContent.style.display = 'none';
        });
    }

    window.blestaHideWidgets = blestaHideWidgets;

    /**
     * Loads widgets at the specified URL
     *
     * @param {HTMLElement} container The container element
     * @param {Object} options Options including fetch_uri, update_uri, toggle_uri, resize_uri
     */
    function blestaLoadWidgets(container, options) {
        options = options || {};

        if (!options.fetch_uri) return;

        blestaRequest('GET', options.fetch_uri, null, function(widgets) {
            for (var widgetId in widgets) {
                var widgetContainer = document.createElement('div');
                widgetContainer.id = 'widget-container-' + widgetId;
                container.appendChild(widgetContainer);

                (function(wId) {
                    blestaRequest('GET', widgets[wId].uri, null, function(data) {
                        var temp = document.createElement('div');
                        temp.innerHTML = data.content;
                        var widgetEl = temp.firstElementChild;

                        // Set data-width attribute from widget state
                        var width = widgets[wId].width || 'full';
                        widgetEl.setAttribute('data-width', width);

                        // Close the widget if its state was closed
                        if (!widgets[wId].open) {
                            var cardHeader = widgetEl.querySelector('div.card-header:last-of-type');
                            if (cardHeader) cardHeader.classList.add('close');
                            widgetEl.classList.add('collapsed');

                            blestaHideWidgets(widgetEl);
                            var arrowLink = widgetEl.querySelector('div.card-header a.arrow');
                            if (arrowLink) blestaToggleIcons(arrowLink);
                        }

                        // Toggle widget-width icons for half-width widgets
                        if (width === 'half') {
                            var resizeLink = widgetEl.querySelector('div.card-header a.widget-width');
                            if (resizeLink) blestaToggleIcons(resizeLink);
                        }

                        // Get the badge value for this widget
                        blestaGetWidgetBadge(widgetEl);

                        // Append the widget to the page
                        var placeholder = document.getElementById('widget-container-' + wId);
                        if (placeholder) {
                            placeholder.parentNode.replaceChild(widgetEl, placeholder);
                        }
                    });
                })(widgetId);
            }

            // Bind GUI Events to widgets that have loaded
            blestaBindGuiEvents(container, {
                sort_uri: options.update_uri,
                toggle_uri: options.toggle_uri,
                resize_uri: options.resize_uri
            });
        }, null, {
            dataType: 'json'
        });
    }

    window.blestaLoadWidgets = blestaLoadWidgets;

    /**
     * Loads cards at the specified URL
     *
     * @param {HTMLElement} container The container element
     * @param {Object} options Options including fetch_uri
     */
    function blestaLoadCards(container, options) {
        options = options || {};

        if (!options.fetch_uri) return;

        blestaRequest('GET', options.fetch_uri, {
            section: null
        }, function(cards) {
            for (var card in cards) {
                container.insertAdjacentHTML('beforeend', cards[card].value);
            }
        });
    }

    window.blestaLoadCards = blestaLoadCards;

    /**
     * Toggles between two widget icons within the given element
     *
     * @param {HTMLElement} element The element containing icons to toggle
     */
    function blestaToggleIcons(element) {
        element.querySelectorAll('i').forEach(function(icon) {
            if (icon.classList.contains('hidden')) {
                icon.classList.remove('hidden');
            } else {
                icon.classList.add('hidden');
            }
        });
    }

    window.blestaToggleIcons = blestaToggleIcons;

    /**
     * Animate an element's height to show/hide with slide effect
     *
     * @param {HTMLElement} element The element to toggle
     * @param {number} duration Animation duration in milliseconds (default: 400)
     * @param {Function} callback Optional callback after animation completes
     */
    function blestaSlideToggle(element, duration, callback) {
        duration = duration || 400;
        var isHidden = element.style.display === 'none' ||
            getComputedStyle(element).display === 'none';
        var transitionProps = 'height ' + duration + 'ms ease, ' +
            'padding-top ' + duration + 'ms ease, ' +
            'padding-bottom ' + duration + 'ms ease';

        if (isHidden) {
            // Slide down (expand)
            element.style.display = 'block';
            var height = element.scrollHeight;
            var cs = getComputedStyle(element);
            var paddingTop = cs.paddingTop;
            var paddingBottom = cs.paddingBottom;
            element.style.overflow = 'hidden';
            element.style.height = '0';
            element.style.paddingTop = '0';
            element.style.paddingBottom = '0';
            element.style.transition = transitionProps;

            element.addEventListener('transitionend', function handler(e) {
                if (e.propertyName !== 'height') return;
                element.removeEventListener('transitionend', handler);
                element.style.height = '';
                element.style.paddingTop = '';
                element.style.paddingBottom = '';
                element.style.overflow = '';
                element.style.transition = '';
                if (callback) callback(true);
            });

            requestAnimationFrame(function() {
                element.style.height = height + 'px';
                element.style.paddingTop = paddingTop;
                element.style.paddingBottom = paddingBottom;
            });
        } else {
            // Slide up (collapse)
            var height = element.scrollHeight;
            var cs = getComputedStyle(element);
            var paddingTop = cs.paddingTop;
            var paddingBottom = cs.paddingBottom;
            element.style.overflow = 'hidden';
            element.style.height = height + 'px';
            element.style.paddingTop = paddingTop;
            element.style.paddingBottom = paddingBottom;
            element.style.transition = transitionProps;

            element.addEventListener('transitionend', function handler(e) {
                if (e.propertyName !== 'height') return;
                element.removeEventListener('transitionend', handler);
                element.style.display = 'none';
                element.style.height = '';
                element.style.paddingTop = '';
                element.style.paddingBottom = '';
                element.style.overflow = '';
                element.style.transition = '';
                if (callback) callback(false);
            });

            requestAnimationFrame(function() {
                element.style.height = '0';
                element.style.paddingTop = '0';
                element.style.paddingBottom = '0';
            });
        }
    }

    window.blestaSlideToggle = blestaSlideToggle;

    /**
     * Binds the close event action to success, error, and alert messages
     *
     * @param {HTMLElement} container The container element
     */
    function blestaBindCloseMessage(container) {
        container = container || document;

        container.addEventListener('click', function(e) {
            var closeBtn = e.target.closest('.error_section a.close');
            if (!closeBtn) return;

            e.preventDefault();
            var article = closeBtn.parentElement;

            // Animate opacity and height
            article.style.transition = 'opacity 0.4s, height 0.4s';
            article.style.opacity = '0';
            article.style.height = article.offsetHeight + 'px';

            setTimeout(function() {
                article.style.height = '0';
                article.style.overflow = 'hidden';

                setTimeout(function() {
                    article.style.display = 'none';

                    // Hide the entire container if there are no visible elements
                    var errorSection = document.querySelector('.error_section');
                    if (errorSection && !errorSection.querySelector('article:not([style*="display: none"])')) {
                        errorSection.style.display = 'none';
                    }
                }, 400);
            }, 0);
        });
    }

    window.blestaBindCloseMessage = blestaBindCloseMessage;

    /**
     * Binds tooltips using Bootstrap's tooltip component
     *
     * @param {HTMLElement} container The container element
     */
    function blestaBindToolTips(container) {
        container = container || document;

        // Use Bootstrap 5 tooltips
        container.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(function(el) {
            new bootstrap.Tooltip(el);
        });

        // Handle legacy span.tooltip elements
        container.querySelectorAll('span.tooltip').forEach(function(el) {
            var tooltipContent = el.querySelector('div');
            if (tooltipContent) {
                el.setAttribute('data-bs-toggle', 'tooltip');
                el.setAttribute('data-bs-html', 'true');
                el.setAttribute('title', tooltipContent.innerHTML);
                tooltipContent.style.display = 'none';
                new bootstrap.Tooltip(el);
            }
        });
    }

    window.blestaBindToolTips = blestaBindToolTips;

    /**
     * Binds support for the 'generate-password' class using Bootstrap modal
     *
     * @param {HTMLElement} container The container element
     */
    function blestaBindPasswordGenerator(container) {
        container = container || document;

        container.querySelectorAll('.generate-password').forEach(function(element) {
            var baseUrl = element.dataset.baseUrl;
            if (!baseUrl) return;

            var forClass = element.dataset.forClass;
            var length = parseInt(element.dataset.length) || 16;
            var options = element.dataset.options;
            try {
                options = options && typeof options === 'string' ? JSON.parse(options) : {};
            } catch (e) {
                options = {};
            }

            // Never emit angle brackets in generated passwords
            options.exclude = Array.isArray(options.exclude) ? options.exclude : [];
            options.exclude.push({
                chars: [
                    ['<'],
                    ['>']
                ]
            });

            element.addEventListener('click', function(e) {
                e.preventDefault();

                // Fetch the modal content
                blestaRequest('GET', baseUrl + 'dialog/password/', null, function(data) {
                    // Create modal container
                    var modalContainer = document.createElement('div');
                    modalContainer.innerHTML = data;

                    // Find or create modal element
                    var modalEl = modalContainer.querySelector('.modal') || document.createElement('div');
                    if (!modalEl.classList.contains('modal')) {
                        modalEl.className = 'modal fade';
                        modalEl.innerHTML = '<div class="modal-dialog"><div class="modal-content">' + data + '</div></div>';
                    }
                    document.body.appendChild(modalEl);

                    var modal = new bootstrap.Modal(modalEl);

                    // Bind generate button
                    var generateBtn = modalEl.querySelector('.btn.generate');
                    if (generateBtn) {
                        generateBtn.addEventListener('click', function(e) {
                            e.preventDefault();
                            var passwordField = modalEl.querySelector('.modal-password');
                            if (passwordField && typeof window.require !== 'undefined') {
                                var generator = window.require('unicode-passgen');
                                passwordField.value = generator.generate(length, options);
                            } else if (passwordField) {
                                // Fallback password generation
                                passwordField.value = blestaRandomString(length);
                            }
                        });
                    }

                    // Bind cancel button
                    var cancelBtn = modalEl.querySelector('.btn.cancel');
                    if (cancelBtn) {
                        cancelBtn.addEventListener('click', function(e) {
                            e.preventDefault();
                            modal.hide();
                        });
                    }

                    // Bind checkbox to enable save button
                    var checkbox = modalEl.querySelector('.modal-password-copied');
                    var saveBtn = modalEl.querySelector('.btn.save');
                    if (checkbox && saveBtn) {
                        checkbox.addEventListener('change', function() {
                            saveBtn.disabled = !this.checked;
                        });
                    }

                    // Bind save button
                    if (saveBtn) {
                        saveBtn.addEventListener('click', function(e) {
                            e.preventDefault();
                            var password = modalEl.querySelector('.modal-password').value;

                            document.querySelectorAll('.' + forClass).forEach(function(field) {
                                if (field.tagName === 'INPUT') {
                                    field.value = password;
                                } else {
                                    field.textContent = password;
                                }
                            });

                            modal.hide();
                        });
                    }

                    // Clean up modal on hide
                    modalEl.addEventListener('hidden.bs.modal', function() {
                        modalEl.remove();
                    });

                    modal.show();
                });
            });
        });
    }

    window.blestaBindPasswordGenerator = blestaBindPasswordGenerator;

    /**
     * Create a custom toolbar button with Bootstrap Icons for Toast UI Editor
     *
     * @param {string} iconClass The Bootstrap icon class (e.g., 'bi-type-bold')
     * @param {string} ariaLabel The aria-label for accessibility
     * @param {Function} onClick The click handler function
     * @returns {HTMLButtonElement} The toolbar button element
     */
    function createToolbarButton(iconClass, ariaLabel, onClick) {
        var button = document.createElement('button');
        button.className = 'toastui-editor-toolbar-btn';
        button.type = 'button';
        button.setAttribute('aria-label', ariaLabel);

        var icon = document.createElement('i');
        icon.className = 'bi ' + iconClass;
        icon.style.fontSize = '16px';
        icon.style.lineHeight = '1';

        button.appendChild(icon);
        button.addEventListener('click', onClick);

        return button;
    }

    /**
     * Binds support for markdown editor using Toast UI
     *
     * @param {HTMLElement} container The container element
     * @param {Object} options Configuration options
     */
    function blestaBindMarkdownEditor(container, options) {
        container = container || document;
        options = options || {};

        var defaults = {
            autofocus: false,
            usageStatistics: false,
            language: 'en',
            default_view: 'markdown'
        };
        options = Object.assign({}, defaults, options);

        var pageLanguage = document.documentElement.lang;

        container.querySelectorAll('textarea[data-markdown-editor]').forEach(function(textarea) {
            var config = Object.assign({}, options);
            var lang = textarea.getAttribute('lang');

            if (lang && lang.length) {
                config.language = lang;
            } else if (pageLanguage && pageLanguage.length) {
                config.language = pageLanguage;
            }

            // Create a container div for the Toast UI editor
            var editorId = 'toastui-editor-' + Math.random().toString(36).substr(2, 9);
            var editorDiv = document.createElement('div');
            editorDiv.id = editorId;
            textarea.parentNode.insertBefore(editorDiv, textarea.nextSibling);
            textarea.style.display = 'none';

            // Initialize Toast UI Editor
            if (typeof toastui !== 'undefined' && toastui.Editor) {
                var rows = parseInt(textarea.getAttribute('rows')) || 15;
                var height = Math.max(rows * 20, 300) + 'px';

                // Store editor reference for use in toolbar button callbacks
                var editorInstance = null;

                var editor = new toastui.Editor({
                    el: editorDiv,
                    height: height,
                    initialEditType: config.default_view,
                    previewStyle: 'vertical',
                    language: config.language,
                    initialValue: textarea.value,
                    usageStatistics: false,
                    toolbarItems: [
                        [{
                                el: createToolbarButton('bi-type-h1', 'Heading', function() {
                                    if (editorInstance) editorInstance.exec('heading', {
                                        level: 1
                                    });
                                }),
                                tooltip: 'Heading'
                            },
                            {
                                el: createToolbarButton('bi-type-bold', 'Bold', function() {
                                    if (editorInstance) editorInstance.exec('bold');
                                }),
                                tooltip: 'Bold'
                            },
                            {
                                el: createToolbarButton('bi-type-italic', 'Italic', function() {
                                    if (editorInstance) editorInstance.exec('italic');
                                }),
                                tooltip: 'Italic'
                            },
                            {
                                el: createToolbarButton('bi-type-strikethrough', 'Strikethrough', function() {
                                    if (editorInstance) editorInstance.exec('strike');
                                }),
                                tooltip: 'Strikethrough'
                            }
                        ],
                        [{
                                el: createToolbarButton('bi-hr', 'Horizontal Rule', function() {
                                    if (editorInstance) editorInstance.exec('hr');
                                }),
                                tooltip: 'Horizontal Rule'
                            },
                            {
                                el: createToolbarButton('bi-quote', 'Blockquote', function() {
                                    if (editorInstance) editorInstance.exec('blockQuote');
                                }),
                                tooltip: 'Blockquote'
                            }
                        ],
                        [{
                                el: createToolbarButton('bi-list-ul', 'Bullet List', function() {
                                    if (editorInstance) editorInstance.exec('bulletList');
                                }),
                                tooltip: 'Bullet List'
                            },
                            {
                                el: createToolbarButton('bi-list-ol', 'Numbered List', function() {
                                    if (editorInstance) editorInstance.exec('orderedList');
                                }),
                                tooltip: 'Numbered List'
                            },
                            {
                                el: createToolbarButton('bi-list-task', 'Task List', function() {
                                    if (editorInstance) editorInstance.exec('taskList');
                                }),
                                tooltip: 'Task List'
                            }
                        ],
                        [{
                                el: createToolbarButton('bi-table', 'Insert Table', function() {
                                    if (editorInstance) {
                                        // Insert a default 2x2 table
                                        var tableMarkdown = '\n| Header 1 | Header 2 |\n| --- | --- |\n| Cell 1 | Cell 2 |\n| Cell 3 | Cell 4 |\n';
                                        var currentContent = editorInstance.getMarkdown();
                                        editorInstance.setMarkdown(currentContent + tableMarkdown);
                                    }
                                }),
                                tooltip: 'Insert Table'
                            },
                            {
                                el: createToolbarButton('bi-link-45deg', 'Insert Link', function() {
                                    if (editorInstance) {
                                        var selectedText = window.getSelection().toString();
                                        var linkText = selectedText || 'link text';
                                        var url = prompt('Enter URL:', 'https://');
                                        if (url) {
                                            editorInstance.exec('addLink', {
                                                linkText: linkText,
                                                linkUrl: url
                                            });
                                        }
                                    }
                                }),
                                tooltip: 'Insert Link'
                            },
                            {
                                el: createToolbarButton('bi-image', 'Insert Image', function() {
                                    if (editorInstance) {
                                        var url = prompt('Enter image URL:', 'https://');
                                        var altText = prompt('Enter image description (alt text):', 'Image');
                                        if (url) {
                                            editorInstance.exec('addImage', {
                                                imageUrl: url,
                                                altText: altText || 'Image'
                                            });
                                        }
                                    }
                                }),
                                tooltip: 'Insert Image'
                            }
                        ],
                        [{
                                el: createToolbarButton('bi-code', 'Inline Code', function() {
                                    if (editorInstance) editorInstance.exec('code');
                                }),
                                tooltip: 'Inline Code'
                            },
                            {
                                el: createToolbarButton('bi-code-square', 'Code Block', function() {
                                    if (editorInstance) editorInstance.exec('codeBlock');
                                }),
                                tooltip: 'Code Block'
                            }
                        ],
                        [{
                            el: createToolbarButton('bi-eye', 'Toggle Preview', function() {
                                if (editorInstance) {
                                    if (editorDiv._previewVisible) {
                                        editorInstance.changePreviewStyle('tab');
                                        editorDiv._previewVisible = false;
                                    } else {
                                        editorInstance.changePreviewStyle('vertical');
                                        editorDiv._previewVisible = true;
                                    }
                                }
                            }),
                            tooltip: 'Toggle Markdown Preview'
                        }]
                    ]
                });

                // Store editor instance for toolbar button callbacks
                editorInstance = editor;

                // Track preview state
                editorDiv._previewVisible = true;

                // Update textarea value when editor content changes
                editor.on('change', function() {
                    textarea.value = editor.getMarkdown();
                });

                // Store editor instance on the div for potential future access
                editorDiv._editor = editor;
            }
        });
    }

    window.blestaBindMarkdownEditor = blestaBindMarkdownEditor;

    /**
     * Binds support for CKEditor 5 WYSIWYG editor
     *
     * @param {HTMLElement|string} element The element(s) to convert
     * @param {Object} options Configuration options
     */
    function blestaBindWysiwygEditor(element, options) {
        var defaults = {
            licenseKey: 'GPL',
            toolbar: [
                'heading', 'fontFamily', 'fontSize', 'highlight', 'emoji', '|',
                'fontColor', 'fontBackgroundColor', 'bold', 'italic', 'link',
                'removeFormat', 'bulletedList', 'numberedList', '|',
                'alignment', 'indent', 'outdent', 'horizontalLine', 'code', '|',
                'imageUpload', 'blockQuote', 'insertTable', 'mediaEmbed',
                'codeBlock', 'htmlEmbed', 'sourceEditing', 'undo', 'redo'
            ],
            language: 'en',
            image: {
                toolbar: [
                    'imageTextAlternative',
                    'imageStyle:block',
                    'imageStyle:side'
                ]
            }
        };
        options = Object.assign({}, defaults, options);

        var elements = typeof element === 'string' ?
            document.querySelectorAll(element) : [element];

        var promises = [];
        elements.forEach(function(el) {
            if (typeof ClassicEditor !== 'undefined') {
                var promise = ClassicEditor.create(el, options).then(function(editor) {
                    el.ckeditorInstance = editor;
                    return {
                        element: el,
                        editor: editor
                    };
                });
                promises.push(promise);
            }
        });

        // Return a promise that resolves with the first editor result (for single element use)
        // or rejects if no editors were created
        if (promises.length === 0) {
            return Promise.resolve(null);
        }

        return promises.length === 1 ? promises[0] : Promise.all(promises).then(function(results) {
            return results[0];
        });
    }

    window.blestaBindWysiwygEditor = blestaBindWysiwygEditor;

    /**
     * Decodes URL-encoded template tags inside href attributes.
     *
     * CKEditor's link model percent-encodes { and } only inside href values,
     * which corrupts H2O template tags placed inside link URLs. This restores
     * them. Scoped to href="..." attributes only to avoid corrupting
     * legitimate percent-encoded URLs elsewhere in the HTML.
     *
     * @param {string} html HTML content potentially containing encoded tags
     * @return {string} HTML with decoded template tags in href attributes
     */
    function blestaDecodeHrefTemplateTags(html) {
        return html.replace(/(href\s*=\s*")([^"]*?)(")/gi, function(match, pre, url, post) {
            return pre + url.replace(/%7B/gi, '{').replace(/%7D/gi, '}') + post;
        });
    }

    window.blestaDecodeHrefTemplateTags = blestaDecodeHrefTemplateTags;

    /**
     * Sets quicklinks for staff members
     *
     * @param {HTMLElement} container The container element
     */
    function blestaBindQuickLinks(container) {
        container = container || document;

        var quicklink = container.querySelector('#quicklink') || document.getElementById('quicklink');
        if (!quicklink) return;

        quicklink.addEventListener('click', function(e) {
            e.preventDefault();

            var icon = this.querySelector('i');
            var action = icon && icon.classList.contains('far') ? 'add' : 'remove';

            var params = {
                action: action,
                title: document.title.split('|')[0],
                uri: window.location.pathname + window.location.search
            };

            blestaRequest('POST', this.getAttribute('href'), params, function(data) {
                if (data.added) {
                    icon.classList.remove('far');
                    icon.classList.add('fas');
                } else {
                    icon.classList.remove('fas');
                    icon.classList.add('far');
                }
            }, null, {
                dataType: 'json'
            });
        });
    }

    window.blestaBindQuickLinks = blestaBindQuickLinks;

    /**
     * Binds date pickers to date text fields using native date input
     *
     * @param {HTMLElement} container The container element
     */
    function blestaBindDatePicker(container) {
        container = container || document;

        container.querySelectorAll('input.date').forEach(function(input) {
            // Check if already wrapped
            if (input.parentElement.classList.contains('date_group')) return;

            // Create wrapper
            var wrapper = document.createElement('div');
            wrapper.className = 'date_group';
            input.parentNode.insertBefore(wrapper, input);
            wrapper.appendChild(input);

            // Convert to date input type if browser supports it
            if (input.type !== 'date') {
                input.type = 'date';
            }
        });
    }

    window.blestaBindDatePicker = blestaBindDatePicker;

    /**
     * Binds drop zone to file fields using native drag and drop
     *
     * Files added by drag and drop or by browsing are added to the field's
     * current set of files rather than replacing them, and each file may be
     * removed individually before the form is submitted.
     *
     * Optional attributes on the file field:
     * - rel: The drop zone message text
     * - data-browse: The browse button text
     * - data-remove: The remove link title text
     *
     * @param {HTMLElement} container The container element
     */
    function blestaBindDropZone(container) {
        container = container || document;

        container.querySelectorAll('.drag-drop').forEach(function(field) {
            // Only bind each field once
            if (field.dataset.dropzoneBound) {
                return;
            }
            field.dataset.dropzoneBound = 'true';

            var removeText = field.getAttribute('data-remove') || 'Remove File';

            // Use the view's own upload UI if the field is placed within one,
            // otherwise build the standard upload UI
            var dropTarget = field.closest('.file-upload-compact');
            if (!dropTarget) {
                var parent = field.parentElement;

                dropTarget = document.createElement('div');
                dropTarget.className = 'file-upload-compact';

                var uploadWrapper = document.createElement('div');
                uploadWrapper.className = 'd-flex align-items-center gap-3 dz-message';

                var icon = document.createElement('i');
                icon.className = 'bi bi-cloud-upload upload-icon';
                uploadWrapper.appendChild(icon);

                var textContainer = document.createElement('div');
                textContainer.className = 'flex-grow-1';
                var textDiv = document.createElement('div');
                textDiv.className = 'upload-text';
                textDiv.textContent = field.getAttribute('rel') ||
                    'Drop files here to upload or Click to select files';
                textContainer.appendChild(textDiv);
                uploadWrapper.appendChild(textContainer);

                var browseBtn = document.createElement('button');
                browseBtn.type = 'button';
                browseBtn.className = 'btn btn-outline-primary btn-sm';
                browseBtn.textContent = field.getAttribute('data-browse') || 'Browse Files';
                browseBtn.addEventListener('click', function() {
                    field.click();
                });
                uploadWrapper.appendChild(browseBtn);

                parent.insertBefore(dropTarget, field);
                dropTarget.appendChild(field);
                dropTarget.appendChild(uploadWrapper);

                // Hide original input
                field.style.display = 'none';
            }

            // Create preview zone
            var previewZone = document.createElement('div');
            previewZone.className = 'dropzone-previews d-flex flex-wrap gap-2 mt-2';
            dropTarget.insertAdjacentElement('afterend', previewZone);

            // Accumulate files across selections so that new files are added
            // to, rather than replace, the current set
            var store = new DataTransfer();

            function addFiles(files) {
                if (!field.multiple) {
                    // A field that does not accept multiple files keeps only
                    // the most recent selection
                    store = new DataTransfer();
                    if (files[0]) {
                        store.items.add(files[0]);
                    }
                } else {
                    Array.from(files).forEach(function(file) {
                        var duplicate = Array.from(store.files).some(function(existing) {
                            return existing.name === file.name &&
                                existing.size === file.size &&
                                existing.lastModified === file.lastModified;
                        });
                        if (!duplicate) {
                            store.items.add(file);
                        }
                    });
                }

                field.files = store.files;
                renderPreviews();
            }

            function renderPreviews() {
                previewZone.innerHTML = '';

                Array.from(store.files).forEach(function(file, index) {
                    var preview = document.createElement('span');
                    preview.className = 'dz-preview badge bg-secondary d-flex align-items-center gap-1';

                    var icon = document.createElement('i');
                    icon.className = 'bi bi-paperclip';
                    preview.appendChild(icon);

                    var filename = document.createElement('span');
                    filename.className = 'dz-filename';
                    filename.textContent = file.name;
                    preview.appendChild(filename);

                    var remove = document.createElement('a');
                    remove.href = '#';
                    remove.className = 'dz-remove text-reset';
                    remove.title = removeText;
                    remove.setAttribute('aria-label', removeText);
                    remove.innerHTML = '<i class="bi bi-x-lg"></i>';
                    remove.addEventListener('click', function(e) {
                        e.preventDefault();
                        store.items.remove(index);
                        field.files = store.files;
                        renderPreviews();
                    });
                    preview.appendChild(remove);

                    previewZone.appendChild(preview);
                });
            }

            // Handle click to browse, ignoring clicks on interactive elements
            dropTarget.addEventListener('click', function(e) {
                if (!e.target.closest('a, button, input, select, textarea, label')) {
                    field.click();
                }
            });

            // Handle file selection via the browse dialog
            field.addEventListener('change', function() {
                addFiles(this.files);
            });

            // Handle drag and drop
            dropTarget.addEventListener('dragover', function(e) {
                e.preventDefault();
                dropTarget.classList.add('drag-over');
            });

            dropTarget.addEventListener('dragleave', function() {
                dropTarget.classList.remove('drag-over');
            });

            dropTarget.addEventListener('drop', function(e) {
                e.preventDefault();
                dropTarget.classList.remove('drag-over');
                addFiles(e.dataTransfer.files);
            });
        });
    }

    window.blestaBindDropZone = blestaBindDropZone;

    /**
     * Generates a random string
     *
     * @param {number} length The length of the string
     * @param {string} pool The character pool to use
     * @returns {string} The random string
     */
    function blestaRandomString(length, pool) {
        var str = '';
        pool = pool || 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';

        for (var i = 0; i < length; i++) {
            str += pool.charAt(Math.floor(Math.random() * pool.length));
        }
        return str;
    }

    window.blestaRandomString = blestaRandomString;

    /**
     * Creates or updates a tag in the document head
     *
     * @param {string} tag The tag name
     * @param {Object} attributes The tag attributes
     */
    function blestaSetHeadTag(tag, attributes) {
        if (attributes.id) {
            var existing = document.head.querySelector('#' + attributes.id);
            if (existing) {
                for (var attr in attributes) {
                    existing.setAttribute(attr, attributes[attr]);
                }
                return;
            }
        }

        var element = document.createElement(tag);
        for (var attr in attributes) {
            element.setAttribute(attr, attributes[attr]);
        }
        document.head.appendChild(element);
    }

    window.blestaSetHeadTag = blestaSetHeadTag;

    /**
     * Adds click functionality and content toggling for tabbed content
     *
     * @param {HTMLElement|string} container The container element or selector
     */
    function blestaTabbedContent(container) {
        var containers = typeof container === 'string' ?
            document.querySelectorAll(container) : [container];

        containers.forEach(function(cont) {
            // Find the active tab
            var currentLi = cont.querySelector('ul li.current');
            var allLis = cont.querySelectorAll('ul > li');
            var index = Array.from(allLis).indexOf(currentLi);
            if (index === -1) index = 0;

            // Hide all tabs except the active tab
            var contentDivs = cont.querySelectorAll('.inner_content > div');
            contentDivs.forEach(function(div, i) {
                div.style.display = i === index ? '' : 'none';
            });

            // Handle tab click
            cont.querySelectorAll('ul > li > a').forEach(function(link) {
                link.addEventListener('click', function(e) {
                    e.preventDefault();

                    var clickedLi = this.closest('li');
                    var siblings = clickedLi.parentElement.children;
                    var clickedIndex = Array.from(siblings).indexOf(clickedLi);

                    // Update active class
                    Array.from(siblings).forEach(function(li) {
                        li.classList.remove('current');
                    });
                    clickedLi.classList.add('current');

                    // Show/hide content
                    contentDivs.forEach(function(div, i) {
                        div.style.display = i === clickedIndex ? '' : 'none';
                    });
                });
            });
        });
    }

    window.blestaTabbedContent = blestaTabbedContent;

    /**
     * Toggles a More/Less content section
     *
     * @param {string} clickableTag Selector for the clickable element
     * @param {string} container Selector for the container to toggle
     * @param {string} openText Text when container is open
     * @param {string} closedText Text when container is closed
     */
    function blestaBindToggleEvent(clickableTag, container, openText, closedText) {
        document.addEventListener('click', function(e) {
            var target = e.target.closest(clickableTag);
            if (!target) return;

            e.preventDefault();

            var containerEl = document.querySelector(container);
            if (!containerEl) return;

            // Toggle visibility
            if (containerEl.classList.contains('show')) {
                containerEl.classList.add('hidden');
                containerEl.classList.remove('show');
            } else if (containerEl.classList.contains('hidden')) {
                containerEl.classList.add('show');
                containerEl.classList.remove('hidden');
            } else {
                containerEl.style.display = containerEl.style.display === 'none' ? '' : 'none';
            }

            var icon = target.querySelector('i.fas, i.bi');

            if (target.classList.contains('show_content')) {
                target.classList.remove('show_content');
                target.classList.add('hide_content');
                if (icon) {
                    icon.classList.remove('fa-chevron-down', 'bi-chevron-down');
                    icon.classList.add('fa-chevron-up', 'bi-chevron-up');
                }
                if (closedText !== undefined) {
                    var iconClone = icon ? icon.cloneNode(true) : null;
                    target.textContent = ' ' + closedText;
                    if (iconClone) target.insertBefore(iconClone, target.firstChild);
                }
            } else {
                target.classList.remove('hide_content');
                target.classList.add('show_content');
                if (icon) {
                    icon.classList.remove('fa-chevron-up', 'bi-chevron-up');
                    icon.classList.add('fa-chevron-down', 'bi-chevron-down');
                }
                if (openText !== undefined) {
                    var iconClone = icon ? icon.cloneNode(true) : null;
                    target.textContent = ' ' + openText;
                    if (iconClone) target.insertBefore(iconClone, target.firstChild);
                }
            }
        });
    }

    window.blestaBindToggleEvent = blestaBindToggleEvent;

    /**
     * Sorts an object containing key/value pairs by its value
     *
     * @param {Object} obj The object to sort
     * @returns {Array} Sorted array of objects with key and value properties
     */
    function blestaSortObject(obj) {
        var sorted = [];

        for (var item in obj) {
            if (obj.hasOwnProperty(item)) {
                sorted.push({
                    key: item.toString(),
                    value: obj[item]
                });
            }
        }

        return sorted.sort(function(a, b) {
            return a.value.toLowerCase().localeCompare(b.value.toLowerCase());
        });
    }

    window.blestaSortObject = blestaSortObject;

    /**
     * Prevents the designated forms from being submitted multiple times
     *
     * @param {HTMLElement} container The container element
     */
    function blestaBindPreventDoubleSubmission(container) {
        container = container || document;

        // Find all forms with disable-on-submit class and bind directly to each
        var forms = container.querySelectorAll ?
            container.querySelectorAll('form.disable-on-submit') :
            document.querySelectorAll('form.disable-on-submit');

        forms.forEach(function(form) {
            // Skip if already bound
            if (form.dataset.doubleSubmitBound === 'true') return;
            form.dataset.doubleSubmitBound = 'true';

            form.addEventListener('submit', function(e) {
                // If already submitting, prevent duplicate submission
                if (this.dataset.submitting === 'true') {
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    return false;
                }

                // Mark as submitting
                this.dataset.submitting = 'true';

                // Disable all submit buttons after a tiny delay to allow form submission to start
                var formEl = this;
                setTimeout(function() {
                    formEl.querySelectorAll('input[type="submit"], button[type="submit"]').forEach(function(btn) {
                        btn.disabled = true;
                        btn.classList.add('disabled');
                    });
                }, 0);
            }, true); // Capture phase
        });
    }

    window.blestaBindPreventDoubleSubmission = blestaBindPreventDoubleSubmission;

    /**
     * Prevent the given form from being submitted multiple times
     *
     * @param {HTMLElement} form The form element
     * @returns {boolean} True if form can be submitted, false if already submitted
     */
    function blestaDisableFormSubmission(form) {
        if (form.dataset.submitted === 'true') {
            return false;
        }

        form.dataset.submitted = 'true';

        form.querySelectorAll('input[type="submit"], button[type="submit"]').forEach(function(btn) {
            btn.classList.add('disabled');
            btn.disabled = true;
        });

        return true;
    }

    window.blestaDisableFormSubmission = blestaDisableFormSubmission;

    /**
     * Enables submission for the given form
     *
     * @param {HTMLElement} form The form element
     */
    function blestaEnableFormSubmission(form) {
        form.dataset.submitted = 'false';

        form.querySelectorAll('input[type="submit"], button[type="submit"]').forEach(function(btn) {
            btn.classList.remove('disabled');
            btn.disabled = false;
        });
    }

    window.blestaEnableFormSubmission = blestaEnableFormSubmission;

    /**
     * Push state to browser history
     *
     * @param {string} box The box selector
     * @param {string} url The URL to push
     * @returns {boolean} True if navigation should continue, false if handled
     */
    function blestaPushState(box, url) {
        if (window.history && window.history.pushState) {
            try {
                window.history.pushState({
                    box: box
                }, document.title, url);
                return false;
            } catch (err) {
                return true;
            }
        }
        return true;
    }

    window.blestaPushState = blestaPushState;

    /**
     * Binds GUI events for widgets and other interactive elements
     *
     * @param {HTMLElement} container The container element
     * @param {Object} options Options including sort_uri, toggle_uri, resize_uri
     */
    function blestaBindGuiEvents(container, options) {
        container = container || document;
        options = options || {};

        // Allow sorting boxes with Sortable.js
        if (options.sort_uri) {
            var grid = container.querySelector('.dashboard-grid') ||
                document.querySelector('.dashboard-grid');

            // If no dashboard-grid found, check if container itself is a widget container (e.g., client profile)
            if (!grid && container.classList && container.classList.contains('column')) {
                grid = container;
            }
            if (grid && typeof Sortable !== 'undefined') {
                new Sortable(grid, {
                    animation: 200,
                    handle: '.card-header',
                    ghostClass: 'sortable-ghost',
                    chosenClass: 'sortable-chosen',
                    dragClass: 'sortable-drag',
                    easing: 'cubic-bezier(0.4, 0, 0.2, 1)',
                    onEnd: function() {
                        var widgetData = [];
                        grid.querySelectorAll('section, .card').forEach(function(card, index) {
                            var id = card.getAttribute('id');
                            var width = card.getAttribute('data-width') || 'full';
                            var column = width === 'half' ? index % 2 : null;

                            if (id) {
                                widgetData.push({
                                    id: id,
                                    width: width,
                                    column: column,
                                    order: index
                                });
                            }
                        });

                        blestaRequest('POST', options.sort_uri, {
                            widget: widgetData
                        });
                    }
                });
            }
        }

        // Cursor style for card headers
        container.querySelectorAll('.card-header').forEach(function(header) {
            header.addEventListener('mouseenter', function() {
                this.style.cursor = 'move';
            });
        });

        // Minimize/expand boxes
        container.addEventListener('click', function(e) {
            var arrowBtn = e.target.closest('.card-header .widget-controls a.arrow');
            if (!arrowBtn) return;

            e.preventDefault();

            var header = arrowBtn.closest('div.card-header');
            var card = arrowBtn.closest('.card');
            var tabContent = header.parentElement.querySelector('.card-content');

            if (!tabContent) return;

            var isCurrentlyClosed = card.classList.contains('collapsed');

            if (isCurrentlyClosed) {
                card.classList.remove('collapsed');
                tabContent.style.display = 'none';
            }

            blestaSlideToggle(tabContent, 400, function(isNowOpen) {
                if (isNowOpen) {
                    header.classList.remove('close');
                } else {
                    header.classList.add('close');
                    card.classList.add('collapsed');
                }

                blestaToggleIcons(arrowBtn);

                if (options.toggle_uri) {
                    blestaRequest('POST', options.toggle_uri, header.parentElement.id + '=' + isNowOpen);
                    blestaGetWidgetBadge(header.parentElement);
                }
            });
        });

        // Toggle full screen
        container.addEventListener('click', function(e) {
            var fullScreenBtn = e.target.closest('a.full_screen');
            if (!fullScreenBtn) return;

            e.preventDefault();

            var card = fullScreenBtn.closest('div.card-header').parentElement;
            card.classList.toggle('full-screen');
            blestaToggleIcons(fullScreenBtn);
        });

        // Widget resize button
        container.addEventListener('click', function(e) {
            var resizeBtn = e.target.closest('.card-header .widget-controls a.widget-width');
            if (!resizeBtn) return;

            e.preventDefault();

            var card = resizeBtn.closest('.card');
            var currentWidth = card.getAttribute('data-width') || 'full';
            var newWidth = currentWidth === 'full' ? 'half' : 'full';
            var id = card.getAttribute('id');

            card.setAttribute('data-width', newWidth);
            blestaToggleIcons(resizeBtn);

            if (options.resize_uri && id) {
                blestaRequest('POST', options.resize_uri, {
                    widget_id: id,
                    width: newWidth
                });
            }
        });
    }

    window.blestaBindGuiEvents = blestaBindGuiEvents;

    /**
     * Binds global GUI events
     *
     * @param {HTMLElement} container The container element
     * @param {Object} options Options
     */
    function blestaBindGlobalGuiEvents(container, options) {
        container = container || document;
        options = options || {};

        // Hide closed widgets
        blestaHideWidgets(container);

        // Close error, success, alert messages
        blestaBindCloseMessage(container);

        // Bind prevention for form double submits
        blestaBindPreventDoubleSubmission(container);

        // Submit forms using button link
        document.addEventListener('click', function(e) {
            var submitLink = e.target.closest('a.submit');
            if (!submitLink) return;

            e.preventDefault();
            var form = submitLink.closest('form');
            if (form) form.submit();
        });

        // Prevent clicks on links/inputs/selects inside expand rows from triggering row toggle
        document.addEventListener('click', function(e) {
            if (e.target.closest('tr.expand a') ||
                e.target.closest('tr.expand input') ||
                e.target.closest('tr.expand select')) {
                e.stopPropagation();
            }
        });

        // Handle tooltips
        blestaBindToolTips(container);

        // Handle password generation
        blestaBindPasswordGenerator(container);

        // Handle markdown editor
        blestaBindMarkdownEditor(container);

        // Date picker
        blestaBindDatePicker(container);

        // Drop zone for file fields
        blestaBindDropZone(container);

        // Handle History API state changes
        if (window.history && window.history.pushState) {
            window.addEventListener('popstate', function(e) {
                var state = e.state;
                if (!state || !state.box) return;

                blestaRequest('GET', window.location.href, null, function(data) {
                    var box = document.querySelector(state.box);
                    if (!box) return;

                    if (data.replacer == null) {
                        box.innerHTML = data.content;
                        blestaBindToolTips(box);
                        blestaBindPasswordGenerator(box);
                        blestaBindMarkdownEditor(box);
                    } else {
                        var replacer = box.querySelector(data.replacer);
                        if (replacer) {
                            replacer.innerHTML = data.content;
                            blestaBindToolTips(replacer);
                            blestaBindPasswordGenerator(replacer);
                            blestaBindMarkdownEditor(replacer);
                        }
                    }

                    if (data.message) {
                        var rightContainer = document.getElementById('right_container');
                        if (rightContainer) {
                            rightContainer.insertAdjacentHTML('afterbegin', data.message);
                        }
                    }

                    blestaBindDatePicker(container);
                    blestaBindDropZone(container);
                }, null, {
                    dataType: 'json'
                });
            });
        }

        // Handle AJAX link requests in widgets
        // Use capture phase (true) to run before jQuery handlers which use bubbling
        document.addEventListener('click', function(e) {
            var ajaxLink = e.target.closest('a.ajax');
            if (!ajaxLink) return;

            var parentBox = ajaxLink.closest('section.card');
            if (!parentBox) return;

            // If this widget has AJAX filtering, let the filter handler in widget.php manage it
            // We still prevent default and stop propagation so only the filter handler runs
            var filterForm = parentBox.querySelector('form.filter-section-form');
            if (filterForm) {
                e.preventDefault();
                // Don't call stopPropagation - let the filter click interceptor handle this
                return;
            }
            // Stop event from reaching jQuery handlers that may interfere
            e.preventDefault();
            e.stopPropagation();

            var url = ajaxLink.getAttribute('href');
            blestaPushState('#' + parentBox.getAttribute('id'), url);

            // Fetch and update widget content
            blestaRequest('GET', url, null, function(data) {
                var target = parentBox;

                // Parse the response content
                var temp = document.createElement('div');
                temp.innerHTML = data.content;

                if (data.replacer == null) {
                    // No specific replacer, replace entire box with parsed HTML
                    if (temp.children.length === 1) {
                        target = temp.children[0];
                        parentBox.replaceWith(target);
                    } else {
                        parentBox.innerHTML = data.content;
                    }
                } else {
                    // Replace specific element within the box
                    var replacer = parentBox.querySelector(data.replacer);
                    if (replacer) {
                        // Response content includes the wrapper element, so replace it entirely
                        if (temp.children.length === 1) {
                            target = temp.children[0];
                            replacer.replaceWith(target);
                        } else {
                            replacer.innerHTML = data.content;
                            target = replacer;
                        }
                    }
                }

                blestaBindToolTips(target);
                blestaBindPasswordGenerator(target);
                blestaBindMarkdownEditor(target);
                blestaBindDatePicker(target);
                blestaBindDropZone(target);

                if (typeof blestaModalConfirm === 'function') {
                    target.querySelectorAll('.modal-confirm-delete').forEach(function(el) {
                        blestaModalConfirm(el, {
                            title: 'Confirm Delete',
                            confirmText: 'Delete',
                            cancelText: 'Cancel',
                            submit: true
                        });
                    });
                    target.querySelectorAll('.modal-confirm-warning').forEach(function(el) {
                        blestaModalConfirm(el, {
                            title: 'Warning',
                            confirmText: 'Confirm',
                            cancelText: 'Cancel',
                            submit: true
                        });
                    });
                    target.querySelectorAll('.modal-confirm-success').forEach(function(el) {
                        blestaModalConfirm(el, {
                            title: 'Confirm',
                            confirmText: 'Confirm',
                            cancelText: 'Cancel',
                            submit: true
                        });
                    });
                }

                // Re-execute inline scripts from AJAX-loaded content
                target.querySelectorAll('script').forEach(function(oldScript) {
                    var newScript = document.createElement('script');
                    Array.from(oldScript.attributes).forEach(function(attr) {
                        newScript.setAttribute(attr.name, attr.value);
                    });
                    newScript.textContent = oldScript.textContent;
                    oldScript.parentNode.replaceChild(newScript, oldScript);
                });

                if (data.message) {
                    var rightContainer = document.getElementById('right_container');
                    if (rightContainer) {
                        rightContainer.insertAdjacentHTML('afterbegin', data.message);
                    }
                }
            }, null, {
                dataType: 'json'
            });
        }, true);

        // Escape key to remove full screen
        document.addEventListener('keyup', function(e) {
            if (e.keyCode === 27) {
                document.querySelectorAll('section.full_screen').forEach(function(section) {
                    section.classList.remove('full_screen');
                    blestaToggleIcons(section.querySelector('a'));
                });
            }
        });

        // Primary navigation hover behavior
        var navIsOpen = function() {
            return document.querySelector('.nav > li.open') !== null;
        };

        var closeNav = function() {
            document.querySelectorAll('.nav > li.open').forEach(function(li) {
                li.classList.remove('open');
            });
            highlightNav();
        };

        var openNav = function(element) {
            element.classList.add('open');
            unhighlightNav();
        };

        var highlightNav = function() {
            document.querySelectorAll('.nav > li.current').forEach(function(li) {
                li.classList.add('active');
                li.classList.remove('current');
            });
        };

        var unhighlightNav = function() {
            document.querySelectorAll('.nav > li.active').forEach(function(li) {
                li.classList.add('current');
                li.classList.remove('active');
            });
        };

        document.querySelectorAll('.nav > li').forEach(function(li) {
            li.addEventListener('mouseenter', function() {
                if (navIsOpen()) {
                    closeNav();
                    openNav(this);
                } else {
                    unhighlightNav();
                }
            });

            li.addEventListener('mouseleave', function() {
                if (!navIsOpen()) {
                    highlightNav();
                }
            });
        });

        document.body.addEventListener('click', function() {
            closeNav();
        });

        // Bind confirmation modals
        blestaModalConfirm('.modal-confirm-delete', {
            title: 'Confirm Delete',
            confirmText: 'Delete',
            cancelText: 'Cancel',
            submit: true
        });

        blestaModalConfirm('.modal-confirm-warning', {
            title: 'Warning',
            confirmText: 'Confirm',
            cancelText: 'Cancel',
            submit: true
        });

        blestaModalConfirm('.modal-confirm-success', {
            title: 'Confirm',
            confirmText: 'Confirm',
            cancelText: 'Cancel',
            submit: true
        });
    }

    window.blestaBindGlobalGuiEvents = blestaBindGlobalGuiEvents;

    /**
     * Prepares modals for confirmation dialogs using Bootstrap modal
     *
     * @param {HTMLElement|string} element The element(s) to bind
     * @param {Object} options Options including title, confirmText, cancelText, submit, form
     */
    function blestaModalConfirm(element, options) {
        options = options || {};

        var defaults = {
            title: 'Confirm',
            confirmText: 'Confirm',
            cancelText: 'Cancel',
            submit: false,
            form: null
        };
        options = Object.assign({}, defaults, options);

        var elements = typeof element === 'string' ?
            document.querySelectorAll(element) : [element];

        elements.forEach(function(el) {
            el.addEventListener('click', function(e) {
                e.preventDefault();

                // Get message from data attribute or rel (fallback for backwards compatibility)
                var message = el.getAttribute('data-confirm-message') || el.getAttribute('rel') || '';
                var title = el.getAttribute('data-confirm-title') || options.title;
                var confirmBtnText = el.getAttribute('data-confirm-button') || options.confirmText;
                var isDelete = el.classList.contains('modal-confirm-delete');
                var isSuccess = el.classList.contains('modal-confirm-success');

                // Determine button style based on type
                var btnClass = isDelete ? 'btn-danger' : (isSuccess ? 'btn-success' : 'btn-warning');
                var iconClass = isDelete ? 'bi-exclamation-triangle-fill text-danger' : (isSuccess ? 'bi-check-circle-fill text-success' : 'bi-exclamation-triangle-fill text-warning');

                // Create modal HTML following blesta-admin patterns
                var modalEl = document.createElement('div');
                modalEl.className = 'modal fade';
                modalEl.setAttribute('tabindex', '-1');
                modalEl.innerHTML =
                    '<div class="modal-dialog modal-dialog-centered">' +
                    '<div class="modal-content">' +
                    '<div class="modal-header border-0 pb-0">' +
                    '<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>' +
                    '</div>' +
                    '<div class="modal-body text-center py-4">' +
                    '<div class="mb-3"><i class="bi ' + iconClass + '" style="font-size: 4rem;"></i></div>' +
                    '<h5 class="modal-title mb-3">' + title + '</h5>' +
                    '<p class="text-secondary">' + message + '</p>' +
                    '</div>' +
                    '<div class="modal-footer border-0 justify-content-center">' +
                    '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">' + options.cancelText + '</button>' +
                    '<button type="button" class="btn ' + btnClass + ' btn-confirm">' + confirmBtnText + '</button>' +
                    '</div>' +
                    '</div>' +
                    '</div>';

                document.body.appendChild(modalEl);
                var modal = new bootstrap.Modal(modalEl);
                var confirmed = false;

                // Handle confirm button
                modalEl.querySelector('.btn-confirm').addEventListener('click', function() {
                    confirmed = true;
                    this.blur(); // Remove focus before hiding to prevent aria-hidden conflict
                    modal.hide();
                });

                // Handle action after modal is fully hidden
                modalEl.addEventListener('hidden.bs.modal', function() {
                    modalEl.remove();

                    if (confirmed) {
                        if (options.submit) {
                            // Try multiple methods to find the form
                            var form = options.form ||
                                el.closest('form') ||
                                (el.getAttribute('data-form') && document.getElementById(el.getAttribute('data-form'))) ||
                                (el.getAttribute('form') && document.getElementById(el.getAttribute('form')));
                            if (form) form.submit();
                        } else if (el.getAttribute('href') && el.getAttribute('href') !== '#') {
                            window.location = el.getAttribute('href');
                        }
                    }
                });

                modal.show();
            });
        });
    }

    window.blestaModalConfirm = blestaModalConfirm;

    /**
     * Prepares modals using Bootstrap modal
     *
     * @param {HTMLElement|string} element The element(s) to bind
     * @param {Object} options Options including title, close, url, data, text, onShow, onHide
     */
    function blestaModal(element, options) {
        options = options || {};

        var defaults = {
            title: null,
            close: 'Close',
            url: null,
            data: {},
            text: '',
            onShow: function() {},
            onHide: function() {},
            onRender: function() {},
            open: false
        };
        options = Object.assign({}, defaults, options);

        var elements = typeof element === 'string' ?
            document.querySelectorAll(element) : [element];

        elements.forEach(function(el) {
            var showModal = function() {
                // Create modal
                var modalEl = document.createElement('div');
                modalEl.className = 'modal fade';
                modalEl.setAttribute('tabindex', '-1');
                modalEl.innerHTML = '<div class="modal-dialog modal-dialog-centered"><div class="modal-content">' +
                    '<div class="modal-header"><h5 class="modal-title">' + (options.title || el.textContent) + '</h5>' +
                    '<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button></div>' +
                    '<div class="modal-body">' + options.text + '</div></div></div>';

                document.body.appendChild(modalEl);
                var modal = new bootstrap.Modal(modalEl);

                var api = {
                    elements: {
                        content: modalEl.querySelector('.modal-body'),
                        tooltip: modalEl,
                        titlebar: modalEl.querySelector('.modal-header')
                    },
                    set: function(prop, value) {
                        if (prop === 'content.text') {
                            this.elements.content.innerHTML = value;
                        }
                    },
                    hide: function() {
                        modal.hide();
                    }
                };

                // Fetch content if URL provided
                var url = options.url !== null ? options.url : el.getAttribute('href');
                if (url && url !== false) {
                    blestaRequest('GET', url, options.data, function(data) {
                        api.set('content.text', data);
                        options.onRender({}, api);
                    });
                } else {
                    options.onRender({}, api);
                }

                modalEl.addEventListener('shown.bs.modal', function() {
                    options.onShow({}, api);
                });

                modalEl.addEventListener('hidden.bs.modal', function() {
                    options.onHide({}, api);
                    modalEl.remove();
                });

                modal.show();
            };

            el.addEventListener('click', function(e) {
                e.preventDefault();
                showModal();
            });

            if (options.open) {
                showModal();
            }
        });
    }

    window.blestaModal = blestaModal;

    /**
     * Makes elements sortable using Sortable.js
     *
     * @param {HTMLElement|string} element The element(s) to make sortable
     * @param {string} handle The handle selector
     * @param {Object} options Additional Sortable options
     */
    function blestaSortable(element, handle, options) {
        options = options || {};

        var defaults = {
            animation: 150,
            handle: handle || false
        };
        options = Object.assign({}, defaults, options);

        var elements = typeof element === 'string' ?
            document.querySelectorAll(element) : [element];

        elements.forEach(function(el) {
            if (typeof Sortable !== 'undefined') {
                new Sortable(el, options);
            }
        });
    }

    window.blestaSortable = blestaSortable;

    /**
     * Initialize color picker for an element
     *
     * @param {HTMLElement} element The input element
     * @param {Object} options Configuration options
     */
    function blestaColorPicker(element, options) {
        options = options || {};

        var updateColor = function() {
            var hex = element.value;
            element.style.backgroundColor = '#' + hex;
            element.style.color = '#' + blestaContrastColor(hex);
        };

        // Set initial color
        updateColor();

        // Update on change
        element.addEventListener('input', updateColor);
        element.addEventListener('change', updateColor);

        // If a color picker library is available, initialize it
        if (typeof ColorPicker !== 'undefined') {
            ColorPicker(element, options);
        }
    }

    window.blestaColorPicker = blestaColorPicker;

    // Initialize global events when DOM is ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function() {
            blestaBindGlobalGuiEvents(document);
            blestaBindQuickLinks(document);
        });
    } else {
        blestaBindGlobalGuiEvents(document);
        blestaBindQuickLinks(document);
    }

    // jQuery plugin shims for backwards compatibility with legacy module/plugin views
    // These bridge jQuery plugin calls to vanilla JS functions or provide no-op fallbacks
    if (typeof jQuery !== 'undefined' && jQuery.fn) {
        jQuery.fn.blestaBindToolTips = function() {
            return this.each(function() {
                if (typeof window.blestaBindToolTips === 'function') {
                    window.blestaBindToolTips(this);
                }
            });
        };

        jQuery.fn.blestaBindPasswordGenerator = function() {
            return this.each(function() {
                if (typeof window.blestaBindPasswordGenerator === 'function') {
                    window.blestaBindPasswordGenerator(this);
                }
            });
        };

        jQuery.fn.blestaBindDatePicker = function() {
            return this.each(function() {
                if (typeof window.blestaBindDatePicker === 'function') {
                    window.blestaBindDatePicker(this);
                }
            });
        };

        jQuery.fn.blestaBindDropZone = function() {
            return this.each(function() {
                if (typeof window.blestaBindDropZone === 'function') {
                    window.blestaBindDropZone(this);
                }
            });
        };

        jQuery.fn.blestaSetHeadTag = function(tag, attributes) {
            if (typeof window.blestaSetHeadTag === 'function') {
                window.blestaSetHeadTag(tag, attributes);
            }
            return this;
        };

        jQuery.fn.blestaEnableFormSubmission = function(form) {
            if (typeof window.blestaEnableFormSubmission === 'function') {
                var el = (form instanceof jQuery) ? form[0] : form;
                if (el) {
                    window.blestaEnableFormSubmission(el);
                }
            }
            return this;
        };

        // jQuery UI shims - provide no-ops to prevent errors
        // Plugins using these should be updated to use vanilla JS alternatives or Paradigm-specific views
        if (!jQuery.fn.autocomplete) {
            jQuery.fn.autocomplete = function() {
                console.warn('jQuery UI autocomplete is not available in Paradigm theme. Plugin should use vanilla JS alternative.');
                return this;
            };
        }

        if (!jQuery.fn.sortable) {
            jQuery.fn.sortable = function() {
                console.warn('jQuery UI sortable is not available in Paradigm theme. Use Sortable.js instead.');
                return this;
            };
        }

        if (!jQuery.fn.disableSelection) {
            jQuery.fn.disableSelection = function() {
                return this;
            };
        }
    }

})();