ag-charts-community
Version:
Advanced Charting / Charts supporting Javascript / Typescript / React / Angular / Vue
1,689 lines (1,669 loc) • 1.33 MB
JavaScript
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __decorateClass = (decorators, target, key, kind) => {
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
for (var i = decorators.length - 1, decorator; i >= 0; i--)
if (decorator = decorators[i])
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
if (kind && result)
__defProp(target, key, result);
return result;
};
// packages/ag-charts-community/src/chart/cartesianChart.ts
import { Logger as Logger29, arraysEqual as arraysEqual4, entries as entries7, groupBy as groupBy2 } from "ag-charts-core";
// packages/ag-charts-community/src/motion/animation.ts
import { clamp as clamp3, isPlainObject as isPlainObject2 } from "ag-charts-core";
// packages/ag-charts-community/src/scene/node.ts
import { createSvgElement, toIterable } from "ag-charts-core";
// packages/ag-charts-community/src/util/id.ts
var ID_MAP = /* @__PURE__ */ new Map();
function createId(instance) {
const constructor = instance.constructor;
const className = Object.hasOwn(constructor, "className") ? constructor.className : constructor.name;
if (!className) {
throw new Error(`The ${constructor} is missing the 'className' property.`);
}
const nextId = (ID_MAP.get(className) ?? 0) + 1;
ID_MAP.set(className, nextId);
return `${className}-${nextId}`;
}
function generateUUID() {
return crypto.randomUUID?.() ?? generateUUIDv4();
}
function generateUUIDv4() {
const uuidArray = new Uint8Array(16);
crypto.getRandomValues(uuidArray);
uuidArray[6] = uuidArray[6] & 15 | 64;
uuidArray[8] = uuidArray[8] & 63 | 128;
let uuid = "";
for (let i = 0; i < uuidArray.length; i++) {
if (i === 4 || i === 6 || i === 8 || i === 10) {
uuid += "-";
}
uuid += uuidArray[i].toString(16).padStart(2, "0");
}
return uuid;
}
// packages/ag-charts-community/src/scene/bbox.ts
import { clamp } from "ag-charts-core";
// packages/ag-charts-community/src/util/bboxinterface.ts
var BBoxValues = { containsPoint, isEmpty, normalize };
function containsPoint(bbox, x, y) {
return x >= bbox.x && x <= bbox.x + bbox.width && y >= bbox.y && y <= bbox.y + bbox.height;
}
function isEmpty(bbox) {
return bbox == null || bbox.height === 0 || bbox.width === 0 || isNaN(bbox.height) || isNaN(bbox.width);
}
function normalize(bbox) {
let { x, y, width: width2, height: height2 } = bbox;
if ((width2 == null || width2 > 0) && (height2 == null || height2 > 0))
return bbox;
if (x != null && width2 != null && width2 < 0) {
width2 = -width2;
x = x - width2;
}
if (y != null && height2 != null && height2 < 0) {
height2 = -height2;
y = y - height2;
}
return { x, y, width: width2, height: height2 };
}
// packages/ag-charts-community/src/util/interpolating.ts
var interpolate = Symbol("interpolate");
var isInterpolating = (x) => x[interpolate] != null;
// packages/ag-charts-community/src/util/nearest.ts
function nearestSquared(x, y, objects, maxDistanceSquared = Infinity) {
const result = { nearest: void 0, distanceSquared: maxDistanceSquared };
for (const obj of objects) {
const thisDistance = obj.distanceSquared(x, y);
if (thisDistance === 0) {
return { nearest: obj, distanceSquared: 0 };
} else if (thisDistance < result.distanceSquared) {
result.nearest = obj;
result.distanceSquared = thisDistance;
}
}
return result;
}
// packages/ag-charts-community/src/scene/bbox.ts
var _BBox = class _BBox {
constructor(x, y, width2, height2) {
this.x = x;
this.y = y;
this.width = width2;
this.height = height2;
}
static fromDOMRect({ x, y, width: width2, height: height2 }) {
return new _BBox(x, y, width2, height2);
}
static merge(boxes) {
let left = Infinity;
let top = Infinity;
let right = -Infinity;
let bottom = -Infinity;
for (const box of boxes) {
if (box.x < left) {
left = box.x;
}
if (box.y < top) {
top = box.y;
}
if (box.x + box.width > right) {
right = box.x + box.width;
}
if (box.y + box.height > bottom) {
bottom = box.y + box.height;
}
}
return new _BBox(left, top, right - left, bottom - top);
}
static nearestBox(x, y, boxes) {
return nearestSquared(x, y, boxes);
}
toDOMRect() {
return {
x: this.x,
y: this.y,
width: this.width,
height: this.height,
top: this.y,
left: this.x,
right: this.x + this.width,
bottom: this.y + this.height,
toJSON() {
return {};
}
};
}
clone() {
const { x, y, width: width2, height: height2 } = this;
return new _BBox(x, y, width2, height2);
}
equals(other) {
return this.x === other.x && this.y === other.y && this.width === other.width && this.height === other.height;
}
containsPoint(x, y) {
return BBoxValues.containsPoint(this, x, y);
}
intersection(other) {
if (!this.collidesBBox(other))
return;
const newX1 = clamp(other.x, this.x, other.x + other.width);
const newY1 = clamp(other.y, this.y, other.y + other.height);
const newX2 = clamp(other.x, this.x + this.width, other.x + other.width);
const newY2 = clamp(other.y, this.y + this.height, other.y + other.height);
return new _BBox(newX1, newY1, newX2 - newX1, newY2 - newY1);
}
collidesBBox(other) {
return this.x < other.x + other.width && this.x + this.width > other.x && this.y < other.y + other.height && this.y + this.height > other.y;
}
computeCenter() {
return { x: this.x + this.width / 2, y: this.y + this.height / 2 };
}
isFinite() {
return Number.isFinite(this.x) && Number.isFinite(this.y) && Number.isFinite(this.width) && Number.isFinite(this.height);
}
distanceSquared(x, y) {
if (this.containsPoint(x, y)) {
return 0;
}
const dx = x - clamp(this.x, x, this.x + this.width);
const dy = y - clamp(this.y, y, this.y + this.height);
return dx * dx + dy * dy;
}
shrink(amount, position) {
if (typeof amount === "number") {
this.applyMargin(amount, position);
} else {
for (const key of Object.keys(amount)) {
const value = amount[key];
if (typeof value === "number") {
this.applyMargin(value, key);
}
}
}
if (this.width < 0) {
this.width = 0;
}
if (this.height < 0) {
this.height = 0;
}
return this;
}
grow(amount, position) {
if (typeof amount === "number") {
this.applyMargin(-amount, position);
} else {
for (const key of Object.keys(amount)) {
const value = amount[key];
if (typeof value === "number") {
this.applyMargin(-value, key);
}
}
}
return this;
}
applyMargin(value, position) {
switch (position) {
case "top":
this.y += value;
case "bottom":
this.height -= value;
break;
case "left":
this.x += value;
case "right":
this.width -= value;
break;
case "vertical":
this.y += value;
this.height -= value * 2;
break;
case "horizontal":
this.x += value;
this.width -= value * 2;
break;
case void 0:
this.x += value;
this.y += value;
this.width -= value * 2;
this.height -= value * 2;
break;
}
}
translate(x, y) {
this.x += x;
this.y += y;
return this;
}
[interpolate](other, d) {
return new _BBox(
this.x * (1 - d) + other.x * d,
this.y * (1 - d) + other.y * d,
this.width * (1 - d) + other.width * d,
this.height * (1 - d) + other.height * d
);
}
};
_BBox.zero = Object.freeze(new _BBox(0, 0, 0, 0));
_BBox.NaN = Object.freeze(new _BBox(NaN, NaN, NaN, NaN));
var BBox = _BBox;
// packages/ag-charts-community/src/scene/changeDetectable.ts
function SceneChangeDetection(opts) {
return function(target, key) {
const privateKey = `__${key}`;
if (target[key]) {
return;
}
prepareGetSet(target, key, privateKey, opts);
};
}
function prepareGetSet(target, key, privateKey, opts) {
const { type = "normal", changeCb, convertor, checkDirtyOnAssignment = false } = opts ?? {};
const requiredOpts = { type, changeCb, checkDirtyOnAssignment, convertor };
let setter;
switch (type) {
case "normal":
setter = buildNormalSetter(privateKey, requiredOpts);
break;
case "transform":
setter = buildTransformSetter(privateKey);
break;
case "path":
setter = buildPathSetter(privateKey);
break;
}
setter = buildCheckDirtyChain(
privateKey,
buildChangeCallbackChain(buildConvertorChain(setter, requiredOpts), requiredOpts),
requiredOpts
);
const getter = function() {
return this[privateKey];
};
Object.defineProperty(target, key, {
set: setter,
get: getter,
enumerable: true,
configurable: true
});
}
function buildConvertorChain(setterFn, opts) {
const { convertor } = opts;
if (convertor) {
return function(value) {
setterFn.call(this, convertor(value));
};
}
return setterFn;
}
var NO_CHANGE = Symbol("no-change");
function buildChangeCallbackChain(setterFn, opts) {
const { changeCb } = opts;
if (changeCb) {
return function(value) {
const change = setterFn.call(this, value);
if (change !== NO_CHANGE) {
changeCb.call(this, this);
}
return change;
};
}
return setterFn;
}
function buildCheckDirtyChain(privateKey, setterFn, opts) {
const { checkDirtyOnAssignment } = opts;
if (checkDirtyOnAssignment) {
return function(value) {
const change = setterFn.call(this, value);
if (value?._dirty === true) {
this.markDirty(privateKey);
}
return change;
};
}
return setterFn;
}
function buildNormalSetter(privateKey, opts) {
const { changeCb } = opts;
return function(value) {
const oldValue = this[privateKey];
if (value !== oldValue) {
this[privateKey] = value;
this.markDirty(privateKey);
changeCb?.(this);
return value;
}
return NO_CHANGE;
};
}
function buildTransformSetter(privateKey) {
return function(value) {
const oldValue = this[privateKey];
if (value !== oldValue) {
this[privateKey] = value;
this.markDirtyTransform();
return value;
}
return NO_CHANGE;
};
}
function buildPathSetter(privateKey) {
return function(value) {
const oldValue = this[privateKey];
if (value !== oldValue) {
this[privateKey] = value;
if (!this._dirtyPath) {
this._dirtyPath = true;
this.markDirty(privateKey);
}
return value;
}
return NO_CHANGE;
};
}
// packages/ag-charts-community/src/scene/node.ts
var _Node = class _Node {
constructor(options) {
/** Unique number to allow creation order to be easily determined. */
this.serialNumber = _Node._nextSerialNumber++;
this.childNodeCounts = { groups: 0, nonGroups: 0, thisComplexity: 0, complexity: 0 };
/** Unique node ID in the form `ClassName-NaturalNumber`. */
this.id = createId(this);
this.pointerEvents = 0 /* All */;
this._dirty = true;
this.dirtyZIndex = false;
/**
* To simplify the type system (especially in Selections) we don't have the `Parent` node
* (one that has children). Instead, we mimic HTML DOM, where any node can have children.
* But we still need to distinguish regular leaf nodes from container leafs somehow.
*/
this.isContainerNode = false;
this.visible = true;
this.zIndex = 0;
this.name = options?.name;
this.tag = options?.tag ?? NaN;
this.zIndex = options?.zIndex ?? 0;
if (options?.debugDirty ?? _Node._debugEnabled) {
this._debugDirtyProperties = /* @__PURE__ */ new Map([["__first__", []]]);
}
}
static toSVG(node, width2, height2) {
const svg = node?.toSVG();
if (svg == null || !svg.elements.length && !svg.defs?.length)
return;
const root = createSvgElement("svg");
root.setAttribute("width", String(width2));
root.setAttribute("height", String(height2));
root.setAttribute("viewBox", `0 0 ${width2} ${height2}`);
if (svg.defs?.length) {
const defs = createSvgElement("defs");
defs.append(...svg.defs);
root.append(defs);
}
root.append(...svg.elements);
return root.outerHTML;
}
static *extractBBoxes(nodes, skipInvisible) {
for (const n of nodes) {
if (!skipInvisible || n.visible && !n.transitionOut) {
const bbox = n.getBBox();
if (bbox)
yield bbox;
}
}
}
/**
* Some arbitrary data bound to the node.
*/
get datum() {
return this._datum;
}
set datum(datum) {
if (this._datum !== datum) {
this._previousDatum = this._datum;
this._datum = datum;
}
}
get previousDatum() {
return this._previousDatum;
}
get layerManager() {
return this._layerManager;
}
get dirty() {
return this._dirty;
}
closestDatum() {
for (const { datum } of this.traverseUp(true)) {
if (datum != null) {
return datum;
}
}
}
/** Perform any pre-rendering initialization. */
preRender(renderCtx, thisComplexity = 1) {
this.childNodeCounts.groups = 0;
this.childNodeCounts.nonGroups = 1;
this.childNodeCounts.complexity = thisComplexity;
this.childNodeCounts.thisComplexity = thisComplexity;
for (const child of this.children()) {
const childCounts = child.preRender(renderCtx);
this.childNodeCounts.groups += childCounts.groups;
this.childNodeCounts.nonGroups += childCounts.nonGroups;
this.childNodeCounts.complexity += childCounts.complexity;
}
return this.childNodeCounts;
}
render(renderCtx) {
const { stats } = renderCtx;
this._dirty = false;
this.debugDirtyProperties();
if (renderCtx.debugNodeSearch) {
const idOrName = this.name ?? this.id;
if (renderCtx.debugNodeSearch.some((v) => typeof v === "string" ? v === idOrName : v.test(idOrName))) {
renderCtx.debugNodes[this.name ?? this.id] = this;
}
}
if (stats) {
stats.nodesRendered++;
stats.opsPerformed += this.childNodeCounts.thisComplexity;
}
}
_setLayerManager(value) {
this._layerManager = value;
this._debug = value?.debug;
for (const child of this.children()) {
child._setLayerManager(value);
}
}
sortChildren(compareFn) {
this.dirtyZIndex = false;
if (!this.childNodes)
return;
const sortedChildren = [...this.childNodes].sort(compareFn);
this.childNodes.clear();
for (const child of sortedChildren) {
this.childNodes.add(child);
}
}
*traverseUp(includeSelf) {
let node = this;
if (includeSelf) {
yield node;
}
while (node = node.parentNode) {
yield node;
}
}
*children() {
if (!this.childNodes)
return;
for (const child of this.childNodes) {
yield child;
}
}
*descendants() {
for (const child of this.children()) {
yield child;
yield* child.descendants();
}
}
/**
* Checks if the node is a leaf (has no children).
*/
isLeaf() {
return !this.childNodes?.size;
}
/**
* Checks if the node is the root (has no parent).
*/
isRoot() {
return !this.parentNode;
}
/**
* Appends one or more new node instances to this parent.
* If one needs to:
* - move a child to the end of the list of children
* - move a child from one parent to another (including parents in other scenes)
* one should use the {@link insertBefore} method instead.
* @param nodes A node or nodes to append.
*/
append(nodes) {
this.childNodes ?? (this.childNodes = /* @__PURE__ */ new Set());
for (const node of toIterable(nodes)) {
node.parentNode?.removeChild(node);
this.childNodes.add(node);
node.parentNode = this;
node._setLayerManager(this.layerManager);
}
this.invalidateCachedBBox();
this.dirtyZIndex = true;
this.markDirty();
}
appendChild(node) {
this.append(node);
return node;
}
removeChild(node) {
if (!this.childNodes?.delete(node)) {
throw new Error(
`AG Charts - internal error, unknown child node ${node.name ?? node.id} in $${this.name ?? this.id}`
);
}
delete node.parentNode;
node._setLayerManager();
this.invalidateCachedBBox();
this.dirtyZIndex = true;
this.markDirty();
}
remove() {
this.parentNode?.removeChild(this);
}
clear() {
for (const child of this.children()) {
delete child.parentNode;
child._setLayerManager();
}
this.childNodes?.clear();
this.invalidateCachedBBox();
}
destroy() {
this.parentNode?.removeChild(this);
}
setProperties(styles, pickKeys) {
if (pickKeys) {
for (const key of pickKeys) {
this[key] = styles[key];
}
} else {
Object.assign(this, styles);
}
return this;
}
containsPoint(_x, _y) {
return false;
}
/**
* Hit testing method.
* Recursively checks if the given point is inside this node or any of its children.
* Returns the first matching node or `undefined`.
* Nodes that render later (show on top) are hit tested first.
*/
pickNode(x, y) {
if (!this.visible || this.pointerEvents === 1 /* None */ || !this.containsPoint(x, y)) {
return;
}
if (this.childNodes != null && this.childNodes.size !== 0) {
const children = [...this.children()];
for (let i = children.length - 1; i >= 0; i--) {
const hit = children[i].pickNode(x, y);
if (hit) {
return hit;
}
}
} else if (!this.isContainerNode) {
return this;
}
}
pickNodes(x, y, into = []) {
if (!this.visible || this.pointerEvents === 1 /* None */ || !this.containsPoint(x, y)) {
return into;
}
if (!this.isContainerNode) {
into.push(this);
}
for (const child of this.children()) {
child.pickNodes(x, y, into);
}
return into;
}
invalidateCachedBBox() {
if (this.cachedBBox != null) {
this.cachedBBox = void 0;
this.parentNode?.invalidateCachedBBox();
}
}
getBBox() {
if (this.cachedBBox == null) {
this.cachedBBox = Object.freeze(this.computeBBox());
}
return this.cachedBBox;
}
computeBBox() {
return;
}
markDirty(property) {
const { _dirty } = this;
if (property != null && this._debugDirtyProperties) {
this.markDebugProperties(property);
}
const noParentCachedBBox = this.cachedBBox == null;
if (noParentCachedBBox && _dirty)
return;
this.invalidateCachedBBox();
this._dirty = true;
if (this.parentNode) {
this.parentNode.markDirty();
}
}
markClean() {
if (!this._dirty)
return;
this._dirty = false;
this.debugDirtyProperties();
for (const child of this.children()) {
child.markClean();
}
}
markDebugProperties(property) {
const sources = this._debugDirtyProperties?.get(property) ?? [];
const caller = new Error().stack?.split("\n").filter((line) => {
return line !== "Error" && !line.includes(".markDebugProperties") && !line.includes(".markDirty") && !line.includes("Object.assign ") && !line.includes(`${this.constructor.name}.`);
}) ?? "unknown";
sources.push(caller[0].replace(" at ", "").trim());
this._debugDirtyProperties?.set(property, sources);
}
debugDirtyProperties() {
if (this._debugDirtyProperties == null)
return;
if (!this._debugDirtyProperties.has("__first__")) {
this._debugDirtyProperties.forEach((sources, property) => {
if (sources.length > 1) {
console.groupCollapsed(
`Property changed multiple times before render: ${this.constructor.name}.${property} (${sources.length}x)`
);
sources.forEach((source) => console.log(source));
console.groupEnd();
}
});
}
this._debugDirtyProperties.clear();
}
onZIndexChange() {
const { parentNode } = this;
if (parentNode) {
parentNode.dirtyZIndex = true;
}
}
toSVG() {
return;
}
};
_Node._nextSerialNumber = 0;
// eslint-disable-next-line sonarjs/public-static-readonly
_Node._debugEnabled = false;
__decorateClass([
SceneChangeDetection()
], _Node.prototype, "visible", 2);
__decorateClass([
SceneChangeDetection({
changeCb: (target) => target.onZIndexChange()
})
], _Node.prototype, "zIndex", 2);
var Node = _Node;
// packages/ag-charts-community/src/util/color.ts
import { clamp as clamp2 } from "ag-charts-core";
var lerp = (x, y, t) => x * (1 - t) + y * t;
var srgbToLinear = (value) => {
const sign = value < 0 ? -1 : 1;
const abs = Math.abs(value);
if (abs <= 0.04045)
return value / 12.92;
return sign * ((abs + 0.055) / 1.055) ** 2.4;
};
var srgbFromLinear = (value) => {
const sign = value < 0 ? -1 : 1;
const abs = Math.abs(value);
if (abs > 31308e-7) {
return sign * (1.055 * abs ** (1 / 2.4) - 0.055);
}
return 12.92 * value;
};
var _Color = class _Color {
/**
* Every color component should be in the [0, 1] range.
* Some easing functions (such as elastic easing) can overshoot the target value by some amount.
* So, when animating colors, if the source or target color components are already near
* or at the edge of the allowed [0, 1] range, it is possible for the intermediate color
* component value to end up outside of that range mid-animation. For this reason the constructor
* performs range checking/constraining.
* @param r Red component.
* @param g Green component.
* @param b Blue component.
* @param a Alpha (opacity) component.
*/
constructor(r, g, b, a = 1) {
this.r = clamp2(0, r || 0, 1);
this.g = clamp2(0, g || 0, 1);
this.b = clamp2(0, b || 0, 1);
this.a = clamp2(0, a || 0, 1);
}
/**
* A color string can be in one of the following formats to be valid:
* - #rgb
* - #rrggbb
* - rgb(r, g, b)
* - rgba(r, g, b, a)
* - CSS color name such as 'white', 'orange', 'cyan', etc.
*/
static validColorString(str) {
if (str.indexOf("#") >= 0) {
return !!_Color.parseHex(str);
}
if (str.indexOf("rgb") >= 0) {
return !!_Color.stringToRgba(str);
}
return _Color.nameToHex.has(str.toLowerCase());
}
/**
* The given string can be in one of the following formats:
* - #rgb
* - #rrggbb
* - rgb(r, g, b)
* - rgba(r, g, b, a)
* - CSS color name such as 'white', 'orange', 'cyan', etc.
* @param str
*/
static fromString(str) {
if (str.indexOf("#") >= 0) {
return _Color.fromHexString(str);
}
const hex = _Color.nameToHex.get(str.toLowerCase());
if (hex) {
return _Color.fromHexString(hex);
}
if (str.indexOf("rgb") >= 0) {
return _Color.fromRgbaString(str);
}
throw new Error(`Invalid color string: '${str}'`);
}
// See https://drafts.csswg.org/css-color/#hex-notation
static parseHex(input) {
input = input.replace(/ /g, "").slice(1);
let parts;
switch (input.length) {
case 6:
case 8:
parts = [];
for (let i = 0; i < input.length; i += 2) {
parts.push(parseInt(`${input[i]}${input[i + 1]}`, 16));
}
break;
case 3:
case 4:
parts = input.split("").map((p) => parseInt(p, 16)).map((p) => p + p * 16);
break;
}
if (parts?.length >= 3 && parts.every((p) => p >= 0)) {
if (parts.length === 3) {
parts.push(255);
}
return parts;
}
}
static fromHexString(str) {
const values = _Color.parseHex(str);
if (values) {
const [r, g, b, a] = values;
return new _Color(r / 255, g / 255, b / 255, a / 255);
}
throw new Error(`Malformed hexadecimal color string: '${str}'`);
}
static stringToRgba(str) {
let po = -1;
let pc = -1;
for (let i = 0; i < str.length; i++) {
const c = str[i];
if (po === -1 && c === "(") {
po = i;
} else if (c === ")") {
pc = i;
break;
}
}
if (po === -1 || pc === -1)
return;
const contents = str.substring(po + 1, pc);
const parts = contents.split(",");
const rgba = [];
for (let i = 0; i < parts.length; i++) {
const part = parts[i];
let value = parseFloat(part);
if (!Number.isFinite(value)) {
return;
}
if (part.indexOf("%") >= 0) {
value = clamp2(0, value, 100);
value /= 100;
} else if (i === 3) {
value = clamp2(0, value, 1);
} else {
value = clamp2(0, value, 255);
value /= 255;
}
rgba.push(value);
}
return rgba;
}
static fromRgbaString(str) {
const rgba = _Color.stringToRgba(str);
if (rgba) {
if (rgba.length === 3) {
return new _Color(rgba[0], rgba[1], rgba[2]);
} else if (rgba.length === 4) {
return new _Color(rgba[0], rgba[1], rgba[2], rgba[3]);
}
}
throw new Error(`Malformed rgb/rgba color string: '${str}'`);
}
static fromArray(arr) {
if (arr.length === 4) {
return new _Color(arr[0], arr[1], arr[2], arr[3]);
}
if (arr.length === 3) {
return new _Color(arr[0], arr[1], arr[2]);
}
throw new Error("The given array should contain 3 or 4 color components (numbers).");
}
static fromHSB(h, s, b, alpha = 1) {
const rgb = _Color.HSBtoRGB(h, s, b);
return new _Color(rgb[0], rgb[1], rgb[2], alpha);
}
static fromHSL(h, s, l, alpha = 1) {
const rgb = _Color.HSLtoRGB(h, s, l);
return new _Color(rgb[0], rgb[1], rgb[2], alpha);
}
static fromOKLCH(l, c, h, alpha = 1) {
const rgb = _Color.OKLCHtoRGB(l, c, h);
return new _Color(rgb[0], rgb[1], rgb[2], alpha);
}
static padHex(str) {
return str.length === 1 ? "0" + str : str;
}
toHexString() {
let hex = "#" + _Color.padHex(Math.round(this.r * 255).toString(16)) + _Color.padHex(Math.round(this.g * 255).toString(16)) + _Color.padHex(Math.round(this.b * 255).toString(16));
if (this.a < 1) {
hex += _Color.padHex(Math.round(this.a * 255).toString(16));
}
return hex;
}
toRgbaString(fractionDigits = 3) {
const components = [Math.round(this.r * 255), Math.round(this.g * 255), Math.round(this.b * 255)];
const k = Math.pow(10, fractionDigits);
if (this.a !== 1) {
components.push(Math.round(this.a * k) / k);
return `rgba(${components.join(", ")})`;
}
return `rgb(${components.join(", ")})`;
}
toString() {
if (this.a === 1) {
return this.toHexString();
}
return this.toRgbaString();
}
toHSB() {
return _Color.RGBtoHSB(this.r, this.g, this.b);
}
static RGBtoOKLCH(r, g, b) {
const LSRGB0 = srgbToLinear(r);
const LSRGB1 = srgbToLinear(g);
const LSRGB2 = srgbToLinear(b);
const LMS0 = Math.cbrt(0.4122214708 * LSRGB0 + 0.5363325363 * LSRGB1 + 0.0514459929 * LSRGB2);
const LMS1 = Math.cbrt(0.2119034982 * LSRGB0 + 0.6806995451 * LSRGB1 + 0.1073969566 * LSRGB2);
const LMS2 = Math.cbrt(0.0883024619 * LSRGB0 + 0.2817188376 * LSRGB1 + 0.6299787005 * LSRGB2);
const OKLAB0 = 0.2104542553 * LMS0 + 0.793617785 * LMS1 - 0.0040720468 * LMS2;
const OKLAB1 = 1.9779984951 * LMS0 - 2.428592205 * LMS1 + 0.4505937099 * LMS2;
const OKLAB2 = 0.0259040371 * LMS0 + 0.7827717662 * LMS1 - 0.808675766 * LMS2;
const hue = Math.atan2(OKLAB2, OKLAB1) * 180 / Math.PI;
const OKLCH0 = OKLAB0;
const OKLCH1 = Math.hypot(OKLAB1, OKLAB2);
const OKLCH2 = hue >= 0 ? hue : hue + 360;
return [OKLCH0, OKLCH1, OKLCH2];
}
static OKLCHtoRGB(l, c, h) {
const OKLAB0 = l;
const OKLAB1 = c * Math.cos(h * Math.PI / 180);
const OKLAB2 = c * Math.sin(h * Math.PI / 180);
const LMS0 = (OKLAB0 + 0.3963377774 * OKLAB1 + 0.2158037573 * OKLAB2) ** 3;
const LMS1 = (OKLAB0 - 0.1055613458 * OKLAB1 - 0.0638541728 * OKLAB2) ** 3;
const LMS2 = (OKLAB0 - 0.0894841775 * OKLAB1 - 1.291485548 * OKLAB2) ** 3;
const LSRGB0 = 4.0767416621 * LMS0 - 3.3077115913 * LMS1 + 0.2309699292 * LMS2;
const LSRGB1 = -1.2684380046 * LMS0 + 2.6097574011 * LMS1 - 0.3413193965 * LMS2;
const LSRGB2 = -0.0041960863 * LMS0 - 0.7034186147 * LMS1 + 1.707614701 * LMS2;
const SRGB0 = srgbFromLinear(LSRGB0);
const SRGB1 = srgbFromLinear(LSRGB1);
const SRGB2 = srgbFromLinear(LSRGB2);
return [SRGB0, SRGB1, SRGB2];
}
static RGBtoHSL(r, g, b) {
const min = Math.min(r, g, b);
const max = Math.max(r, g, b);
const l = (max + min) / 2;
let h;
let s;
if (max === min) {
h = 0;
s = 0;
} else {
const delta3 = max - min;
s = l > 0.5 ? delta3 / (2 - max - min) : delta3 / (max + min);
if (max === r) {
h = (g - b) / delta3 + (g < b ? 6 : 0);
} else if (max === g) {
h = (b - r) / delta3 + 2;
} else {
h = (r - g) / delta3 + 4;
}
h *= 360 / 6;
}
return [h, s, l];
}
static HSLtoRGB(h, s, l) {
h = (h % 360 + 360) % 360;
if (s === 0) {
return [l, l, l];
}
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
function hueToRgb(t) {
if (t < 0)
t += 1;
if (t > 1)
t -= 1;
if (t < 1 / 6)
return p + (q - p) * 6 * t;
if (t < 1 / 2)
return q;
if (t < 2 / 3)
return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
const r = hueToRgb(h / 360 + 1 / 3);
const g = hueToRgb(h / 360);
const b = hueToRgb(h / 360 - 1 / 3);
return [r, g, b];
}
/**
* Converts the given RGB triple to an array of HSB (HSV) components.
*/
static RGBtoHSB(r, g, b) {
const min = Math.min(r, g, b);
const max = Math.max(r, g, b);
const S = max === 0 ? 0 : (max - min) / max;
let H = 0;
if (min !== max) {
const delta3 = max - min;
const rc = (max - r) / delta3;
const gc = (max - g) / delta3;
const bc = (max - b) / delta3;
if (r === max) {
H = bc - gc;
} else if (g === max) {
H = 2 + rc - bc;
} else {
H = 4 + gc - rc;
}
H /= 6;
if (H < 0) {
H = H + 1;
}
}
return [H * 360, S, max];
}
/**
* Converts the given HSB (HSV) triple to an array of RGB components.
*/
static HSBtoRGB(H, S, B) {
H = (H % 360 + 360) % 360 / 360;
let r = 0;
let g = 0;
let b = 0;
if (S === 0) {
r = g = b = B;
} else {
const h = (H - Math.floor(H)) * 6;
const f = h - Math.floor(h);
const p = B * (1 - S);
const q = B * (1 - S * f);
const t = B * (1 - S * (1 - f));
switch (h >> 0) {
case 0:
r = B;
g = t;
b = p;
break;
case 1:
r = q;
g = B;
b = p;
break;
case 2:
r = p;
g = B;
b = t;
break;
case 3:
r = p;
g = q;
b = B;
break;
case 4:
r = t;
g = p;
b = B;
break;
case 5:
r = B;
g = p;
b = q;
break;
}
}
return [r, g, b];
}
static mix(c0, c1, t) {
return new _Color(lerp(c0.r, c1.r, t), lerp(c0.g, c1.g, t), lerp(c0.b, c1.b, t), lerp(c0.a, c1.a, t));
}
static lighten(c, t) {
const oklch = _Color.RGBtoOKLCH(c.r, c.g, c.b);
return _Color.fromOKLCH(clamp2(0, oklch[0] + t, 1), oklch[1], oklch[2]);
}
static darken(c, t) {
const oklch = _Color.RGBtoOKLCH(c.r, c.g, c.b);
return _Color.fromOKLCH(clamp2(0, oklch[0] - t, 1), oklch[1], oklch[2]);
}
static interpolate(colors, count) {
const step = 1 / (colors.length - 1);
const oklchColors = colors.map((c) => _Color.RGBtoOKLCH(c.r, c.g, c.b));
return Array.from({ length: count }, (_, i) => {
const t = i / (count - 1);
const index = colors.length <= 2 ? 0 : Math.min(Math.floor(t * (colors.length - 1)), colors.length - 2);
const q = (t - index * step) / step;
const c0 = oklchColors[index];
const c1 = oklchColors[index + 1];
return _Color.fromOKLCH(lerp(c0[0], c1[0], q), lerp(c0[1], c1[1], q), lerp(c0[2], c1[2], q));
});
}
};
/**
* CSS Color Module Level 4:
* https://drafts.csswg.org/css-color/#named-colors
*/
_Color.nameToHex = /* @__PURE__ */ new Map([
["aliceblue", "#F0F8FF"],
["antiquewhite", "#FAEBD7"],
["aqua", "#00FFFF"],
["aquamarine", "#7FFFD4"],
["azure", "#F0FFFF"],
["beige", "#F5F5DC"],
["bisque", "#FFE4C4"],
["black", "#000000"],
["blanchedalmond", "#FFEBCD"],
["blue", "#0000FF"],
["blueviolet", "#8A2BE2"],
["brown", "#A52A2A"],
["burlywood", "#DEB887"],
["cadetblue", "#5F9EA0"],
["chartreuse", "#7FFF00"],
["chocolate", "#D2691E"],
["coral", "#FF7F50"],
["cornflowerblue", "#6495ED"],
["cornsilk", "#FFF8DC"],
["crimson", "#DC143C"],
["cyan", "#00FFFF"],
["darkblue", "#00008B"],
["darkcyan", "#008B8B"],
["darkgoldenrod", "#B8860B"],
["darkgray", "#A9A9A9"],
["darkgreen", "#006400"],
["darkgrey", "#A9A9A9"],
["darkkhaki", "#BDB76B"],
["darkmagenta", "#8B008B"],
["darkolivegreen", "#556B2F"],
["darkorange", "#FF8C00"],
["darkorchid", "#9932CC"],
["darkred", "#8B0000"],
["darksalmon", "#E9967A"],
["darkseagreen", "#8FBC8F"],
["darkslateblue", "#483D8B"],
["darkslategray", "#2F4F4F"],
["darkslategrey", "#2F4F4F"],
["darkturquoise", "#00CED1"],
["darkviolet", "#9400D3"],
["deeppink", "#FF1493"],
["deepskyblue", "#00BFFF"],
["dimgray", "#696969"],
["dimgrey", "#696969"],
["dodgerblue", "#1E90FF"],
["firebrick", "#B22222"],
["floralwhite", "#FFFAF0"],
["forestgreen", "#228B22"],
["fuchsia", "#FF00FF"],
["gainsboro", "#DCDCDC"],
["ghostwhite", "#F8F8FF"],
["gold", "#FFD700"],
["goldenrod", "#DAA520"],
["gray", "#808080"],
["green", "#008000"],
["greenyellow", "#ADFF2F"],
["grey", "#808080"],
["honeydew", "#F0FFF0"],
["hotpink", "#FF69B4"],
["indianred", "#CD5C5C"],
["indigo", "#4B0082"],
["ivory", "#FFFFF0"],
["khaki", "#F0E68C"],
["lavender", "#E6E6FA"],
["lavenderblush", "#FFF0F5"],
["lawngreen", "#7CFC00"],
["lemonchiffon", "#FFFACD"],
["lightblue", "#ADD8E6"],
["lightcoral", "#F08080"],
["lightcyan", "#E0FFFF"],
["lightgoldenrodyellow", "#FAFAD2"],
["lightgray", "#D3D3D3"],
["lightgreen", "#90EE90"],
["lightgrey", "#D3D3D3"],
["lightpink", "#FFB6C1"],
["lightsalmon", "#FFA07A"],
["lightseagreen", "#20B2AA"],
["lightskyblue", "#87CEFA"],
["lightslategray", "#778899"],
["lightslategrey", "#778899"],
["lightsteelblue", "#B0C4DE"],
["lightyellow", "#FFFFE0"],
["lime", "#00FF00"],
["limegreen", "#32CD32"],
["linen", "#FAF0E6"],
["magenta", "#FF00FF"],
["maroon", "#800000"],
["mediumaquamarine", "#66CDAA"],
["mediumblue", "#0000CD"],
["mediumorchid", "#BA55D3"],
["mediumpurple", "#9370DB"],
["mediumseagreen", "#3CB371"],
["mediumslateblue", "#7B68EE"],
["mediumspringgreen", "#00FA9A"],
["mediumturquoise", "#48D1CC"],
["mediumvioletred", "#C71585"],
["midnightblue", "#191970"],
["mintcream", "#F5FFFA"],
["mistyrose", "#FFE4E1"],
["moccasin", "#FFE4B5"],
["navajowhite", "#FFDEAD"],
["navy", "#000080"],
["oldlace", "#FDF5E6"],
["olive", "#808000"],
["olivedrab", "#6B8E23"],
["orange", "#FFA500"],
["orangered", "#FF4500"],
["orchid", "#DA70D6"],
["palegoldenrod", "#EEE8AA"],
["palegreen", "#98FB98"],
["paleturquoise", "#AFEEEE"],
["palevioletred", "#DB7093"],
["papayawhip", "#FFEFD5"],
["peachpuff", "#FFDAB9"],
["peru", "#CD853F"],
["pink", "#FFC0CB"],
["plum", "#DDA0DD"],
["powderblue", "#B0E0E6"],
["purple", "#800080"],
["rebeccapurple", "#663399"],
["red", "#FF0000"],
["rosybrown", "#BC8F8F"],
["royalblue", "#4169E1"],
["saddlebrown", "#8B4513"],
["salmon", "#FA8072"],
["sandybrown", "#F4A460"],
["seagreen", "#2E8B57"],
["seashell", "#FFF5EE"],
["sienna", "#A0522D"],
["silver", "#C0C0C0"],
["skyblue", "#87CEEB"],
["slateblue", "#6A5ACD"],
["slategray", "#708090"],
["slategrey", "#708090"],
["snow", "#FFFAFA"],
["springgreen", "#00FF7F"],
["steelblue", "#4682B4"],
["tan", "#D2B48C"],
["teal", "#008080"],
["thistle", "#D8BFD8"],
["tomato", "#FF6347"],
["transparent", "#00000000"],
["turquoise", "#40E0D0"],
["violet", "#EE82EE"],
["wheat", "#F5DEB3"],
["white", "#FFFFFF"],
["whitesmoke", "#F5F5F5"],
["yellow", "#FFFF00"],
["yellowgreen", "#9ACD32"]
]);
var Color = _Color;
// packages/ag-charts-community/src/util/interpolate.ts
function interpolateNumber(a, b) {
return (d) => Number(a) * (1 - d) + Number(b) * d;
}
function interpolateColor(a, b) {
if (typeof a === "string") {
try {
a = Color.fromString(a);
} catch {
a = Color.fromArray([0, 0, 0]);
}
}
if (typeof b === "string") {
try {
b = Color.fromString(b);
} catch {
b = Color.fromArray([0, 0, 0]);
}
}
return (d) => Color.mix(a, b, d).toRgbaString();
}
// packages/ag-charts-community/src/util/object.ts
import { entries, isArray, isObject, isPlainObject } from "ag-charts-core";
// packages/ag-charts-community/src/util/decorator.ts
var BREAK_TRANSFORM_CHAIN = Symbol("BREAK");
var CONFIG_KEY = "__decorator_config";
function addFakeTransformToInstanceProperty(target, propertyKeyOrSymbol) {
initialiseConfig(target, propertyKeyOrSymbol).optional = true;
}
function initialiseConfig(target, propertyKeyOrSymbol) {
if (Object.getOwnPropertyDescriptor(target, CONFIG_KEY) == null) {
Object.defineProperty(target, CONFIG_KEY, { value: {} });
}
const config = target[CONFIG_KEY];
const propertyKey = propertyKeyOrSymbol.toString();
if (typeof config[propertyKey] !== "undefined") {
return config[propertyKey];
}
const valuesMap = /* @__PURE__ */ new WeakMap();
config[propertyKey] = { setters: [], getters: [], observers: [], valuesMap };
const descriptor = Object.getOwnPropertyDescriptor(target, propertyKeyOrSymbol);
const prevSet = descriptor?.set;
const prevGet = descriptor?.get;
const getter = function() {
let value = prevGet ? prevGet.call(this) : valuesMap.get(this);
for (const transformFn of config[propertyKey].getters) {
value = transformFn(this, propertyKeyOrSymbol, value);
if (value === BREAK_TRANSFORM_CHAIN) {
return;
}
}
return value;
};
const setter = function(value) {
const { setters, observers } = config[propertyKey];
let oldValue;
if (setters.some((f) => f.length > 2)) {
oldValue = prevGet ? prevGet.call(this) : valuesMap.get(this);
}
for (const transformFn of setters) {
value = transformFn(this, propertyKeyOrSymbol, value, oldValue);
if (value === BREAK_TRANSFORM_CHAIN) {
return;
}
}
if (prevSet) {
prevSet.call(this, value);
} else {
valuesMap.set(this, value);
}
for (const observerFn of observers) {
observerFn(this, value, oldValue);
}
};
Object.defineProperty(target, propertyKeyOrSymbol, {
set: setter,
get: getter,
enumerable: true,
configurable: false
});
return config[propertyKey];
}
function addTransformToInstanceProperty(setTransform, getTransform, configMetadata) {
return (target, propertyKeyOrSymbol) => {
const config = initialiseConfig(target, propertyKeyOrSymbol);
config.setters.push(setTransform);
if (getTransform) {
config.getters.unshift(getTransform);
}
if (configMetadata) {
Object.assign(config, configMetadata);
}
};
}
function addObserverToInstanceProperty(setObserver) {
return (target, propertyKeyOrSymbol) => {
initialiseConfig(target, propertyKeyOrSymbol).observers.push(setObserver);
};
}
function isDecoratedObject(target) {
return typeof target !== "undefined" && CONFIG_KEY in target;
}
function listDecoratedProperties(target) {
const targets = /* @__PURE__ */ new Set();
while (isDecoratedObject(target)) {
targets.add(target?.[CONFIG_KEY]);
target = Object.getPrototypeOf(target);
}
return Array.from(targets).flatMap((configMap) => Object.keys(configMap));
}
function extractDecoratedProperties(target) {
return listDecoratedProperties(target).reduce((result, key) => {
result[key] = target[key] ?? null;
return result;
}, {});
}
function extractDecoratedPropertyMetadata(target, propertyKeyOrSymbol) {
const propertyKey = propertyKeyOrSymbol.toString();
while (isDecoratedObject(target)) {
const config = target[CONFIG_KEY];
if (Object.hasOwn(config, propertyKey)) {
return config[propertyKey];
}
target = Object.getPrototypeOf(target);
}
}
// packages/ag-charts-community/src/util/object.ts
function objectsEqual(a, b) {
if (Array.isArray(a)) {
if (!Array.isArray(b))
return false;
if (a.length !== b.length)
return false;
return a.every((av, i) => objectsEqual(av, b[i]));
} else if (isPlainObject(a)) {
if (!isPlainObject(b))
return false;
return objectsEqualWith(a, b, objectsEqual);
}
return a === b;
}
function objectsEqualWith(a, b, cmp2) {
for (const key of Object.keys(b)) {
if (!(key in a))
return false;
}
for (const key of Object.keys(a)) {
if (!(key in b))
return false;
if (!cmp2(a[key], b[key]))
return false;
}
return true;
}
function mergeDefaults(...sources) {
const target = {};
for (const source of sources) {
if (!isObject(source))
continue;
const keys = isDecoratedObject(source) ? listDecoratedProperties(source) : Object.keys(source);
for (const key of keys) {
if (isPlainObject(target[key]) && isPlainObject(source[key])) {
target[key] = mergeDefaults(target[key], source[key]);
} else {
target[key] ?? (target[key] = source[key]);
}
}
}
return target;
}
function merge(...sources) {
const target = {};
for (const source of sources) {
if (!isObject(source))
continue;
const keys = isDecoratedObject(source) ? listDecoratedProperties(source) : Object.keys(source);
for (const key of keys) {
if (isPlainObject(target[key]) && isPlainObject(source[key])) {
target[key] = merge(target[key], source[key]);
} else if (!(key in target)) {
target[key] ?? (target[key] = source[key]);
}
}
}
return target;
}
function without(object3, keys) {
const clone2 = { ...object3 };
for (const key of keys) {
delete clone2[key];
}
return clone2;
}
function getPath(object3, path) {
const pathArray = isArray(path) ? path : path.split(".");
return pathArray.reduce((value, pathKey) => value[pathKey], object3);
}
var SKIP_JS_BUILTINS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
function setPath(object3, path, newValue) {
const pathArray = isArray(path) ? path.slice() : path.split(".");
const lastKey = pathArray.pop();
if (pathArray.some((p) => SKIP_JS_BUILTINS.has(p)))
return;
const lastObject = pathArray.reduce((value, pathKey) => value[pathKey], object3);
lastObject[lastKey] = newValue;
return lastObject[lastKey];
}
function partialAssign(keysToCopy, target, source) {
if (source === void 0) {
return target;
}
for (const key of keysToCopy) {
const value = source[key];
if (value !== void 0) {
target[key] = value;
}
}
return target;
}
// packages/ag-charts-community/src/motion/easing.ts
var linear = (n) => n;
var easeOut = (n) => Math.sin(n * Math.PI / 2);
var inverseEaseOut = (x) => 2 * Math.asin(x) / Math.PI;
// packages/ag-charts-community/src/motion/animation.ts
var QUICK_TRANSITION = 0.2;
var PHASE_ORDER = ["initial", "remove", "update", "add", "trailing", "end", "none"];
var PHASE_METADATA = {
initial: {
animationDuration: 1,
animationDelay: 0
},
add: {
animationDuration: 0.25,
animationDelay: 0.75
},
remove: {
animationDuration: 0.25,
animationDelay: 0
},
update: {
animationDuration: 0.5,
animationDelay: 0.25
},
trailing: {
animationDuration: QUICK_TRANSITION,
animationDelay: 1,
skipIfNoEarlierAnimations: true
},
end: {
animationDelay: 1 + QUICK_TRANSITION,
animationDuration: 0,
skipIfNoEarlierAnimations: true
},
none: {
animationDuration: 0,
animationDelay: 0
}
};
function isNodeArray(array3) {
return array3.every((n) => n instanceof Node);
}
function deconstructSelectionsOrNodes(selectionsOrNodes) {
return isNodeArray(selectionsOrNodes) ? { nodes: selectionsOrNodes, selections: [] } : { nodes: [], selections: selectionsOrNodes };
}
function animationValuesEqual(a, b) {
if (a === b) {
return true;
} else if (Array.isArray(a) && Array.isArray(b)) {
return a.length === b.length && a.every((v, i) => animationValuesEqual(v, b[i]));
} else if (isInterpolating(a) && isInterpolating(b)) {
return a.equals(b);
} else if (isPlainObject2(a) && isPlainObject2(b)) {
return objectsEqualWith(a, b, animationValuesEqual);
}
return false;
}
var Animation = class {
constructor(opts) {
this.isComplete = false;
this.elapsed = 0;
this.iteration = 0;
this.isPlaying = false;
this.isReverse = false;
this.id = opts.id;
this.groupId = opts.groupId;
this.autoplay = opts.autoplay ?? true;
this.ease = opts.ease ?? linear;
this.phase = opts.phase;
const durationProportion = opts.duration ?? PHASE_METADATA[this.phase].animationDuration;
this.duration = durationProportion * opts.defaultDuration;
this.delay = (opts.delay ?? 0) * opts.defaultDuration;
this.onComplete = opts.onComplete;
this.onPlay = opts.onPlay;
this.onStop = opts.onStop;
this.onUpdate = opts.onUpdate;
this.interpolate = this.createInterpolator(opts.from, opts.to);
this.from = opts.from;
if (opts.skip === true) {
this.onUpdate?.(opts.to, false, this);
this.onStop?.(this);
this.onComplete?.(this);
this.isComplete = true;
}
if (opts.collapsable !== false) {
this.duration = this.checkCollapse(opts, this.duration);
}
}
checkCollapse(opts, calculatedDuration) {
return animationValuesEqual(opts.from, opts.to) ? 0 : calculatedDuration;
}
play(initialUpdate = false) {
if (this.isPlaying || this.isComplete)
return;
this.isPlaying = true;
this.onPlay?.(this);
if (!this.autoplay)
return;
this.autoplay = false;
if (!initialUpdate)
return;
this.onUpdate?.(this.from, true, this);
}
stop() {
this.isPlaying = false;
if (!this.isComplete) {
this.isComplete = true;
this.onStop?.(this);
}
}
update(time2) {
if (this.isComplete)
return time2;
if (!this.isPlaying && this.autoplay) {
this.play(true);
}
const previousElapsed = this.elapsed;
this.elapsed += time2;
if (this.delay > this.elapsed)
return 0;
const value = this.interpolate(this.isReverse ? 1 - this.delta : this.delta);
this.onUpdate?.(value, false, this);
const totalDuration = this.delay + this.duration;
if (this.elapsed >= totalDuration) {
this.stop();
this.isComplete = true;
this.onComplete?.(this);
return time2 - (totalDuration - previousElapsed);
}
return 0;
}
get delta() {
return this.ease(clamp3(0, (this.elapsed - this.delay) / this.duration, 1));
}
createInterpolator(from2, to) {
if (typeof to !== "object" || isInterpolating(to)) {
return this.interpolateValue(from2, to);
}
const interpolatorEntries = [];
for (const key of Object.keys(to)) {
const interpolator = this.interpolateValue(from2[key], to[key]);
if (interpolator != null) {
interpolatorEntries.push([key, interpolator]);
}
}
return (d) => {
const result = {};
for (const [key, interpolator] of interpolatorEntries) {
result[key] = interpolator(d);
}
return result;
};
}
interpolateValue(a, b) {
if (a == null || b == null) {
return;
} else if (isInterpolating(a)) {
return (d) => a[interpolate](b, d);
}
try {
switch (typeof a) {
case "number":
return interpolateNumber(a, b);
case "string":
return interpolateColor(a, b);
case "boolean":
if (a === b) {
return () => a;
}
break;
case "object":
return () => a;
}
} catch {
}
throw new Error(`Unable to interpolate values: ${a}, ${b}`);
}
};
// packages/ag-charts-community/src/motion/fromToMotion.ts
var NODE_UPDATE_STATE_TO_PHASE_MAPPING = {
added: "add",
updated: "update",
removed: "remove",
unknown: "initial",
"no-op": "none"
};
function fromToMotion(groupId, subId, animationManager, selectionsOrNodes, fns, getDatumId, diff2) {
const { fromFn, toFn, applyFn = (node, props) => node.setProperties(props) } = fns;
const { nodes, selections } = deconstructSelectionsOrNodes(selectionsOrNodes);
const processNodes = (liveNodes, subNodes) => {
let prevFromProps;
let liveNodeIndex = 0;
let nodeIndex = 0;
for (const node of subNodes) {
const isLive = liveNodes[liveNodeIndex] === node;
const ctx = {
last: nodeIndex >= subNodes.length - 1,
lastLive: liveNodeIndex >= liveNodes.length - 1,
prev: subNodes[nodeIndex - 1],
prevFromProps,
prevLive: liveNodes[liveNodeIndex - 1],
next: subNodes[nodeIndex + 1],
nextLive: liveNodes[liveNodeIndex + (isLive ? 1 : 0)]
};
const animationId = `${groupId}_${subId}_${node.id}`;