apexcharts
Version:
A JavaScript Chart Library
1,859 lines • 704 kB
JavaScript
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.10.6
* (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 Utils {
/**
* @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(Utils.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 && Utils.is("ShadowRoot", rootNode);
}
/**
* gets the shadow root host element
* @param {any} el
*/
static getShadowRootHost(el) {
if (!Utils.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"));
}
/**
* @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 (Utils.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 (!Utils.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;
}
}
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 && diff < 100) {
return val.toFixed(1);
}
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: 80