ag-charts-core
Version:
Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue
1,353 lines (1,331 loc) • 41.2 kB
JavaScript
;
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, {
EventEmitter: () => EventEmitter,
Logger: () => logger_exports,
ModuleRegistry: () => moduleRegistry_exports,
ModuleType: () => ModuleType,
ValidationError: () => ValidationError,
and: () => and,
array: () => array,
arrayLength: () => arrayLength,
arrayOf: () => arrayOf,
arrayOfDefs: () => arrayOfDefs,
arraysEqual: () => arraysEqual,
attachDescription: () => attachDescription,
boolean: () => boolean,
callback: () => callback,
circularSliceArray: () => circularSliceArray,
clamp: () => clamp,
color: () => color,
colorUnion: () => colorUnion,
constant: () => constant,
countFractionDigits: () => countFractionDigits,
countLines: () => countLines,
createElement: () => createElement,
createNumberFormatter: () => createNumberFormatter,
createSvgElement: () => createSvgElement,
date: () => date,
debounce: () => debounce,
defined: () => defined,
diffArrays: () => diffArrays,
downloadUrl: () => downloadUrl,
entries: () => entries,
fillGradientDefaults: () => fillGradientDefaults,
fillOptionsDef: () => fillOptionsDef,
fillPatternDefaults: () => fillPatternDefaults,
findMaxIndex: () => findMaxIndex,
findMaxValue: () => findMaxValue,
findMinIndex: () => findMinIndex,
findMinValue: () => findMinValue,
first: () => first,
fontOptionsDef: () => fontOptionsDef,
getDocument: () => getDocument,
getWindow: () => getWindow,
gradientColorStops: () => gradientColorStops,
gradientStrict: () => gradientStrict,
greaterThan: () => greaterThan,
groupBy: () => groupBy,
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,
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,
partialDefs: () => partialDefs,
positiveNumber: () => positiveNumber,
positiveNumberNonZero: () => positiveNumberNonZero,
ratio: () => ratio,
required: () => required,
roundTo: () => roundTo,
setDocument: () => setDocument,
setWindow: () => setWindow,
sortBasedOnArray: () => sortBasedOnArray,
string: () => string,
stringifyValue: () => stringifyValue,
strokeOptionsDef: () => strokeOptionsDef,
throttle: () => throttle,
toArray: () => toArray,
toIterable: () => toIterable,
typeUnion: () => typeUnion,
union: () => union,
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 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;
}