UNPKG

apexcharts

Version:

A JavaScript Chart Library

1,859 lines 704 kB
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