UNPKG

ag-charts-core

Version:

Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue

1,583 lines (1,560 loc) 57.3 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // packages/ag-charts-core/src/main.ts var main_exports = {}; __export(main_exports, { AsyncAwaitQueue: () => AsyncAwaitQueue, ErrorType: () => ErrorType, EventEmitter: () => EventEmitter, Logger: () => logger_exports, ModuleRegistry: () => moduleRegistry_exports, ModuleType: () => ModuleType, UnknownError: () => UnknownError, ValidationError: () => ValidationError, and: () => and, array: () => array, arrayLength: () => arrayLength, arrayOf: () => arrayOf, arrayOfDefs: () => arrayOfDefs, arraysEqual: () => arraysEqual, attachDescription: () => attachDescription, boolean: () => boolean, callback: () => callback, callbackDefs: () => callbackDefs, callbackOf: () => callbackOf, circularSliceArray: () => circularSliceArray, clamp: () => clamp, color: () => color, colorStopsOrderValidator: () => colorStopsOrderValidator, colorUnion: () => colorUnion, constant: () => constant, countFractionDigits: () => countFractionDigits, countLines: () => countLines, createElement: () => createElement, createElementId: () => createElementId, createId: () => createId, createNumberFormatter: () => createNumberFormatter, createSvgElement: () => createSvgElement, date: () => date, debounce: () => debounce, defined: () => defined, diffArrays: () => diffArrays, downloadUrl: () => downloadUrl, dropFirstWhile: () => dropFirstWhile, dropLastWhile: () => dropLastWhile, entries: () => entries, fillGradientDefaults: () => fillGradientDefaults, fillImageDefaults: () => fillImageDefaults, fillOptionsDef: () => fillOptionsDef, fillPatternDefaults: () => fillPatternDefaults, findMaxIndex: () => findMaxIndex, findMaxValue: () => findMaxValue, findMinIndex: () => findMinIndex, findMinValue: () => findMinValue, first: () => first, fontFamilyFull: () => fontFamilyFull, fontOptionsDef: () => fontOptionsDef, generateUUID: () => generateUUID, geoJson: () => geoJson, getAttribute: () => getAttribute, getDocument: () => getDocument, getWindow: () => getWindow, googleFont: () => googleFont, gradientColorStops: () => gradientColorStops, gradientStrict: () => gradientStrict, greaterThan: () => greaterThan, groupBy: () => groupBy, hasRequiredInPath: () => hasRequiredInPath, htmlElement: () => htmlElement, inRange: () => inRange, instanceOf: () => instanceOf, isArray: () => isArray, isBoolean: () => isBoolean, isColor: () => isColor, isDate: () => isDate, isDefined: () => isDefined, isEnumKey: () => isEnumKey, isEnumValue: () => isEnumValue, isFiniteNumber: () => isFiniteNumber, isFunction: () => isFunction, isHtmlElement: () => isHtmlElement, isInteger: () => isInteger, isKeyOf: () => isKeyOf, isNegative: () => isNegative, isNumber: () => isNumber, isNumberEqual: () => isNumberEqual, isObject: () => isObject, isObjectLike: () => isObjectLike, isPlainObject: () => isPlainObject, isRegExp: () => isRegExp, isString: () => isString, isSymbol: () => isSymbol, isValidDate: () => isValidDate, isValidNumberFormat: () => isValidNumberFormat, iterate: () => iterate, joinFormatted: () => joinFormatted, lessThan: () => lessThan, levenshteinDistance: () => levenshteinDistance, lineDashOptionsDef: () => lineDashOptionsDef, modulus: () => modulus, number: () => number, numberMin: () => numberMin, numberRange: () => numberRange, object: () => object, optionsDefs: () => optionsDefs, or: () => or, parseColor: () => parseColor, parseNumberFormat: () => parseNumberFormat, pause: () => pause, positiveNumber: () => positiveNumber, positiveNumberNonZero: () => positiveNumberNonZero, ratio: () => ratio, required: () => required, resetIds: () => resetIds, roundTo: () => roundTo, safeCall: () => safeCall, setAttribute: () => setAttribute, setAttributes: () => setAttributes, setDocument: () => setDocument, setElementStyle: () => setElementStyle, setElementStyles: () => setElementStyles, setWindow: () => setWindow, sortBasedOnArray: () => sortBasedOnArray, string: () => string, stringLength: () => stringLength, stringifyValue: () => stringifyValue, strokeOptionsDef: () => strokeOptionsDef, themeOperator: () => themeOperator, throttle: () => throttle, toArray: () => toArray, toIterable: () => toIterable, typeUnion: () => typeUnion, undocumented: () => undocumented, union: () => union, unionSymbol: () => unionSymbol, unique: () => unique, validate: () => validate }); module.exports = __toCommonJS(main_exports); // packages/ag-charts-core/src/globals/logger.ts var logger_exports = {}; __export(logger_exports, { error: () => error, errorOnce: () => errorOnce, log: () => log, logGroup: () => logGroup, reset: () => reset, table: () => table, warn: () => warn, warnOnce: () => warnOnce }); var doOnceCache = /* @__PURE__ */ new Set(); function log(...logContent) { console.log(...logContent); } function warn(message, ...logContent) { console.warn(`AG Charts - ${message}`, ...logContent); } function error(message, ...logContent) { if (typeof message === "object") { console.error(`AG Charts error`, message, ...logContent); } else { console.error(`AG Charts - ${message}`, ...logContent); } } function table(...logContent) { console.table(...logContent); } function guardOnce(messageOrError, prefix, cb) { let message; if (messageOrError instanceof Error) { message = messageOrError.message; } else if (typeof messageOrError === "string") { message = messageOrError; } else if (typeof messageOrError === "object") { message = JSON.stringify(messageOrError); } else { message = String(messageOrError); } const cacheKey = `${prefix}: ${message}`; if (doOnceCache.has(cacheKey)) return; cb(messageOrError); doOnceCache.add(cacheKey); } function warnOnce(messageOrError, ...logContent) { guardOnce(messageOrError, "Logger.warn", (message) => warn(message, ...logContent)); } function errorOnce(messageOrError, ...logContent) { guardOnce(messageOrError, "Logger.error", (message) => error(message, ...logContent)); } function reset() { doOnceCache.clear(); } function logGroup(name, cb) { console.groupCollapsed(name); try { return cb(); } finally { console.groupEnd(); } } // packages/ag-charts-core/src/globals/moduleRegistry.ts var moduleRegistry_exports = {}; __export(moduleRegistry_exports, { detectChartDefinition: () => detectChartDefinition, getAxisModule: () => getAxisModule, getPresetModule: () => getPresetModule, getSeriesModule: () => getSeriesModule, hasModule: () => hasModule, listModulesByType: () => listModulesByType, register: () => register, registerMany: () => registerMany, reset: () => reset2 }); // packages/ag-charts-core/src/interfaces/moduleDefinition.ts var ModuleType = /* @__PURE__ */ ((ModuleType2) => { ModuleType2["Axis"] = "axis"; ModuleType2["Chart"] = "chart"; ModuleType2["Preset"] = "preset"; ModuleType2["Plugin"] = "plugin"; ModuleType2["Series"] = "series"; return ModuleType2; })(ModuleType || {}); // packages/ag-charts-core/src/globals/moduleRegistry.ts var registeredModules = /* @__PURE__ */ new Map(); function register(definition) { const existingDefinition = registeredModules.get(definition.name); if (existingDefinition && (existingDefinition.enterprise || !definition.enterprise)) { throw new Error(`AG Charts - Module '${definition.name}' already registered`); } registeredModules.set(definition.name, definition); } function registerMany(definitions) { for (const definition of definitions) { register(definition); } } function reset2() { registeredModules.clear(); } function hasModule(moduleName) { return registeredModules.has(moduleName); } function* listModulesByType(moduleType) { for (const definition of registeredModules.values()) { if (isModuleType(moduleType, definition)) { yield definition; } } } function detectChartDefinition(options) { for (const definition of registeredModules.values()) { if (isModuleType("chart" /* Chart */, definition) && definition.detect(options)) { return definition; } } throw new Error( `AG Charts - Unknown chart type; Check options are correctly structured and series types are specified` ); } function getAxisModule(moduleName) { const definition = registeredModules.get(moduleName); if (isModuleType("axis" /* Axis */, definition)) { return definition; } } function getPresetModule(moduleName) { const definition = registeredModules.get(moduleName); if (isModuleType("preset" /* Preset */, definition)) { return definition; } } function getSeriesModule(moduleName) { const definition = registeredModules.get(moduleName); if (isModuleType("series" /* Series */, definition)) { return definition; } } function isModuleType(moduleType, definition) { return definition?.type === moduleType; } // packages/ag-charts-core/src/classes/eventEmitter.ts var EventEmitter = class { constructor() { this.events = /* @__PURE__ */ new Map(); } /** * Registers an event listener. * @param eventName The event name to listen for. * @param listener The callback to be invoked on the event. * @returns A function to unregister the listener. */ on(eventName, listener) { if (!this.events.has(eventName)) { this.events.set(eventName, /* @__PURE__ */ new Set()); } this.events.get(eventName)?.add(listener); return () => this.off(eventName, listener); } /** * Unregisters an event listener. * @param eventName The event name to stop listening for. * @param listener The callback to be removed. */ off(eventName, listener) { const eventListeners = this.events.get(eventName); if (eventListeners) { eventListeners.delete(listener); if (eventListeners.size === 0) { this.events.delete(eventName); } } } /** * Emits an event to all registered listeners. * @param eventName The name of the event to emit. * @param event The event payload. */ emit(eventName, event) { this.events.get(eventName)?.forEach((callback2) => callback2(event)); } /** * Clears all listeners for a specific event or all events if no event name is provided. * @param eventName (Optional) The name of the event to clear listeners for. If not provided, all listeners for all events are cleared. */ clear(eventName) { if (eventName) { this.events.delete(eventName); } else { this.events.clear(); } } }; // packages/ag-charts-core/src/utils/dom/globalsProxy.ts var verifiedGlobals = {}; if (typeof window !== "undefined") { verifiedGlobals.window = window; } else if (typeof global !== "undefined") { verifiedGlobals.window = global.window; } if (typeof document !== "undefined") { verifiedGlobals.document = document; } else if (typeof global !== "undefined") { verifiedGlobals.document = global.document; } function getDocument(propertyName) { return propertyName ? verifiedGlobals.document?.[propertyName] : verifiedGlobals.document; } function getWindow(propertyName) { return propertyName ? verifiedGlobals.window?.[propertyName] : verifiedGlobals.window; } function setDocument(document2) { verifiedGlobals.document = document2; } function setWindow(window2) { verifiedGlobals.window = window2; } // packages/ag-charts-core/src/utils/dom/domElements.ts function createElement(tagName, className, style) { const element = getDocument().createElement(tagName); if (typeof className === "object") { style = className; className = void 0; } if (className) { for (const name of className.split(" ")) { element.classList.add(name); } } if (style) { Object.assign(element.style, style); } return element; } function createSvgElement(elementName) { return getDocument().createElementNS("http://www.w3.org/2000/svg", elementName); } // packages/ag-charts-core/src/utils/dom/domDownload.ts function downloadUrl(dataUrl, fileName) { const body = getDocument("body"); const element = createElement("a", { display: "none" }); element.href = dataUrl; element.download = fileName; body.appendChild(element); element.click(); setTimeout(() => body.removeChild(element)); } // packages/ag-charts-core/src/utils/dom/domUtils.ts function parseColor(color2) { const OptionConstructor = getWindow("Option"); const { style } = new OptionConstructor(); style.color = color2; return style.color || null; } // packages/ag-charts-core/src/utils/typeGuards.ts function isDefined(val) { return val != null; } function isArray(value) { return Array.isArray(value); } function isBoolean(value) { return typeof value === "boolean"; } function isDate(value) { return value instanceof Date; } function isValidDate(value) { return isDate(value) && !isNaN(Number(value)); } function isRegExp(value) { return value instanceof RegExp; } function isFunction(value) { return typeof value === "function"; } function isObject(value) { return typeof value === "object" && value !== null && !isArray(value); } function isObjectLike(value) { return isArray(value) || isPlainObject(value); } function isPlainObject(value) { return typeof value === "object" && value !== null && value.constructor?.name === "Object"; } function isString(value) { return typeof value === "string"; } function isNumber(value) { return typeof value === "number"; } function isFiniteNumber(value) { return Number.isFinite(value); } function isHtmlElement(value) { return typeof window !== "undefined" && value instanceof HTMLElement; } function isEnumKey(enumObject, enumKey) { return isString(enumKey) && Object.keys(enumObject).includes(enumKey); } function isEnumValue(enumObject, enumValue) { return Object.values(enumObject).includes(enumValue); } function isSymbol(value) { return typeof value === "symbol"; } function isColor(value) { return isString(value) && (value === "none" || parseColor(value) != null); } function isKeyOf(value, container) { return value in container; } // packages/ag-charts-core/src/utils/functions.ts function debounce(callback2, waitMs = 0, options) { const { leading = false, trailing = true, maxWait = Infinity } = options ?? {}; let timerId; let startTime; if (maxWait < waitMs) { throw new Error("Value of maxWait cannot be lower than waitMs."); } function debounceCallback(...args) { if (leading && !startTime) { startTime = Date.now(); timerId = setTimeout(() => startTime = null, waitMs); callback2(...args); return; } let adjustedWaitMs = waitMs; if (maxWait !== Infinity && startTime) { const elapsedTime = Date.now() - startTime; if (waitMs > maxWait - elapsedTime) { adjustedWaitMs = maxWait - elapsedTime; } } clearTimeout(timerId); startTime ?? (startTime = Date.now()); timerId = setTimeout(() => { startTime = null; if (trailing) { callback2(...args); } }, adjustedWaitMs); } return Object.assign(debounceCallback, { cancel() { clearTimeout(timerId); startTime = null; } }); } function throttle(callback2, waitMs, options) { const { leading = true, trailing = true } = options ?? {}; let timerId; let lastArgs; let shouldWait = false; function timeoutHandler() { if (trailing && lastArgs) { timerId = setTimeout(timeoutHandler, waitMs); callback2(...lastArgs); } else { shouldWait = false; } lastArgs = null; } function throttleCallback(...args) { if (shouldWait) { lastArgs = args; } else { shouldWait = true; timerId = setTimeout(timeoutHandler, waitMs); if (leading) { callback2(...args); } else { lastArgs = args; } } } return Object.assign(throttleCallback, { cancel() { clearTimeout(timerId); shouldWait = false; lastArgs = null; } }); } function safeCall(callback2, args, errorPath = "") { try { return callback2(...args); } catch (error2) { const postfix = errorPath ? ` \`${errorPath}\`` : ""; warnOnce(`Uncaught exception in user callback${postfix}`, error2); } } // packages/ag-charts-core/src/utils/strings.ts function joinFormatted(values, conjunction = "and", format = String, maxItems = Infinity) { if (values.length === 0) { return ""; } else if (values.length === 1) { return format(values[0]); } values = values.map(format); const lastValue = values.pop(); if (values.length >= maxItems) { const remainingCount = values.length - (maxItems - 1); return `${values.slice(0, maxItems - 1).join(", ")}, and ${remainingCount} more ${conjunction} ${lastValue}`; } return `${values.join(", ")} ${conjunction} ${lastValue}`; } function stringifyValue(value, maxLength = Infinity) { if (typeof value === "number") { if (isNaN(value)) { return "NaN"; } else if (value === Infinity) { return "Infinity"; } else if (value === -Infinity) { return "-Infinity"; } } const strValue = JSON.stringify(value) ?? typeof value; if (strValue.length > maxLength) { return `${strValue.slice(0, maxLength)}... (+${strValue.length - maxLength} characters)`; } return strValue; } function countLines(text) { let count = 1; for (let i = 0; i < text.length; i++) { if (text.charCodeAt(i) === 10) { count++; } } return count; } function levenshteinDistance(a, b) { if (a === b) return 0; const [shorter, longer] = a.length < b.length ? [a, b] : [b, a]; const m = shorter.length; const n = longer.length; let prevRow = new Array(m + 1).fill(0).map((_, i) => i); let currRow = new Array(m + 1); for (let i = 1; i <= n; i++) { currRow[0] = i; for (let j = 1; j <= m; j++) { const cost = longer[i - 1] === shorter[j - 1] ? 0 : 1; currRow[j] = Math.min( prevRow[j] + 1, // Deletion currRow[j - 1] + 1, // Insertion prevRow[j - 1] + cost // Substitution ); } [prevRow, currRow] = [currRow, prevRow]; } return prevRow[m]; } // packages/ag-charts-core/src/utils/validation.ts var descriptionSymbol = Symbol("description"); var requiredSymbol = Symbol("required"); var markedSymbol = Symbol("marked"); var undocumentedSymbol = Symbol("undocumented"); var unionSymbol = Symbol("union"); var similarOptionsMap = [ ["placement", "position"], ["padding", "spacing", "gap"], ["color", "fill", "stroke"], ["whisker", "wick"], ["nodeClick", "seriesNodeClick"], ["nodeDoubleClick", "seriesNodeDoubleClick"], ["src", "url"] ].reduce((map, words) => { for (const word of words) { map.set(word.toLowerCase(), new Set(words.filter((w) => w !== word))); } return map; }, /* @__PURE__ */ new Map()); var ErrorType = /* @__PURE__ */ ((ErrorType2) => { ErrorType2["Invalid"] = "invalid"; ErrorType2["Required"] = "required"; ErrorType2["Unknown"] = "unknown"; return ErrorType2; })(ErrorType || {}); function extendPath(path, key) { if (isFiniteNumber(key)) { return `${path}[${key}]`; } return path ? `${path}.${key}` : key; } var ValidationError = class { constructor(type, description, value, path, key) { this.type = type; this.description = description; this.value = value; this.path = path; this.key = key; } setUnionType(unionType, path) { if (this.path.startsWith(path)) { const suffix = this.path.slice(path.length); this.altPath = `${path}[type=${unionType}]${suffix}`; } } getPrefix() { const { altPath: path = this.path, key } = this; if (!path && !key) return "Value"; return `Option \`${key ? extendPath(path, key) : path}\``; } toString() { const { description = "unknown", type, value } = this; if (type === "required" /* Required */ && value == null) { return `${this.getPrefix()} is required and has not been provided; expecting ${description}, ignoring.`; } return `${this.getPrefix()} cannot be set to \`${stringifyValue(value, 50)}\`; expecting ${description}, ignoring.`; } }; var UnknownError = class extends ValidationError { constructor(suggestions, value, path, key) { super("unknown" /* Unknown */, void 0, value, path, key); this.suggestions = suggestions; this.key = key; } getPrefix() { return `Unknown option \`${extendPath(this.path, this.key)}\``; } getPostfix() { const suggestions = joinFormatted(findSuggestions(this.key, this.suggestions), "or", (val) => `\`${val}\``); return suggestions ? `; Did you mean ${suggestions}? Ignoring.` : ", ignoring."; } toString() { return `${this.getPrefix()}${this.getPostfix()}`; } }; function validate(options, optionsDefs2, path = "") { if (!isObject(options)) { return { cleared: null, invalid: [new ValidationError("required" /* Required */, "an object", options, path)] }; } const cleared = {}; const invalid = []; const optionsKeys = new Set(Object.keys(options)); const unusedKeys = []; if (unionSymbol in optionsDefs2) { const validTypes = Object.keys(optionsDefs2); const defaultType = optionsDefs2[unionSymbol]; if (options.type != null && validTypes.includes(options.type) || options.type == null && defaultType != null) { const { type = defaultType, ...rest } = options; const nestedResult = validate(rest, optionsDefs2[type], path); Object.assign(cleared, { type }, nestedResult.cleared); for (const error2 of nestedResult.invalid) { error2.setUnionType(type, path); } invalid.push(...nestedResult.invalid); } else { const keywords = joinFormatted(validTypes, "or", (val) => `'${val}'`); invalid.push( new ValidationError("required" /* Required */, `a keyword such as ${keywords}`, options.type, path, "type") ); } return { cleared, invalid }; } for (const key of Object.keys(optionsDefs2)) { const validatorOrDefs = optionsDefs2[key]; const required2 = validatorOrDefs[requiredSymbol]; const value = options[key]; optionsKeys.delete(key); if (typeof value === "undefined") { if (!validatorOrDefs[undocumentedSymbol]) { unusedKeys.push(key); } if (!required2) continue; } const keyPath = extendPath(path, key); if (isFunction(validatorOrDefs)) { const context = { options, path: keyPath }; const validatorResult = validatorOrDefs(value, context); const objectResult = typeof validatorResult === "object"; if (objectResult) { invalid.push(...validatorResult.invalid); if (validatorResult.valid) { cleared[key] = validatorResult.cleared; continue; } else if (hasRequiredInPath(validatorResult.invalid, keyPath)) { continue; } } else if (validatorResult) { cleared[key] = value; continue; } invalid.push( new ValidationError( required2 ? "required" /* Required */ : "invalid" /* Invalid */, validatorOrDefs[descriptionSymbol], value, path, key ) ); } else { const nestedResult = validate(value, validatorOrDefs, keyPath); if (nestedResult.cleared != null) { cleared[key] = nestedResult.cleared; } invalid.push(...nestedResult.invalid); } } for (const key of optionsKeys) { const value = options[key]; if (typeof value === "undefined") continue; invalid.push(new UnknownError(unusedKeys, value, path, key)); } return { cleared, invalid }; } function findSuggestions(value, suggestions, maxDistance = 2) { const result = []; const lowerCaseValue = value.toLowerCase(); const similarValues = similarOptionsMap.get(lowerCaseValue); for (const key of suggestions) { const lowerCaseKey = key.toLowerCase(); if (similarValues?.has(key) || lowerCaseKey.includes(lowerCaseValue) || levenshteinDistance(lowerCaseValue, lowerCaseKey) <= maxDistance) { result.push(key); } } return result; } function attachDescription(validatorOrDefs, description) { return Object.assign( isFunction(validatorOrDefs) ? (value, context) => validatorOrDefs(value, context) : { ...validatorOrDefs }, { [descriptionSymbol]: description } ); } function required(validatorOrDefs) { return Object.assign( isFunction(validatorOrDefs) ? (value, context) => validatorOrDefs(value, context) : optionsDefs(validatorOrDefs), { [requiredSymbol]: true, [descriptionSymbol]: validatorOrDefs[descriptionSymbol] } ); } function undocumented(validatorOrDefs) { return Object.assign( isFunction(validatorOrDefs) ? (value, context) => validatorOrDefs(value, context) : optionsDefs(validatorOrDefs), { [undocumentedSymbol]: true, [descriptionSymbol]: validatorOrDefs[descriptionSymbol] } ); } var optionsDefs = (defs, description = "an object") => attachDescription((value, context) => { const result = validate(value, defs, context.path); const valid = !hasRequiredInPath(result.invalid, context.path); return { valid, cleared: result.cleared, invalid: result.invalid }; }, description); var typeUnion = (defs, description, defaultType) => ({ ...defs, [descriptionSymbol]: description, [unionSymbol]: defaultType }); var and = (...validators) => attachDescription( (value, context) => { const invalid = []; for (const validator of validators) { const result = validator(value, context); if (typeof result === "object") { invalid.push(...result.invalid); if (!result.valid) { return { valid: false, cleared: value, invalid }; } value = result.cleared; } else if (!result) { return false; } } return { valid: true, cleared: value, invalid }; }, validators.map((v) => v[descriptionSymbol]).filter(Boolean).join(" and ") ); var or = (...validators) => attachDescription( (value, context) => { for (const validator of validators) { const result = validator(value, context); if (typeof result === "object" ? result.valid : result) { return result; } } return false; }, validators.map((v) => v[descriptionSymbol]).filter(Boolean).join(" or ") ); var isComparable = (value) => isFiniteNumber(value) || isValidDate(value); var isValidDateValue = (value) => isDate(value) || (isFiniteNumber(value) || isString(value)) && isValidDate(new Date(value)); var array = attachDescription(isArray, "an array"); var boolean = attachDescription(isBoolean, "a boolean"); var callback = attachDescription(isFunction, "a function"); var color = attachDescription(isColor, "a color string"); var date = attachDescription(isValidDateValue, "a date"); var defined = attachDescription(isDefined, "a defined value"); var number = attachDescription(isFiniteNumber, "a number"); var object = attachDescription(isObject, "an object"); var string = attachDescription(isString, "a string"); var htmlElement = attachDescription( (value) => typeof HTMLElement === "undefined" || value instanceof HTMLElement, "an html element" ); var arrayLength = (minLength, maxLength = Infinity) => { let message; if (maxLength === Infinity) { message = `an array of at least ${minLength} items`; } else if (minLength === maxLength) { message = `an array of exactly ${minLength} items`; } else if (minLength === 0) { message = `an array of no more than ${maxLength} items`; } else { message = `an array of at least ${minLength} and no more than ${maxLength} items`; } return attachDescription( (value) => isArray(value) && value.length >= minLength && value.length <= maxLength, message ); }; var stringLength = (minLength, maxLength = Infinity) => { let message; if (maxLength === Infinity) { message = `a string of at least ${minLength} characters`; } else if (minLength === maxLength) { message = `an string of exactly ${minLength} characters`; } else if (minLength === 0) { message = `an string of no more than ${maxLength} characters`; } else { message = `an string of at least ${minLength} and no more than ${maxLength} characters`; } return attachDescription( (value) => isString(value) && value.length >= minLength && value.length <= maxLength, message ); }; var numberMin = (min, inclusive = true) => attachDescription( (value) => isFiniteNumber(value) && (value > min || inclusive && value === min), `a number greater than ${inclusive ? "or equal to " : ""}${min}` ); var numberRange = (min, max) => attachDescription( (value) => isFiniteNumber(value) && value >= min && value <= max, `a number between ${min} and ${max} inclusive` ); var positiveNumber = numberMin(0); var positiveNumberNonZero = numberMin(0, false); var ratio = numberRange(0, 1); var lessThan = (otherField) => attachDescription( (value, { options }) => !isComparable(value) || !isComparable(options[otherField]) || value < options[otherField], `the value to be less than \`${otherField}\`` ); var greaterThan = (otherField) => attachDescription( (value, { options }) => !isComparable(value) || !isComparable(options[otherField]) || value > options[otherField], `the value to be greater than \`${otherField}\`` ); function union(...allowed) { if (isObject(allowed[0])) { allowed = Object.values(allowed[0]); } const keywords = joinFormatted(allowed, "or", (value) => `'${value}'`); return attachDescription((value) => allowed.includes(value), `a keyword such as ${keywords}`); } var constant = (allowed) => attachDescription((value) => allowed === value, `the value ${JSON.stringify(allowed)}`); var instanceOf = (instanceType, description) => attachDescription((value) => value instanceof instanceType, description ?? `an instance of ${instanceType.name}`); var arrayOf = (validator, description, strict = true) => attachDescription( (value, context) => { if (!isArray(value)) return false; let valid = strict; const cleared = []; const invalid = []; const setValid = (result) => valid = strict ? valid && result : valid || result; if (value.length === 0) { return { valid: true, cleared, invalid }; } for (let i = 0; i < value.length; i++) { const options = value[i]; const result = validator(options, { options, path: `${context.path}[${i}]` }); if (typeof result === "object") { valid = setValid(result.valid); invalid.push(...result.invalid); if (result.cleared != null) { cleared.push(result.cleared); } } else { valid = setValid(result); if (result) { cleared.push(options); } } } return { valid, cleared: valid || !strict ? cleared : null, invalid }; }, description ?? `${validator[descriptionSymbol]} array` ); var arrayOfDefs = (defs, description = "an object array") => attachDescription((value, context) => { if (!isArray(value)) return false; const cleared = []; const invalid = []; for (let i = 0; i < value.length; i++) { const indexPath = `${context.path}[${i}]`; const result = validate(value[i], defs, indexPath); if (!hasRequiredInPath(result.invalid, indexPath)) { cleared.push(result.cleared); } invalid.push(...result.invalid); } return { valid: true, cleared, invalid }; }, description); var callbackOf = (validator, description) => attachDescription((value, context) => { if (!isFunction(value)) return false; if (markedSymbol in value) return true; const cbWithValidation = Object.assign( (...args) => { const result = safeCall(value, args); if (result == null) return; const validatorResult = validator(result, { options: result, path: "" }); if (typeof validatorResult === "object") { validatorResult.invalid.forEach( callbackWarnInvalid(context, description ?? validator[descriptionSymbol]) ); if (validatorResult.valid) { return validatorResult.cleared; } } else if (validatorResult) { return result; } else { warnOnce( `Callback \`${context.path}\` returned an invalid value \`${stringifyValue(result, 50)}\`; expecting ${description ?? validator[descriptionSymbol]}, ignoring.` ); } }, { [markedSymbol]: true } ); return { valid: true, cleared: cbWithValidation, invalid: [] }; }, "a function"); var callbackDefs = (defs, description = "an object") => attachDescription((value, context) => { if (!isFunction(value)) return false; if (markedSymbol in value) return true; const cbWithValidation = Object.assign( (...args) => { const result = safeCall(value, args, context.path); if (result == null) return; const validatorResult = validate(result, defs); validatorResult.invalid.forEach(callbackWarnInvalid(context, description)); return validatorResult.cleared; }, { [markedSymbol]: true } ); return { valid: true, cleared: cbWithValidation, invalid: [] }; }, "a function"); function hasRequiredInPath(errors, rootPath) { return errors.some((error2) => error2.type === "required" /* Required */ && error2.path === rootPath); } function callbackWarnInvalid(context, description) { return (error2) => { if (error2 instanceof UnknownError) { return warnOnce( `Callback \`${context.path}\` returned an unknown property \`${extendPath(error2.path, error2.key)}\`${error2.getPostfix()}` ); } const errorValue = stringifyValue(error2.value, 50); warnOnce( error2.key ? `Callback \`${context.path}\` returned an invalid property \`${extendPath(error2.path, error2.key)}\`: \`${errorValue}\`; expecting ${error2.description}, ignoring.` : `Callback \`${context.path}\` returned an invalid value \`${errorValue}\`; expecting ${description ?? error2.description}, ignoring.` ); }; } // packages/ag-charts-core/src/options/commonOptionsDefs.ts var themeOperator = (value) => { if (!isObject(value)) return false; const keys = Object.keys(value); return keys.length === 1 && keys[0].startsWith("$"); }; var colorStop = optionsDefs({ color, stop: ratio }, ""); var colorStopsOrderValidator = attachDescription((value) => { let lastStop = -Infinity; for (const item of value) { if (item?.stop != null) { if (item.stop < lastStop) { return false; } lastStop = item.stop; } } return true; }, "color stops to be defined in ascending order"); var gradientColorStops = and(arrayLength(2), arrayOf(colorStop), colorStopsOrderValidator); var gradientBounds = union("axis", "item", "series"); var gradientStrict = optionsDefs( { type: required(constant("gradient")), colorStops: required(gradientColorStops), rotation: number, // @ts-expect-error undocumented options gradient: undocumented(union("linear", "radial", "conic")), bounds: undocumented(gradientBounds), reverse: undocumented(boolean) }, "a gradient object with color stops" ); var strokeOptionsDef = { stroke: color, strokeWidth: positiveNumber, strokeOpacity: ratio }; var fillGradientDefaults = optionsDefs({ type: required(constant("gradient")), gradient: required(union("linear", "radial", "conic")), bounds: required(gradientBounds), colorStops: required(or(gradientColorStops, and(arrayLength(2), arrayOf(color)))), rotation: required(number), reverse: required(boolean) }); var fillPatternDefaults = optionsDefs({ type: required(constant("pattern")), pattern: required( union( "vertical-lines", "horizontal-lines", "forward-slanted-lines", "backward-slanted-lines", "circles", "squares", "triangles", "diamonds", "stars", "hearts", "crosses" ) ), path: stringLength(2), width: required(positiveNumber), height: required(positiveNumber), fill: required(color), fillOpacity: required(ratio), backgroundFill: required(color), backgroundFillOpacity: required(ratio), padding: required(positiveNumber), rotation: required(number), scale: required(positiveNumber), stroke: required(color), strokeWidth: required(positiveNumber), strokeOpacity: required(ratio) }); var fillImageDefaults = optionsDefs({ type: required(constant("image")), url: string, width: positiveNumber, height: positiveNumber, rotation: required(number), backgroundFill: required(color), backgroundFillOpacity: ratio, fit: required(union("stretch", "contain", "cover")), repeat: required(union("repeat", "repeat-x", "repeat-y", "no-repeat")) }); var colorObject = typeUnion( { gradient: { colorStops: gradientColorStops, rotation: number, // @ts-expect-error undocumented option gradient: undocumented(union("linear", "radial", "conic")), bounds: undocumented(gradientBounds), reverse: undocumented(boolean) }, pattern: { pattern: union( "vertical-lines", "horizontal-lines", "forward-slanted-lines", "backward-slanted-lines", "circles", "squares", "triangles", "diamonds", "stars", "hearts", "crosses" ), path: stringLength(2), width: positiveNumber, height: positiveNumber, rotation: number, scale: positiveNumber, fill: color, fillOpacity: ratio, backgroundFill: color, backgroundFillOpacity: ratio, ...strokeOptionsDef, // @ts-expect-error undocumented option padding: undocumented(positiveNumber) }, image: { url: required(string), backgroundFill: color, backgroundFillOpacity: ratio, width: positiveNumber, height: positiveNumber, fit: union("stretch", "contain", "cover", "none"), repeat: union("repeat", "repeat-x", "repeat-y", "no-repeat"), rotation: number } }, "a color object" ); var colorUnion = or(color, optionsDefs(colorObject, "a color object")); var fillOptionsDef = { fill: colorUnion, fillOpacity: ratio }; fillOptionsDef.fillGradientDefaults = undocumented(fillGradientDefaults); fillOptionsDef.fillPatternDefaults = undocumented(fillPatternDefaults); fillOptionsDef.fillImageDefaults = undocumented(fillImageDefaults); var lineDashOptionsDef = { lineDash: arrayOf(positiveNumber), lineDashOffset: number }; var googleFont = optionsDefs({ googleFont: string }, "google font"); var fontFamilyFull = or(string, themeOperator, googleFont, arrayOf(or(string, googleFont))); var fontOptionsDef = { color, fontFamily: fontFamilyFull, fontSize: positiveNumber, fontStyle: union("normal", "italic", "oblique"), fontWeight: or(positiveNumber, union("normal", "bold", "bolder", "lighter")) }; // packages/ag-charts-core/src/utils/arrays.ts function toArray(value) { if (typeof value === "undefined") { return []; } return Array.isArray(value) ? value : [value]; } function unique(array2) { return Array.from(new Set(array2)); } function groupBy(array2, iteratee) { return array2.reduce((result, item) => { const groupKey = iteratee(item); result[groupKey] ?? (result[groupKey] = []); result[groupKey].push(item); return result; }, {}); } function arraysEqual(a, b) { if (a == null || b == null || a.length !== b.length) { return false; } for (let i = 0; i < a.length; i++) { if (Array.isArray(a[i]) && Array.isArray(b[i])) { if (!arraysEqual(a[i], b[i])) { return false; } } else if (a[i] !== b[i]) { return false; } } return true; } function circularSliceArray(data, size, offset = 0) { if (data.length === 0) { return []; } const result = []; for (let i = 0; i < size; i++) { result.push(data.at((i + offset) % data.length)); } return result; } function sortBasedOnArray(baseArray, orderArray) { const orderMap = /* @__PURE__ */ new Map(); orderArray.forEach((item, index) => { orderMap.set(item, index); }); return baseArray.sort((a, b) => { const indexA = orderMap.get(a) ?? Infinity; const indexB = orderMap.get(b) ?? Infinity; return indexA - indexB; }); } function dropFirstWhile(array2, cond) { let i = 0; while (i < array2.length && cond(array2[i])) { i += 1; } const deleteCount = i; if (deleteCount !== 0) array2.splice(0, deleteCount); } function dropLastWhile(array2, cond) { let i = array2.length - 1; while (i >= 0 && cond(array2[i])) { i -= 1; } const deleteCount = array2.length - 1 - i; if (deleteCount !== 0) array2.splice(array2.length - deleteCount, deleteCount); } // packages/ag-charts-core/src/utils/async.ts var AsyncAwaitQueue = class { constructor() { this.queue = []; } /** Await another async process to call notify(). */ await(timeout = 50) { return new Promise((resolve) => { const successFn = () => { clearTimeout(timeoutHandle); resolve(true); }; const timeoutFn = () => { const queueIndex = this.queue.indexOf(successFn); if (queueIndex < 0) return; this.queue.splice(queueIndex, 1); resolve(false); }; const timeoutHandle = setTimeout(timeoutFn, timeout); this.queue.push(successFn); }); } /** Trigger any await()ing async processes to continue. */ notify() { this.queue.splice(0).forEach((cb) => cb()); } }; function pause(delayMilliseconds = 0) { return new Promise((resolve) => { setTimeout(resolve, delayMilliseconds); }); } // packages/ag-charts-core/src/utils/iterators.ts function* iterate(...iterators) { for (const iterator of iterators) { yield* iterator; } } function toIterable(value) { return value != null && typeof value === "object" && Symbol.iterator in value ? value : [value]; } function first(iterable) { for (const value of iterable) { return value; } throw new Error("AG Charts - no first() value found"); } function* entries(obj) { const resultTuple = [void 0, void 0]; for (const key of Object.keys(obj)) { resultTuple[0] = key; resultTuple[1] = obj[key]; yield resultTuple; } } // packages/ag-charts-core/src/utils/attributeUtil.ts function booleanParser(value) { return value === "true"; } function numberParser(value) { return Number(value); } function stringParser(value) { return value; } var AttributeTypeParsers = { role: stringParser, "aria-checked": booleanParser, "aria-controls": stringParser, "aria-describedby": stringParser, "aria-disabled": booleanParser, "aria-expanded": booleanParser, "aria-haspopup": stringParser, "aria-hidden": booleanParser, "aria-label": stringParser, "aria-labelledby": stringParser, "aria-live": stringParser, "aria-orientation": stringParser, "aria-selected": booleanParser, "data-focus-override": booleanParser, "data-focus-visible-override": booleanParser, "data-preventdefault": booleanParser, class: stringParser, for: stringParser, id: stringParser, tabindex: numberParser, title: stringParser, placeholder: stringParser }; function setAttribute(e, qualifiedName, value) { if (value == null || value === "" || value === "") { e?.removeAttribute(qualifiedName); } else { e?.setAttribute(qualifiedName, value.toString()); } } function setAttributes(e, attrs) { if (attrs == null) return; for (const [key, value] of entries(attrs)) { if (key === "class") continue; setAttribute(e, key, value); } } function getAttribute(e, qualifiedName, defaultValue) { if (!(e instanceof HTMLElement)) return void 0; const value = e.getAttribute(qualifiedName); if (value === null) return defaultValue; return AttributeTypeParsers[qualifiedName]?.(value) ?? void 0; } function setElementStyle(e, property, value) { if (e == null) return; if (value == null) { e.style.removeProperty(property); } else { e.style.setProperty(property, value.toString()); } } function setElementStyles(e, styles) { for (const [key, value] of entries(styles)) { setElementStyle(e, key, value); } } // packages/ag-charts-core/src/utils/binarySearch.ts function findMaxIndex(min, max, iteratee) { if (min > max) return; let found; while (max >= min) { const index = Math.floor((max + min) / 2); const value = iteratee(index); if (value) { found = index; min = index + 1; } else { max = index - 1; } } return found; } function findMinIndex(min, max, iteratee) { if (min > max) return; let found; while (max >= min) { const index = Math.floor((max + min) / 2); const value = iteratee(index); if (value) { found = index; max = index - 1; } else { min = index + 1; } } return found; } function findMaxValue(min, max, iteratee) { if (min > max) return; let found; while (max >= min) { const index = Math.floor((max + min) / 2); const value = iteratee(index); if (value == null) { max = index - 1; } else { found = value; min = index + 1; } } return found; } function findMinValue(min, max, iteratee) { if (min > max) return; let found; while (max >= min) { const index = Math.floor((max + min) / 2); const value = iteratee(index); if (value == null) { min = index + 1; } else { found = value; max = index - 1; } } return found; } // packages/ag-charts-core/src/utils/diff.ts function diffArrays(previous, current) { const size = Math.max(previous.length, current.length); const added = /* @__PURE__ */ new Set(); const removed = /* @__PURE__ */ new Set(); for (let i = 0; i < size; i++) { const prev = previous[i]; const curr = current[i]; if (prev === curr) continue; if (removed.has(curr)) { removed.delete(curr); } else if (curr) { added.add(curr); } if (added.has(prev)) { added.delete(prev); } else if (prev) { removed.add(prev); } } return { changed: added.size > 0 || removed.size > 0, added, removed }; } // packages/ag-charts-core/src/utils/numbers.ts function clamp(min, value, max) { return Math.min(max, Math.max(min, value)); } function inRange(value, range, epsilon = 1e-10) { return value >= range[0] - epsilon && value <= range[1] + epsilon; } function isNumberEqual(a, b, epsilon = 1e-10) { return a === b || Math.abs(a - b) < epsilon; } function isNegative(value) { return Math.sign(value) === -1 || Object.is(value, -0); } function isInteger(value) { return value % 1 === 0; } function roundTo(value, decimals = 2) { const base = 10 ** decimals; return Math.round(value * base) / base; } function modulus(n, m) { return Math.floor(n % m + (n < 0 ? Math.abs(m) : 0)); } function countFractionDigits(value) { if (Math.floor(value) === value) { return 0; } let valueString = String(value); let exponent = 0; if (value < 1e-6 || value >= 1e21) { let exponentString; [valueString, exponentString] = valueString.split("e"); if (exponentString != null) { exponent = Number(exponentString); } } const decimalPlaces = valueString.split(".")[1]?.length ?? 0; return Math.max(decimalPlaces - exponent, 0); } // packages/ag-charts-core/src/utils/geoJson.ts function isValidCoordinate(value) { return Array.isArray(value) && value.length >= 2 && value.every(isFiniteNumber); } function isValidCoordinates(value) { return Array.isArray(value) && value.length >= 2 && value.every(isValidCoordinate); } function hasSameStartEndPoint(c) { const start = c[0]; const end = c[c.length - 1]; return isNumberEqual(start[0], end[0], 1e-3) && isNumberEqual(start[1], end[1], 1e-3); } function isValidPolygon(value) { return Array.isArray(value) && value.every(isValidCoordinates) && value.every(hasSameStartEndPoint); } function isValidGeometry(value) { if (value === null) return true; if (!isObject(value) || value.type == null) return false; const { type, coordinates } = value; switch (type) { case "GeometryCollection": return Array.isArray(value.geometries) && value.geometries.every(isValidGeometry); case "MultiPolygon": return Array.isArray(coordinates) && coordinates.every(isValidPolygon); case "Polygon": return isValidPolygon(coordinates); case "MultiLineString": return Array.isArray(coordinates) && coordinates.every(isValidCoordinates); case "LineString": return isValidCoordinates(coordinates); case "MultiPoint": return isValidCoordinates(coordinates); case "Point": return isValidCoordinate(coordinates); default: return false; } } function isValidFeature(value) { return isObject(value) && value.type === "Feature" && isValidGeometry(value.geometry); } function isValidFeatureCollection(value) { return isObject(value) && value.type === "FeatureCollection" && Array.isArray(value.feat