UNPKG

ag-charts-core

Version:

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

1,336 lines (1,315 loc) 38.6 kB
var __defProp = Object.defineProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; // 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 warnOnce(message, ...logContent) { const cacheKey = `Logger.warn: ${message}`; if (doOnceCache.has(cacheKey)) return; warn(message, ...logContent); doOnceCache.add(cacheKey); } function errorOnce(message, ...logContent) { const cacheKey = `Logger.error: ${message}`; if (doOnceCache.has(cacheKey)) return; error(message, ...logContent); doOnceCache.add(cacheKey); } 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, 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 (definition.type === moduleType) { yield definition; } } } function detectChartDefinition(options) { for (const definition of registeredModules.values()) { if (isChartModule(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 getSeriesModule(moduleName) { const definition = registeredModules.get(moduleName); if (isSeriesModule(definition)) { return definition; } } function getAxisModule(moduleName) { const definition = registeredModules.get(moduleName); if (isAxisModule(definition)) { return definition; } } function isChartModule(definition) { return definition?.type === "chart" /* Chart */; } function isAxisModule(definition) { return definition?.type === "axis" /* Axis */; } function isSeriesModule(definition) { return definition?.type === "series" /* Series */; } // 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/strings.ts function joinFormatted(values, conjunction = "and", format = String, maxItems = Infinity) { 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/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) && parseColor(value) != null; } // packages/ag-charts-core/src/utils/validation.ts var descriptionSymbol = Symbol("description"); var requiredSymbol = Symbol("required"); var ValidationError = class { constructor(message, path, required2, unknown) { this.message = message; this.path = path; this.required = required2; this.unknown = unknown; } toString() { return this.message; } }; function validate(options, optionsDefs2, path = "") { if (!isObject(options)) { const message = validateMessage(path, options, "an object", true); return { valid: null, errors: [new ValidationError(message, path, true)] }; } const unusedKeys = []; const optionsKeys = new Set(Object.keys(options)); const errors = []; const valid = {}; function extendPath(key) { if (isArray(optionsDefs2)) { return `${path}[${key}]`; } return path ? `${path}.${key}` : key; } for (const key of Object.keys(optionsDefs2)) { const validatorOrDefs = optionsDefs2[key]; const value = options[key]; const required2 = validatorOrDefs[requiredSymbol]; optionsKeys.delete(key); if (typeof value === "undefined") { unusedKeys.push(key); if (!required2) continue; } const keyPath = extendPath(key); if (isFunction(validatorOrDefs)) { const context = { options, path: keyPath }; if (validatorOrDefs(value, context)) { valid[key] = context.result?.valid ?? value; } else if (!context.result) { const message = validateMessage(keyPath, value, validatorOrDefs, required2); errors.push(new ValidationError(message, path, required2)); } if (context.result) { errors.push(...context.result.errors); } } else { const nestedResult = validate(value, validatorOrDefs, keyPath); if (nestedResult.valid != null) { valid[key] = nestedResult.valid; } errors.push(...nestedResult.errors); } } for (const key of optionsKeys) { const value = options[key]; if (typeof value === "undefined") continue; const message = unknownMessage(key, extendPath(key), unusedKeys); errors.push(new ValidationError(message, path, void 0, true)); } return { valid, errors }; } function validateMessage(path, value, validatorOrDefs, required2) { const description = isString(validatorOrDefs) ? validatorOrDefs : validatorOrDefs[descriptionSymbol]; const expecting = description ? `; expecting ${description}` : ""; const prefix = path ? `Option \`${path}\`` : "Value"; return required2 && value == null ? `${prefix} is required and has not been provided${expecting}, ignoring.` : `${prefix} cannot be set to \`${stringifyValue(value, 50)}\`${expecting}, ignoring.`; } function unknownMessage(key, keyPath, unusedKeys) { const match = findSuggestion(key, unusedKeys); const postfix = match ? `; Did you mean \`${match}\`? Ignoring.` : ", ignoring."; return `Unknown option \`${keyPath}\`${postfix}`; } function findSuggestion(value, suggestions, maxDistance = 2) { let smallestDistance = Infinity; const lowerCaseValue = value.toLowerCase(); return suggestions.reduce((res, item) => { const d = levenshteinDistance(lowerCaseValue, item.toLowerCase()); if (smallestDistance > d && d <= maxDistance) { smallestDistance = d; return item; } return res; }, null); } 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] } ); } var optionsDefs = (defs, description = "an object") => attachDescription((value, context) => { context.result = validate(value, defs, context.path); return !context.result.errors.some((error2) => error2.required && error2.path === context.path); }, description); var partialDefs = (defs, description = "an object") => attachDescription((value, context) => { context.result = validate(value, defs, context.path); context.result.errors = context.result.errors.filter((error2) => !error2.unknown); return !context.result.errors.some((error2) => error2.required && error2.path === context.path); }, description); var and = (...validators) => attachDescription( (value, context) => validators.every((validator) => { const result = validator(value, context); if (context.result && !result) { delete context.result; } return result; }), validators.map((v) => v[descriptionSymbol]).filter(Boolean).join(" and ") ); var or = (...validators) => attachDescription( (value, context) => validators.some((validator) => { const result = validator(value, context); if (context.result && !result) { delete context.result; } return result; }), 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 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 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) => attachDescription( (value, context) => isArray(value) && value.every((v) => { const result = validator(v, context); delete context.result; return result; }), description ?? `${validator[descriptionSymbol]} array` ); var arrayOfDefs = (defs, description = "an object array") => attachDescription((value, context) => { if (!isArray(value)) return false; const valid = []; const errors = []; for (let i = 0; i < value.length; i++) { const indexPath = `${context.path}[${i}]`; const result = validate(value[i], defs, indexPath); errors.push(...result.errors); if (!result.errors.some((error2) => error2.required && error2.path === indexPath)) { valid.push(result.valid); } } context.result = { valid, errors }; return true; }, description); var typeUnion = (defs, description = "an object") => { const typeValidator = partialDefs({ type: required(union(...Object.keys(defs))) }); return attachDescription((value, context) => { if (typeValidator(value, context)) { const type = value.type; const typeDefs = { type: required(constant(type)), ...defs[type] }; const result = optionsDefs(typeDefs)(value, context); if (context.result) { for (const error2 of context.result.errors) { error2.message += ` (type="${type}")`; } } return result; } return false; }, description); }; // packages/ag-charts-core/src/options/commonOptionsDefs.ts 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), and(arrayOf(colorStop), colorStopsOrderValidator)); var gradientBounds = union("axis", "item", "series"); var gradientStrict = typeUnion( { gradient: { // @ts-expect-error undocumented options gradient: union("linear", "radial", "conic"), bounds: gradientBounds, colorStops: required(gradientColorStops), rotation: number, reverse: 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" ) ), width: required(positiveNumber), height: required(positiveNumber), fill: required(color), fillOpacity: required(ratio), backgroundFill: required(color), backgroundFillOpacity: required(ratio), padding: required(positiveNumber), rotation: required(number), stroke: required(color), strokeWidth: required(positiveNumber), strokeOpacity: required(ratio) }); var gradientUndocumentedOpts = { // @ts-expect-error undocumented option gradient: union("linear", "radial", "conic"), bounds: gradientBounds, reverse: boolean }; var patternUndocumentedOpts = { // @ts-expect-error undocumented option rotation: number, padding: positiveNumber }; var colorObject = typeUnion( { gradient: { ...gradientUndocumentedOpts, colorStops: gradientColorStops, rotation: number }, pattern: { ...patternUndocumentedOpts, pattern: union( "vertical-lines", "horizontal-lines", "forward-slanted-lines", "backward-slanted-lines", "circles", "squares", "triangles", "diamonds", "stars", "hearts", "crosses" ), width: positiveNumber, height: positiveNumber, fill: color, fillOpacity: ratio, backgroundFill: color, backgroundFillOpacity: ratio, ...strokeOptionsDef } }, "a color object" ); var colorUnion = or(color, colorObject); var fillOptionsDef = { fill: colorUnion, fillOpacity: ratio }; fillOptionsDef.fillGradientDefaults = fillGradientDefaults; fillOptionsDef.fillPatternDefaults = fillPatternDefaults; var lineDashOptionsDef = { lineDash: arrayOf(positiveNumber), lineDashOffset: number }; var fontOptionsDef = { color, fontFamily: string, 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; }); } // 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/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; } }); } // 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/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/numberFormat.ts var formatRegEx = /^(?:(.)?([<>=^]))?([+\-( ])?([$€£¥₣₹#])?(0)?(\d+)?(,)?(?:\.(\d+))?(~)?([%a-z])?$/i; var surroundedRegEx = /^((?:[^#]|#[^{])*)#{([^}]+)}(.*)$/; function isValidNumberFormat(value) { if (!isString(value)) return false; const match = surroundedRegEx.exec(value); return formatRegEx.test(match ? match[2] : value); } function parseNumberFormat(format) { let prefix; let suffix; const surrounded = surroundedRegEx.exec(format); if (surrounded) { [, prefix, format, suffix] = surrounded; } const match = formatRegEx.exec(format); if (!match) { throw new Error(`The number formatter is invalid: ${format}`); } const [, fill, align, sign, symbol, zero, width, comma, precision, trim, type] = match; return { fill, align, sign, symbol, zero, width: parseInt(width), comma, precision: parseInt(precision), trim: Boolean(trim), type, prefix, suffix }; } function createNumberFormatter(format) { const options = typeof format === "string" ? parseNumberFormat(format) : format; const { fill, align, sign = "-", symbol, zero, width, comma, type, prefix = "", suffix = "", precision } = options; let { trim } = options; const precisionIsNaN = precision == null || isNaN(precision); let formatBody; if (!type) { formatBody = decimalTypes["g"]; trim = true; } else if (type in decimalTypes && type in integerTypes) { formatBody = precisionIsNaN ? integerTypes[type] : decimalTypes[type]; } else if (type in decimalTypes) { formatBody = decimalTypes[type]; } else if (type in integerTypes) { formatBody = integerTypes[type]; } else { throw new Error(`The number formatter type is invalid: ${type}`); } let formatterPrecision; if (precisionIsNaN) { formatterPrecision = type ? 6 : 12; } else { formatterPrecision = precision; } return (n) => { let result = formatBody(n, formatterPrecision); if (trim) { result = removeTrailingZeros(result); } if (comma) { result = insertSeparator(result, comma); } result = addSign(n, result, sign); if (symbol && symbol !== "#") { result = `${symbol}${result}`; } if (symbol === "#" && type === "x") { result = `0x${result}`; } if (type === "s") { result = `${result}${getSIPrefix(n)}`; } if (type === "%" || type === "p") { result = `${result}%`; } if (width != null && !isNaN(width)) { result = addPadding(result, width, fill ?? zero, align); } result = `${prefix}${result}${suffix}`; return result; }; } var integerTypes = { b: (n) => absFloor(n).toString(2), c: (n) => String.fromCharCode(n), d: (n) => Math.round(Math.abs(n)).toFixed(0), o: (n) => absFloor(n).toString(8), x: (n) => absFloor(n).toString(16), X: (n) => integerTypes.x(n).toUpperCase(), n: (n) => integerTypes.d(n), "%": (n) => `${absFloor(n * 100).toFixed(0)}` }; var decimalTypes = { e: (n, f) => Math.abs(n).toExponential(f), E: (n, f) => decimalTypes.e(n, f).toUpperCase(), f: (n, f) => Math.abs(n).toFixed(f), F: (n, f) => decimalTypes.f(n, f).toUpperCase(), g: (n, f) => { if (n === 0) { return "0"; } const a = Math.abs(n); const p = Math.floor(Math.log10(a)); if (p >= -4 && p < f) { return a.toFixed(f - 1 - p); } return a.toExponential(f - 1); }, G: (n, f) => decimalTypes.g(n, f).toUpperCase(), n: (n, f) => decimalTypes.g(n, f), p: (n, f) => decimalTypes.r(n * 100, f), r: (n, f) => { if (n === 0) { return "0"; } const a = Math.abs(n); const p = Math.floor(Math.log10(a)); const q = p - (f - 1); if (q <= 0) { return a.toFixed(-q); } const x = 10 ** q; return (Math.round(a / x) * x).toFixed(); }, s: (n, f) => { const p = getSIPrefixPower(n); return decimalTypes.r(n / 10 ** p, f); }, "%": (n, f) => decimalTypes.f(n * 100, f) }; var minSIPrefix = -24; var maxSIPrefix = 24; var siPrefixes = { [minSIPrefix]: "y", [-21]: "z", [-18]: "a", [-15]: "f", [-12]: "p", [-9]: "n", [-6]: "\xB5", [-3]: "m", [0]: "", [3]: "k", [6]: "M", [9]: "G", [12]: "T", [15]: "P", [18]: "E", [21]: "Z", [maxSIPrefix]: "Y" }; var minusSign = "\u2212"; function absFloor(n) { return Math.floor(Math.abs(n)); } function removeTrailingZeros(numString) { return numString.replace(/\.0+$/, "").replace(/(\.[1-9])0+$/, "$1"); } function insertSeparator(numString, separator) { let dotIndex = numString.indexOf("."); if (dotIndex < 0) { dotIndex = numString.length; } const integerChars = numString.substring(0, dotIndex).split(""); const fractionalPart = numString.substring(dotIndex); for (let i = integerChars.length - 3; i > 0; i -= 3) { integerChars.splice(i, 0, separator); } return `${integerChars.join("")}${fractionalPart}`; } function getSIPrefix(n) { return siPrefixes[getSIPrefixPower(n)]; } function getSIPrefixPower(n) { return clamp(minSIPrefix, n ? Math.floor(Math.log10(Math.abs(n)) / 3) * 3 : 0, maxSIPrefix); } function addSign(num, numString, signType = "") { if (signType === "(") { return num >= 0 ? numString : `(${numString})`; } const plusSign = signType === "+" ? "+" : ""; return `${num >= 0 ? plusSign : minusSign}${numString}`; } function addPadding(numString, width, fill = " ", align = ">") { let result = numString; if (align === ">" || !align) { result = result.padStart(width, fill); } else if (align === "<") { result = result.padEnd(width, fill); } else if (align === "^") { const padWidth = Math.max(0, width - result.length); const padLeft = Math.ceil(padWidth / 2); const padRight = Math.floor(padWidth / 2); result = result.padStart(padLeft + result.length, fill); result = result.padEnd(padRight + result.length, fill); } return result; } export { EventEmitter, logger_exports as Logger, moduleRegistry_exports as ModuleRegistry, ModuleType, ValidationError, and, array, arrayLength, arrayOf, arrayOfDefs, arraysEqual, attachDescription, boolean, callback, circularSliceArray, clamp, color, colorUnion, constant, countFractionDigits, countLines, createElement, createNumberFormatter, createSvgElement, date, debounce, defined, diffArrays, downloadUrl, entries, fillGradientDefaults, fillOptionsDef, fillPatternDefaults, findMaxIndex, findMaxValue, findMinIndex, findMinValue, first, fontOptionsDef, getDocument, getWindow, gradientColorStops, gradientStrict, greaterThan, groupBy, inRange, instanceOf, isArray, isBoolean, isColor, isDate, isDefined, isEnumKey, isEnumValue, isFiniteNumber, isFunction, isHtmlElement, isInteger, isNegative, isNumber, isNumberEqual, isObject, isObjectLike, isPlainObject, isRegExp, isString, isSymbol, isValidDate, isValidNumberFormat, iterate, joinFormatted, lessThan, levenshteinDistance, lineDashOptionsDef, modulus, number, numberMin, numberRange, object, optionsDefs, or, parseColor, parseNumberFormat, partialDefs, positiveNumber, positiveNumberNonZero, ratio, required, roundTo, setDocument, setWindow, sortBasedOnArray, string, stringifyValue, strokeOptionsDef, throttle, toArray, toIterable, typeUnion, union, unique, validate };