Files
sigpro-grid/node_modules/ag-charts-enterprise/dist/package/main.esm.mjs
2026-03-17 08:44:54 +01:00

49701 lines
1.7 MiB
Executable File

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-enterprise/src/main.ts
import { ModuleRegistry as ModuleRegistry3, enterpriseRegistry as enterpriseRegistry2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/background/background.ts
import { _ModuleSupport as _ModuleSupport2 } from "ag-charts-community";
import { ActionOnSet, ChartUpdateType, Property as Property2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/image/image.ts
import { _ModuleSupport } from "ag-charts-community";
import {
BaseProperties,
ObserveChanges,
Property,
ProxyProperty,
calculatePlacement,
createElement
} from "ag-charts-core";
var Image = class extends BaseProperties {
constructor() {
super();
this.opacity = 1;
this.loadedSynchronously = true;
this.containerWidth = 0;
this.containerHeight = 0;
this.onLoad = void 0;
this.onImageLoad = () => {
if (this.loadedSynchronously) {
return;
}
this.node.visible = false;
this.performLayout(this.containerWidth, this.containerHeight);
this.onLoad?.();
};
this.imageElement = createElement("img");
this.imageElement.onload = this.onImageLoad;
this.node = new _ModuleSupport.Image(this.imageElement);
}
get complete() {
return this.imageElement.width > 0 && this.imageElement.height > 0;
}
performLayout(containerWidth, containerHeight) {
this.containerWidth = containerWidth;
this.containerHeight = containerHeight;
const container = { width: containerWidth, height: containerHeight };
const placement = calculatePlacement(this.imageElement.width, this.imageElement.height, container, this);
this.node.setProperties(
this.complete ? {
visible: true,
opacity: this.opacity,
...placement
} : { visible: false }
);
return placement;
}
};
__decorateClass([
Property
], Image.prototype, "top", 2);
__decorateClass([
Property
], Image.prototype, "right", 2);
__decorateClass([
Property
], Image.prototype, "bottom", 2);
__decorateClass([
Property
], Image.prototype, "left", 2);
__decorateClass([
Property
], Image.prototype, "width", 2);
__decorateClass([
Property
], Image.prototype, "height", 2);
__decorateClass([
Property
], Image.prototype, "opacity", 2);
__decorateClass([
ProxyProperty("imageElement.src"),
ObserveChanges((target) => target.loadedSynchronously = target.complete)
], Image.prototype, "url", 2);
// packages/ag-charts-enterprise/src/features/background/background.ts
var Background = class extends _ModuleSupport2.Background {
constructor() {
super(...arguments);
this.image = new Image();
}
onLayoutComplete(event) {
super.onLayoutComplete(event);
if (this.image) {
const { width, height } = event.chart;
this.image.performLayout(width, height);
}
}
onImageLoad() {
this.ctx.updateService.update(ChartUpdateType.SCENE_RENDER);
}
};
__decorateClass([
Property2,
ActionOnSet({
newValue(image) {
this.node.appendChild(image.node);
image.onLoad = () => this.onImageLoad();
},
oldValue(image) {
image.node.remove();
image.onLoad = void 0;
}
})
], Background.prototype, "image", 2);
// packages/ag-charts-enterprise/src/features/foreground/foreground.ts
import { _ModuleSupport as _ModuleSupport3 } from "ag-charts-community";
import {
ActionOnSet as ActionOnSet2,
ChartUpdateType as ChartUpdateType2,
Property as Property3,
ProxyPropertyOnWrite,
ZIndexMap
} from "ag-charts-core";
var Foreground = class extends _ModuleSupport3.Background {
constructor() {
super(...arguments);
this.image = new Image();
this.fill = "transparent";
this.fillOpacity = void 0;
}
createNode() {
return new _ModuleSupport3.Group({ name: "foreground", zIndex: ZIndexMap.FOREGROUND });
}
onLayoutComplete(event) {
super.onLayoutComplete(event);
const { width, height } = event.chart;
const placement = this.image.performLayout(width, height);
if (this.text) {
this.updateTextNode(placement);
}
}
onImageLoad() {
this.ctx.updateService.update(ChartUpdateType2.SCENE_RENDER);
}
updateTextNode(placement) {
const { textNode } = this;
textNode.fontWeight = "bold";
textNode.fontFamily = "Impact, sans-serif";
textNode.fontSize = 19;
textNode.opacity = 0.7;
textNode.fill = "#9b9b9b";
textNode.textBaseline = "top";
const { width } = textNode.getBBox();
const textPadding = 10;
textNode.x = placement.x + placement.width / 2 - width / 2;
textNode.y = placement.y + placement.height + textPadding;
}
};
__decorateClass([
Property3,
ActionOnSet2({
newValue(image) {
this.node.appendChild(image.node);
image.onLoad = () => this.onImageLoad();
},
oldValue(image) {
image.node.remove();
image.onLoad = void 0;
}
})
], Foreground.prototype, "image", 2);
__decorateClass([
Property3,
ProxyPropertyOnWrite("rectNode", "fill")
], Foreground.prototype, "fill", 2);
__decorateClass([
Property3,
ProxyPropertyOnWrite("rectNode", "fillOpacity")
], Foreground.prototype, "fillOpacity", 2);
// packages/ag-charts-enterprise/src/license/md5.ts
var MD5 = class {
constructor() {
this.ieCompatibility = false;
}
init() {
this.ieCompatibility = this.md5("hello") != "5d41402abc4b2a76b9719d911017c592";
}
md5cycle(x, k) {
let a = x[0], b = x[1], c = x[2], d = x[3];
a = this.ff(a, b, c, d, k[0], 7, -680876936);
d = this.ff(d, a, b, c, k[1], 12, -389564586);
c = this.ff(c, d, a, b, k[2], 17, 606105819);
b = this.ff(b, c, d, a, k[3], 22, -1044525330);
a = this.ff(a, b, c, d, k[4], 7, -176418897);
d = this.ff(d, a, b, c, k[5], 12, 1200080426);
c = this.ff(c, d, a, b, k[6], 17, -1473231341);
b = this.ff(b, c, d, a, k[7], 22, -45705983);
a = this.ff(a, b, c, d, k[8], 7, 1770035416);
d = this.ff(d, a, b, c, k[9], 12, -1958414417);
c = this.ff(c, d, a, b, k[10], 17, -42063);
b = this.ff(b, c, d, a, k[11], 22, -1990404162);
a = this.ff(a, b, c, d, k[12], 7, 1804603682);
d = this.ff(d, a, b, c, k[13], 12, -40341101);
c = this.ff(c, d, a, b, k[14], 17, -1502002290);
b = this.ff(b, c, d, a, k[15], 22, 1236535329);
a = this.gg(a, b, c, d, k[1], 5, -165796510);
d = this.gg(d, a, b, c, k[6], 9, -1069501632);
c = this.gg(c, d, a, b, k[11], 14, 643717713);
b = this.gg(b, c, d, a, k[0], 20, -373897302);
a = this.gg(a, b, c, d, k[5], 5, -701558691);
d = this.gg(d, a, b, c, k[10], 9, 38016083);
c = this.gg(c, d, a, b, k[15], 14, -660478335);
b = this.gg(b, c, d, a, k[4], 20, -405537848);
a = this.gg(a, b, c, d, k[9], 5, 568446438);
d = this.gg(d, a, b, c, k[14], 9, -1019803690);
c = this.gg(c, d, a, b, k[3], 14, -187363961);
b = this.gg(b, c, d, a, k[8], 20, 1163531501);
a = this.gg(a, b, c, d, k[13], 5, -1444681467);
d = this.gg(d, a, b, c, k[2], 9, -51403784);
c = this.gg(c, d, a, b, k[7], 14, 1735328473);
b = this.gg(b, c, d, a, k[12], 20, -1926607734);
a = this.hh(a, b, c, d, k[5], 4, -378558);
d = this.hh(d, a, b, c, k[8], 11, -2022574463);
c = this.hh(c, d, a, b, k[11], 16, 1839030562);
b = this.hh(b, c, d, a, k[14], 23, -35309556);
a = this.hh(a, b, c, d, k[1], 4, -1530992060);
d = this.hh(d, a, b, c, k[4], 11, 1272893353);
c = this.hh(c, d, a, b, k[7], 16, -155497632);
b = this.hh(b, c, d, a, k[10], 23, -1094730640);
a = this.hh(a, b, c, d, k[13], 4, 681279174);
d = this.hh(d, a, b, c, k[0], 11, -358537222);
c = this.hh(c, d, a, b, k[3], 16, -722521979);
b = this.hh(b, c, d, a, k[6], 23, 76029189);
a = this.hh(a, b, c, d, k[9], 4, -640364487);
d = this.hh(d, a, b, c, k[12], 11, -421815835);
c = this.hh(c, d, a, b, k[15], 16, 530742520);
b = this.hh(b, c, d, a, k[2], 23, -995338651);
a = this.ii(a, b, c, d, k[0], 6, -198630844);
d = this.ii(d, a, b, c, k[7], 10, 1126891415);
c = this.ii(c, d, a, b, k[14], 15, -1416354905);
b = this.ii(b, c, d, a, k[5], 21, -57434055);
a = this.ii(a, b, c, d, k[12], 6, 1700485571);
d = this.ii(d, a, b, c, k[3], 10, -1894986606);
c = this.ii(c, d, a, b, k[10], 15, -1051523);
b = this.ii(b, c, d, a, k[1], 21, -2054922799);
a = this.ii(a, b, c, d, k[8], 6, 1873313359);
d = this.ii(d, a, b, c, k[15], 10, -30611744);
c = this.ii(c, d, a, b, k[6], 15, -1560198380);
b = this.ii(b, c, d, a, k[13], 21, 1309151649);
a = this.ii(a, b, c, d, k[4], 6, -145523070);
d = this.ii(d, a, b, c, k[11], 10, -1120210379);
c = this.ii(c, d, a, b, k[2], 15, 718787259);
b = this.ii(b, c, d, a, k[9], 21, -343485551);
x[0] = this.add32(a, x[0]);
x[1] = this.add32(b, x[1]);
x[2] = this.add32(c, x[2]);
x[3] = this.add32(d, x[3]);
}
cmn(q, a, b, x, s, t) {
a = this.add32(this.add32(a, q), this.add32(x, t));
return this.add32(a << s | a >>> 32 - s, b);
}
ff(a, b, c, d, x, s, t) {
return this.cmn(b & c | ~b & d, a, b, x, s, t);
}
gg(a, b, c, d, x, s, t) {
return this.cmn(b & d | c & ~d, a, b, x, s, t);
}
hh(a, b, c, d, x, s, t) {
return this.cmn(b ^ c ^ d, a, b, x, s, t);
}
ii(a, b, c, d, x, s, t) {
return this.cmn(c ^ (b | ~d), a, b, x, s, t);
}
md51(s) {
const n = s.length;
const state = [1732584193, -271733879, -1732584194, 271733878];
let i;
for (i = 64; i <= s.length; i += 64) {
this.md5cycle(state, this.md5blk(s.substring(i - 64, i)));
}
s = s.substring(i - 64);
const tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (i = 0; i < s.length; i++) {
tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
}
tail[i >> 2] |= 128 << (i % 4 << 3);
if (i > 55) {
this.md5cycle(state, tail);
for (i = 0; i < 16; i++) {
tail[i] = 0;
}
}
tail[14] = n * 8;
this.md5cycle(state, tail);
return state;
}
/* there needs to be support for Unicode here, * unless we pretend that we can redefine the MD-5
* algorithm for multi-byte characters (perhaps by adding every four 16-bit characters and
* shortening the sum to 32 bits). Otherwise I suggest performing MD-5 as if every character
* was two bytes--e.g., 0040 0025 = @%--but then how will an ordinary MD-5 sum be matched?
* There is no way to standardize text to something like UTF-8 before transformation; speed cost is
* utterly prohibitive. The JavaScript standard itself needs to look at this: it should start
* providing access to strings as preformed UTF-8 8-bit unsigned value arrays.
*/
md5blk(s) {
const md5blks = [];
for (let i = 0; i < 64; i += 4) {
md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
}
return md5blks;
}
rhex(n) {
const hex_chr = "0123456789abcdef".split("");
let s = "", j = 0;
for (; j < 4; j++) {
s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
}
return s;
}
hex(x) {
for (let i = 0; i < x.length; i++) {
x[i] = this.rhex(x[i]);
}
return x.join("");
}
md5(s) {
return this.hex(this.md51(s));
}
add32(a, b) {
return this.ieCompatibility ? this.add32Compat(a, b) : this.add32Std(a, b);
}
/* this function is much faster, so if possible we use it. Some IEs are the only ones I know of that
need the idiotic second function, generated by an if clause. */
add32Std(a, b) {
return a + b & 4294967295;
}
add32Compat(x, y) {
const lsw = (x & 65535) + (y & 65535), msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return msw << 16 | lsw & 65535;
}
};
// packages/ag-charts-enterprise/src/license/licenseManager.ts
function missingOrEmpty(value) {
return value == null || value.length === 0;
}
var WATERMARK_SVG_DATA_URL = `data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjU4IiBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMjU4IDQwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMjUuNzc5IDI4LjY1N0gxMy4zNTlMMTEuMTczIDM0LjAxMkg1LjY3Mjk3TDE3LjE4MiA3LjA1OTk5SDIxLjk1M0wzMy40NjIgMzQuMDEySDI3Ljk2MkwyNS43NzYgMjguNjU3SDI1Ljc3OVpNMjQuMDY4IDI0LjM5N0wxOS41ODggMTMuNDM0TDE1LjEwNyAyNC4zOTdIMjQuMDY4Wk02Mi4wOTIgMTguODIzSDQ5LjgxN1YyMy4wODZINTYuNzc1QzU2LjU1NSAyNS4yMjIgNTUuNzU1IDI2LjkyNyA1NC4zNzIgMjguMjAyQzUyLjk4OSAyOS40NzYgNTEuMTY2IDMwLjExNSA0OC45MDkgMzAuMTE1QzQ3LjYyMiAzMC4xMTUgNDYuNDUgMjkuODg1IDQ1LjM5MyAyOS40MjNDNDQuMzU4MyAyOC45NzgxIDQzLjQzMjYgMjguMzEzOCA0Mi42OCAyNy40NzZDNDEuOTI3IDI2LjYzOSA0MS4zNDQgMjUuNjMxIDQwLjkzMSAyNC40NTNDNDAuNTE5IDIzLjI3NSA0MC4zMTEgMjEuOTcgNDAuMzExIDIwLjUzN0M0MC4zMTEgMTkuMTA1IDQwLjUxNiAxNy44IDQwLjkzMSAxNi42MjFDNDEuMzQ0IDE1LjQ0MyA0MS45MjcgMTQuNDM2IDQyLjY4IDEzLjU5OEM0My40Mzc2IDEyLjc1NzcgNDQuMzY5NiAxMi4wOTMyIDQ1LjQxMSAxMS42NTFDNDYuNDc4IDExLjE4OSA0Ny42NTYgMTAuOTYgNDguOTQ2IDEwLjk2QzUxLjYxMiAxMC45NiA1My42MzcgMTEuNjAyIDU1LjAyIDEyLjg4NUw1OC4zIDkuNjA0OTlDNTUuODE3IDcuNjY5OTkgNTIuNjc2IDYuNjk5OTkgNDguODcyIDYuNjk5OTlDNDYuNzYgNi42OTk5OSA0NC44NTMgNy4wMzQ5OSA0My4xNTQgNy43MDA5OUM0MS40NTUgOC4zNjc5OSAzOS45OTggOS4zMDM5OSAzOC43ODMgMTAuNTA0QzM3LjU2NyAxMS43MDcgMzYuNjM0IDEzLjE1OCAzNS45NzcgMTQuODU3QzM1LjMxOSAxNi41NTYgMzQuOTk0IDE4LjQ1MSAzNC45OTQgMjAuNTRDMzQuOTk0IDIyLjYzIDM1LjMyOSAyNC40OTQgMzUuOTk1IDI2LjIwNUMzNi42NjIgMjcuOTE2IDM3LjYwNSAyOS4zNzQgMzguODE3IDMwLjU3N0M0MC4wMzIgMzEuNzggNDEuNDg2IDMyLjcxMyA0My4xODggMzMuMzgzQzQ0Ljg4OCAzNC4wNDkgNDYuNzgyIDM0LjM4NCA0OC44NzIgMzQuMzg0QzUwLjk2MSAzNC4zODQgNTIuNzUgMzQuMDQ5IDU0LjM5IDMzLjM4M0M1Ni4wMzEgMzIuNzE2IDU3LjQyNiAzMS43OCA1OC41NzkgMzAuNTc3QzU5LjczMyAyOS4zNzQgNjAuNjE5IDI3LjkxNiA2MS4yMzkgMjYuMjA1QzYxLjg2IDI0LjQ5NCA2Mi4xNyAyMi42MDUgNjIuMTcgMjAuNTRDNjIuMTY5NiAxOS45Njg4IDYyLjE0NDUgMTkuMzk4IDYyLjA5NSAxOC44MjlMNjIuMDkyIDE4LjgyM1pNMTUxLjgxIDE2Ljk4MUMxNTMuNDEgMTQuNjA5IDE1Ny40MTkgMTQuMzU4IDE1OS4wMjIgMTQuMzU4VjE4LjkxQzE1Ni45NTcgMTguOTEgMTU0Ljk4NSAxOC45OTYgMTUzLjc1NyAxOS44OTJDMTUyLjUyOSAyMC43OTIgMTUxLjkxOSAyMS45ODIgMTUxLjkxOSAyMy40NjRWMzMuOTlIMTQ2Ljk2NFYxNC4zNThIMTUxLjczNkwxNTEuODEgMTYuOTgxWk0xNDMuMDExIDE0LjM2MVYzNC4wMzFIMTM4LjI0TDEzOC4xMzEgMzEuMDQ1QzEzNy40NjYgMzIuMDc2IDEzNi41NTEgMzIuOTIxOSAxMzUuNDcxIDMzLjUwNEMxMzQuMzc2IDM0LjA5OSAxMzMuMDY4IDM0LjM5NiAxMzEuNTM2IDM0LjM5NkMxMzAuMiAzNC4zOTYgMTI4Ljk2MyAzNC4xNTIgMTI3LjgyMiAzMy42NjhDMTI2LjcgMzMuMTk2NCAxMjUuNjg5IDMyLjQ5NSAxMjQuODU1IDMxLjYwOUMxMjQuMDE4IDMwLjcyMiAxMjMuMzU0IDI5LjY2MiAxMjIuODcxIDI4LjQyMkMxMjIuMzg0IDI3LjE4NSAxMjIuMTQyIDI1LjgxMSAxMjIuMTQyIDI0LjMwNEMxMjIuMTQyIDIyLjc5OCAxMjIuMzg0IDIxLjM3OCAxMjIuODcxIDIwLjExNkMxMjMuMzU3IDE4Ljg1NCAxMjQuMDE4IDE3Ljc3MiAxMjQuODU1IDE2Ljg3M0MxMjUuNjg4IDE1Ljk3NjQgMTI2LjY5OCAxNS4yNjM2IDEyNy44MjIgMTQuNzhDMTI4Ljk2MyAxNC4yODEgMTMwLjIwMyAxNC4wMzMgMTMxLjUzNiAxNC4wMzNDMTMzLjA0MyAxNC4wMzMgMTM0LjMzIDE0LjMxOCAxMzUuMzk3IDE0Ljg4OEMxMzYuNDYyIDE1LjQ1ODkgMTM3LjM3NSAxNi4yNzggMTM4LjA1NyAxNy4yNzZWMTQuMzYxSDE0My4wMTFaTTEzMi42MzEgMzAuMTMzQzEzNC4yNTYgMzAuMTMzIDEzNS41NjcgMjkuNTk0IDEzNi41NjUgMjguNTEyQzEzNy41NjEgMjcuNDMgMTM4LjA2IDI1Ljk5MSAxMzguMDYgMjQuMTk2QzEzOC4wNiAyMi40MDEgMTM3LjU2MSAyMC45OSAxMzYuNTY1IDE5Ljg5OUMxMzUuNTcgMTguODA3IDEzNC4yNTkgMTguMjU4IDEzMi42MzEgMTguMjU4QzEzMS4wMDMgMTguMjU4IDEyOS43MjkgMTguODA0IDEyOC43MzQgMTkuODk5QzEyNy43MzggMjAuOTkzIDEyNy4yMzkgMjIuNDM4IDEyNy4yMzkgMjQuMjMzQzEyNy4yMzkgMjYuMDI4IDEyNy43MzUgMjcuNDMzIDEyOC43MzQgMjguNTE1QzEyOS43MjkgMjkuNTk0IDEzMS4wMjggMzAuMTM2IDEzMi42MzEgMzAuMTM2VjMwLjEzM1pNOTMuNjk4IDI3Ljg3NkM5My41Nzk1IDI4LjAwMjUgOTMuNDU2NCAyOC4xMjQ2IDkzLjMyOSAyOC4yNDJDOTEuOTQ3IDI5LjUxNiA5MC4xMjMgMzAuMTU1IDg3Ljg2NiAzMC4xNTVDODYuNTggMzAuMTU1IDg1LjQwOCAyOS45MjYgODQuMzUgMjkuNDY0QzgzLjMxNTUgMjkuMDE4OSA4Mi4zODk4IDI4LjM1NDYgODEuNjM3IDI3LjUxN0M4MC44ODQgMjYuNjc5IDgwLjMwMSAyNS42NzIgNzkuODg5IDI0LjQ5NEM3OS40NzYgMjMuMzE1IDc5LjI2OSAyMi4wMSA3OS4yNjkgMjAuNTc4Qzc5LjI2OSAxOS4xNDUgNzkuNDczIDE3Ljg0IDc5Ljg4OSAxNi42NjJDODAuMzAxIDE1LjQ4NCA4MC44ODQgMTQuNDc2IDgxLjYzNyAxMy42MzlDODIuMzk0OSAxMi43OTg3IDgzLjMyNzMgMTIuMTM0MiA4NC4zNjkgMTEuNjkyQzg1LjQzNiAxMS4yMyA4Ni42MTQgMTEgODcuOTAzIDExQzkwLjU3IDExIDkyLjU5NSAxMS42NDIgOTMuOTc3IDEyLjkyNkw5Ny4yNTggOS42NDQ5OUM5NC43NzQgNy43MTA5OSA5MS42MzMgNi43Mzk5OSA4Ny44MjkgNi43Mzk5OUM4NS43MTggNi43Mzk5OSA4My44MTEgNy4wNzQ5OSA4Mi4xMTIgNy43NDE5OUM4MC40MTMgOC40MDc5OSA3OC45NTYgOS4zNDQ5OSA3Ny43NCAxMC41NDVDNzYuNTI1IDExLjc0NyA3NS41OTIgMTMuMTk5IDc0LjkzNCAxNC44OThDNzQuMjc3IDE2LjU5NyA3My45NTEgMTguNDkxIDczLjk1MSAyMC41ODFDNzMuOTUxIDIyLjY3IDc0LjI4NiAyNC41MzQgNzQuOTUzIDI2LjI0NUM3NS42MTkgMjcuOTU3IDc2LjU2MiAyOS40MTQgNzcuNzc0IDMwLjYxN0M3OC45OSAzMS44MiA4MC40NDQgMzIuNzUzIDgyLjE0NiAzMy40MjNDODMuODQ1IDM0LjA5IDg1LjczOSAzNC40MjQgODcuODI5IDM0LjQyNEM4OS45MTkgMzQuNDI0IDkxLjcwOCAzNC4wOSA5My4zNDggMzMuNDIzQzk0LjcxOCAzMi44NjUgOTUuOTE4IDMyLjEyMSA5Ni45NDggMzEuMTkxQzk3LjE0OSAzMS4wMDggOTcuMzQ4IDMwLjgxNSA5Ny41MzcgMzAuNjJMOTMuNzAxIDI3Ljg4NUw5My42OTggMjcuODc2Wk0xMTAuODAyIDE0LjAxNUMxMDkuMTk5IDE0LjAxNSAxMDYuODM2IDE0LjQ3MSAxMDUuNjExIDE2LjE1OEwxMDUuNTM3IDYuMDE1OTlIMTAwLjc2NVYzMy45MzlIMTA1LjcyVjIyLjY0MUMxMDUuNzcxIDIxLjQ2MDcgMTA2LjI4OCAyMC4zNDg4IDEwNy4xNTcgMTkuNTQ4OUMxMDguMDI3IDE4Ljc0OTEgMTA5LjE3OCAxOC4zMjY2IDExMC4zNTggMTguMzc0QzExMy4zOTcgMTguMzc0IDExNC4yNjggMjEuMTU5IDExNC4yNjggMjIuNjQxVjMzLjkzOUgxMTkuMjIzVjIxLjA1OUMxMTkuMjIzIDIxLjA1OSAxMTkuMTQyIDE0LjAxNSAxMTAuODAyIDE0LjAxNVpNMTczLjc2MyAxNC4zNThIMTY5Ljk5OVY4LjcxNDk5SDE2NS4wNDhWMTQuMzU4SDE2MS4yODRWMTguOTE2SDE2NS4wNDhWMzQuMDAzSDE2OS45OTlWMTguOTE2SDE3My43NjNWMTQuMzU4Wk0xOTAuNzg3IDI1LjI2MkMxOTAuMTI5IDI0LjUwMTQgMTg5LjMwNyAyMy44OTk0IDE4OC4zODQgMjMuNTAxQzE4Ny40ODggMjMuMTE3IDE4Ni4zMzEgMjIuNzMyIDE4NC45NDggMjIuMzY0QzE4NC4xNjUgMjIuMTQzOSAxODMuMzkgMjEuODk3OCAxODIuNjIzIDIxLjYyNkMxODIuMTYzIDIxLjQ2MjEgMTgxLjc0MSAyMS4yMDY2IDE4MS4zODMgMjAuODc1QzE4MS4yMzUgMjAuNzQyMSAxODEuMTE4IDIwLjU3ODkgMTgxLjAzOSAyMC4zOTY0QzE4MC45NjEgMjAuMjE0IDE4MC45MjIgMjAuMDE2NiAxODAuOTI3IDE5LjgxOEMxODAuOTI3IDE5LjI3MiAxODEuMTU2IDE4Ljg0NCAxODEuNjI1IDE4LjUxQzE4Mi4xMjEgMTguMTU2IDE4Mi44NjIgMTcuOTc2IDE4My44MjYgMTcuOTc2QzE4NC43OSAxNy45NzYgMTg1LjU4NyAxOC4yMDkgMTg2LjE0OCAxOC42NjhDMTg2LjcwNiAxOS4xMjQgMTg3LjAwNyAxOS43MjUgMTg3LjA3MiAyMC41TDE4Ny4wOTQgMjAuNzgySDE5MS42MzNMMTkxLjYxNyAyMC40NkMxOTEuNTIxIDE4LjQ4NSAxOTAuNzcxIDE2LjkgMTg5LjM4NSAxNS43NUMxODguMDEyIDE0LjYxMiAxODYuMTg1IDE0LjAzMyAxODMuOTYyIDE0LjAzM0MxODIuNDc3IDE0LjAzMyAxODEuMTQxIDE0LjI4NyAxNzkuOTk0IDE0Ljc4NkMxNzguODMxIDE1LjI5MSAxNzcuOTI2IDE1Ljk5NSAxNzcuMjk2IDE2Ljg4MkMxNzYuNjczIDE3Ljc0NTUgMTc2LjMzOCAxOC43ODQgMTc2LjM0MSAxOS44NDlDMTc2LjM0MSAyMS4xNjcgMTc2LjY5OCAyMi4yNDkgMTc3LjM5OSAyMy4wNjRDMTc4LjA2IDIzLjg0MzIgMTc4Ljg5OCAyNC40NTM0IDE3OS44NDIgMjQuODQ0QzE4MC43NDQgMjUuMjE2IDE4MS45MjggMjUuNjA3IDE4My4zNjEgMjZDMTg0LjgwNiAyNi40MSAxODUuODcyIDI2Ljc4NSAxODYuNTMgMjcuMTIzQzE4Ny4xIDI3LjQxNCAxODcuMzc5IDI3Ljg0NSAxODcuMzc5IDI4LjQ0NEMxODcuMzc5IDI5LjA0MiAxODcuMTIyIDI5LjQ2NyAxODYuNTk1IDI5LjgzOUMxODYuMDQzIDMwLjIyNiAxODUuMjM3IDMwLjQyNSAxODQuMjAxIDMwLjQyNUMxODMuMTY2IDMwLjQyNSAxODIuMzk0IDMwLjE3NCAxODEuNzQ5IDI5LjY3NEMxODEuMTEzIDI5LjE4MSAxODAuNzcyIDI4LjU4OSAxODAuNzEgMjcuODY0TDE4MC42ODUgMjcuNTgySDE3Ni4wMTNMMTc2LjAyNSAyNy45MDFDMTc2LjA2NyAyOS4wOTU1IDE3Ni40NzIgMzAuMjQ4NyAxNzcuMTg4IDMxLjIwNkMxNzcuOTA3IDMyLjE4IDE3OC44OTMgMzIuOTU4IDE4MC4xMTggMzMuNTE5QzE4MS4zMzYgMzQuMDc3IDE4Mi43MzIgMzQuMzYyIDE4NC4yNjYgMzQuMzYyQzE4NS44MDEgMzQuMzYyIDE4Ny4xMDkgMzQuMTA4IDE4OC4yMzggMzMuNjA5QzE4OS4zNzYgMzMuMTA0IDE5MC4yNzIgMzIuMzk0IDE5MC45MDEgMzEuNDk0QzE5MS41MzQgMzAuNTkyIDE5MS44NTMgMjkuNTU0IDE5MS44NTMgMjguNDAzQzE5MS44MjggMjcuMTEgMTkxLjQ2NiAyNi4wNTMgMTkwLjc3NyAyNS4yNjJIMTkwLjc4N1oiIGZpbGw9IiM5QjlCOUIiLz4KPHBhdGggZD0iTTI0MS45ODIgMjUuNjU4MlYxNy43MTE3SDIyOC40NDFMMjIwLjQ5NCAyNS42NTgySDI0MS45ODJaIiBmaWxsPSIjOUI5QjlCIi8+CjxwYXRoIGQ9Ik0yNTcuMjM5IDUuOTUwODFIMjQwLjI2NUwyMzIuMjU1IDEzLjg5NzNIMjU3LjIzOVY1Ljk1MDgxWiIgZmlsbD0iIzlCOUI5QiIvPgo8cGF0aCBkPSJNMjEyLjYxMSAzMy42MDQ4TDIxNi42OCAyOS41MzYxSDIzMC40MTJWMzcuNDgyN0gyMTIuNjExVjMzLjYwNDhaIiBmaWxsPSIjOUI5QjlCIi8+CjxwYXRoIGQ9Ik0yMTUuNTk5IDIxLjc4MDNIMjI0LjM3MkwyMzIuMzgyIDEzLjgzMzdIMjE1LjU5OVYyMS43ODAzWiIgZmlsbD0iIzlCOUI5QiIvPgo8cGF0aCBkPSJNMjA2IDMzLjYwNDdIMjEyLjYxMUwyMjAuNDk0IDI1LjY1ODJIMjA2VjMzLjYwNDdaIiBmaWxsPSIjOUI5QjlCIi8+CjxwYXRoIGQ9Ik0yNDAuMjY1IDUuOTUwODFMMjM2LjE5NyAxMC4wMTk0SDIxMC4yNTlWMi4wNzI4OEgyNDAuMjY1VjUuOTUwODFaIiBmaWxsPSIjOUI5QjlCIi8+Cjwvc3ZnPgo=`;
var LICENSE_TYPES = {
"01": "GRID",
"02": "CHARTS",
"0102": "BOTH"
};
var LICENSING_HELP_URL = "https://www.ag-grid.com/charts/licensing/";
var _LicenseManager = class _LicenseManager {
constructor(document2) {
this.watermarkMessage = void 0;
this.totalMessageLength = 124;
this.document = document2;
this.md5 = new MD5();
this.md5.init();
}
validateLicense() {
const licenseDetails = this.getLicenseDetails(_LicenseManager.licenseKey, _LicenseManager.gridContext);
const currentLicenseName = `AG ${licenseDetails.currentLicenseType === "BOTH" ? "Grid and " : ""}Charts Enterprise`;
let suppliedLicenseName = "";
if (licenseDetails.suppliedLicenseType === "BOTH") {
suppliedLicenseName = "AG Grid and AG Charts Enterprise";
} else if (licenseDetails.suppliedLicenseType === "GRID") {
suppliedLicenseName = "AG Grid Enterprise";
} else if (licenseDetails.suppliedLicenseType !== void 0) {
suppliedLicenseName = "AG Charts Enterprise";
}
if (licenseDetails.missing) {
if (!this.isWebsiteUrl() || this.isForceWatermark()) {
this.outputMissingLicenseKey(currentLicenseName);
}
} else if (licenseDetails.expired) {
const gridReleaseDate = _LicenseManager.getChartsReleaseDate();
const formattedReleaseDate = _LicenseManager.formatDate(gridReleaseDate);
this.outputExpiredKey(licenseDetails.expiry, formattedReleaseDate, suppliedLicenseName);
} else if (!licenseDetails.valid) {
this.outputInvalidLicenseKey(
!!licenseDetails.incorrectLicenseType,
currentLicenseName,
suppliedLicenseName
);
} else if (licenseDetails.isTrial && licenseDetails.trialExpired) {
this.outputExpiredTrialKey(licenseDetails.expiry, currentLicenseName, suppliedLicenseName);
}
}
static extractExpiry(license) {
const restrictionHashed = license.substring(license.lastIndexOf("_") + 1, license.length);
return new Date(Number.parseInt(_LicenseManager.decode(restrictionHashed), 10));
}
static extractLicenseComponents(licenseKey) {
let cleanedLicenseKey = licenseKey.replaceAll(/[\u200B-\u200D\uFEFF]/g, "");
cleanedLicenseKey = cleanedLicenseKey.replaceAll(/\r?\n|\r/g, "");
if (licenseKey.length <= 32) {
return { md5: null, license: licenseKey, version: null, isTrial: null };
}
const hashStart = cleanedLicenseKey.length - 32;
const md5 = cleanedLicenseKey.substring(hashStart);
const license = cleanedLicenseKey.substring(0, hashStart);
const [version, isTrial, type] = _LicenseManager.extractBracketedInformation(cleanedLicenseKey);
return { md5, license, version, isTrial, type };
}
getLicenseDetails(licenseKey, gridContext = false) {
const currentLicenseType = "CHARTS";
if (missingOrEmpty(licenseKey)) {
return {
licenseKey,
valid: false,
missing: true,
currentLicenseType
};
}
const chartsReleaseDate = _LicenseManager.getChartsReleaseDate();
const { md5, license, version, isTrial, type } = _LicenseManager.extractLicenseComponents(licenseKey);
let valid = md5 === this.md5.md5(license) && !licenseKey.includes("For_Trialing_ag-Grid_Only");
let trialExpired = void 0;
let expired = void 0;
let expiry = null;
let incorrectLicenseType = false;
let suppliedLicenseType = void 0;
function handleTrial() {
const now = /* @__PURE__ */ new Date();
trialExpired = expiry < now;
expired = void 0;
}
if (valid) {
expiry = _LicenseManager.extractExpiry(license);
valid = !Number.isNaN(expiry.getTime());
if (valid) {
expired = chartsReleaseDate > expiry;
switch (version) {
case "legacy":
case "2": {
valid = false;
break;
}
case "3": {
if (missingOrEmpty(type)) {
valid = false;
} else {
suppliedLicenseType = type;
if (type !== LICENSE_TYPES["02"] && type !== LICENSE_TYPES["0102"]) {
valid = false;
incorrectLicenseType = true;
} else if (isTrial) {
handleTrial();
}
}
}
}
}
}
if (!valid) {
return {
licenseKey,
valid,
incorrectLicenseType,
currentLicenseType,
suppliedLicenseType
};
}
return {
licenseKey,
valid,
expiry: _LicenseManager.formatDate(expiry),
expired,
version,
isTrial,
trialExpired,
invalidLicenseTypeForCombo: gridContext ? suppliedLicenseType !== "BOTH" : void 0,
incorrectLicenseType,
currentLicenseType,
suppliedLicenseType
};
}
isDisplayWatermark() {
return this.isForceWatermark() || !this.isLocalhost() && !this.isE2ETest() && !this.isWebsiteUrl() && !missingOrEmpty(this.watermarkMessage);
}
getWatermarkMessage() {
return this.watermarkMessage ?? "";
}
getWatermarkForegroundConfig() {
const message = this.getWatermarkMessage();
if (!message) {
return void 0;
}
return this.buildWatermarkConfig(message);
}
getWatermarkForegroundConfigForBrowser() {
if (!this.isDisplayWatermark()) {
return void 0;
}
const message = this.getWatermarkMessage();
if (!message) {
return void 0;
}
return this.buildWatermarkConfig(message);
}
buildWatermarkConfig(text2) {
return {
text: text2,
image: {
url: WATERMARK_SVG_DATA_URL,
width: 170,
height: 25,
right: 25,
bottom: 50,
opacity: 0.7
}
};
}
getHostname() {
if (!this.document) {
return "localhost";
}
const win = this.document.defaultView ?? globalThis;
if (!win) {
return "localhost";
}
try {
const hostname = win.location?.hostname ?? "";
return hostname || "localhost";
} catch {
return "localhost";
}
}
isForceWatermark() {
if (!this.document) {
return false;
}
const win = this.document?.defaultView ?? globalThis.window != void 0 ? globalThis : void 0;
if (!win) {
return false;
}
const pathname = win.location?.pathname;
return pathname ? pathname.includes("forceWatermark") : false;
}
isWebsiteUrl() {
const hostname = this.getHostname();
return /^((?:[\w-]+\.)?ag-grid\.com)$/.exec(hostname) !== null;
}
isLocalhost() {
const hostname = this.getHostname();
return /^(?:127\.0\.0\.1|localhost)$/.exec(hostname) !== null;
}
isE2ETest() {
const hostname = this.getHostname();
return /^(?:172\.17\.0\.1|host\.docker\.internal)$/.exec(hostname) !== null;
}
static formatDate(date2) {
const monthNames = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
const day = date2.getDate();
const monthIndex = date2.getMonth();
const year = date2.getFullYear();
return day + " " + monthNames[monthIndex] + " " + year;
}
static getChartsReleaseDate() {
return new Date(Number.parseInt(_LicenseManager.decode(_LicenseManager.RELEASE_INFORMATION), 10));
}
static decode(input) {
const keystr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
let t = "";
let n, r, i;
let s, o, u, a;
let f = 0;
const e = input.replaceAll(/[^A-Za-z0-9+/=]/g, "");
while (f < e.length) {
s = keystr.indexOf(e.charAt(f++));
o = keystr.indexOf(e.charAt(f++));
u = keystr.indexOf(e.charAt(f++));
a = keystr.indexOf(e.charAt(f++));
n = s << 2 | o >> 4;
r = (o & 15) << 4 | u >> 2;
i = (u & 3) << 6 | a;
t = t + String.fromCodePoint(n);
if (u != 64) {
t = t + String.fromCodePoint(r);
}
if (a != 64) {
t = t + String.fromCodePoint(i);
}
}
t = _LicenseManager.utf8_decode(t);
return t;
}
static utf8_decode(input) {
input = input.replaceAll("rn", "n");
let t = "";
for (let n = 0; n < input.length; n++) {
const r = input.codePointAt(n);
if (r < 128) {
t += String.fromCodePoint(r);
} else if (r > 127 && r < 2048) {
t += String.fromCodePoint(r >> 6 | 192);
t += String.fromCodePoint(r & 63 | 128);
} else {
t += String.fromCodePoint(r >> 12 | 224);
t += String.fromCodePoint(r >> 6 & 63 | 128);
t += String.fromCodePoint(r & 63 | 128);
}
}
return t;
}
static setGridContext(gridContext = false) {
_LicenseManager.gridContext = gridContext;
}
static setLicenseKey(licenseKey) {
if (this.licenseKey && this.licenseKey !== licenseKey) {
console.warn(
`License Key being set multiple times with different values. This can result in an incorrect license key being used.`
);
}
_LicenseManager.licenseKey = licenseKey;
}
static extractBracketedInformation(licenseKey) {
if (!licenseKey.includes("[")) {
return ["legacy", false, void 0];
}
const matches = licenseKey.match(/\[(.*?)\]/g).map((match) => match.replace("[", "").replace("]", ""));
if (!matches || matches.length === 0) {
return ["legacy", false, void 0];
}
const isTrial = matches.filter((match) => match === "TRIAL").length === 1;
const rawVersion = matches.find((match) => match.startsWith("v"));
const version = rawVersion ? rawVersion.replace("v", "") : "legacy";
const type = LICENSE_TYPES[matches.find((match) => LICENSE_TYPES[match])];
return [version, isTrial, type];
}
centerPadAndOutput(input) {
const paddingRequired = this.totalMessageLength - input.length;
console.error(input.padStart(paddingRequired / 2 + input.length, "*").padEnd(this.totalMessageLength, "*"));
}
padAndOutput(input, padding2 = "*", terminateWithPadding = "") {
console.error(
input.padEnd(this.totalMessageLength - terminateWithPadding.length, padding2) + terminateWithPadding
);
}
outputInvalidLicenseKey(incorrectLicenseType, currentLicenseName, suppliedLicenseName) {
if (!_LicenseManager.gridContext) {
if (incorrectLicenseType) {
this.centerPadAndOutput("");
this.centerPadAndOutput(` ${currentLicenseName} License `);
this.centerPadAndOutput(" Incompatible License Key ");
this.padAndOutput(
`* Your license key is for ${suppliedLicenseName} only and does not cover you for ${currentLicenseName}.`,
" ",
"*"
);
this.padAndOutput(`* To troubleshoot your license key visit ${LICENSING_HELP_URL}.`, " ", "*");
this.centerPadAndOutput("");
this.centerPadAndOutput("");
} else {
this.centerPadAndOutput("");
this.centerPadAndOutput(` ${currentLicenseName} License `);
this.centerPadAndOutput(" Invalid License Key ");
this.padAndOutput(`* Your license key is not valid.`, " ", "*");
this.padAndOutput(`* To troubleshoot your license key visit ${LICENSING_HELP_URL}.`, " ", "*");
this.centerPadAndOutput("");
this.centerPadAndOutput("");
}
}
this.watermarkMessage = "Invalid License";
}
outputExpiredTrialKey(formattedExpiryDate, currentLicenseName, suppliedLicenseName) {
if (!_LicenseManager.gridContext) {
this.centerPadAndOutput("");
this.centerPadAndOutput(` ${currentLicenseName} License `);
this.centerPadAndOutput(" Trial Period Expired. ");
this.padAndOutput(
`* Your trial only license for ${suppliedLicenseName} expired on ${formattedExpiryDate}.`,
" ",
"*"
);
this.padAndOutput("* Please email info@ag-grid.com to purchase a license.", " ", "*");
this.centerPadAndOutput("");
this.centerPadAndOutput("");
}
this.watermarkMessage = "Trial Period Expired";
}
outputMissingLicenseKey(currentLicenseName) {
if (!_LicenseManager.gridContext) {
this.centerPadAndOutput("");
this.centerPadAndOutput(` ${currentLicenseName} License `);
this.centerPadAndOutput(" License Key Not Found ");
this.padAndOutput(`* All ${currentLicenseName} features are unlocked for trial.`, " ", "*");
this.padAndOutput(
"* If you want to hide the watermark please email info@ag-grid.com for a trial license key.",
" ",
"*"
);
this.centerPadAndOutput("");
this.centerPadAndOutput("");
}
this.watermarkMessage = "For Trial Use Only";
}
outputExpiredKey(formattedExpiryDate, formattedReleaseDate, currentLicenseName) {
if (!_LicenseManager.gridContext) {
this.centerPadAndOutput("");
this.centerPadAndOutput(` ${currentLicenseName} License `);
this.centerPadAndOutput(" Incompatible Software Version ");
this.padAndOutput(
`* Your license key works with versions of ${currentLicenseName} released before ${formattedExpiryDate}.`,
" ",
"*"
);
this.padAndOutput(`* The version you are trying to use was released on ${formattedReleaseDate}.`, " ", "*");
this.padAndOutput("* Please contact info@ag-grid.com to renew your license key.", " ", "*");
this.centerPadAndOutput("");
this.centerPadAndOutput("");
}
this.watermarkMessage = "License Expired";
}
};
_LicenseManager.RELEASE_INFORMATION = "MTc3MDgwNzY1NDM4MQ==";
_LicenseManager.gridContext = false;
var LicenseManager = _LicenseManager;
// packages/ag-charts-enterprise/src/license/watermark.ts
import { createElement as createElement2 } from "ag-charts-core";
function injectWatermark(domManager, text2) {
const element = domManager.addChild("canvas-overlay", "watermark");
const textElement = createElement2("span");
textElement.innerText = text2;
element.addEventListener("animationend", () => {
domManager.removeChild("canvas-overlay", "watermark");
domManager.removeStyles("watermark");
});
element.classList.add("ag-watermark");
element.appendChild(textElement);
}
// packages/ag-charts-enterprise/src/styles.css
var styles_default = `.ag-watermark{position:absolute;bottom:20px;right:25px;font-weight:700;font-family:Impact,sans-serif;font-size:19px;opacity:.7;animation:1s ease-out 3s ag-watermark-fadeout;color:#9b9b9b;pointer-events:none;&:before{content:"";display:block;height:40px;width:170px;background-image:url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjU4IiBoZWlnaHQ9IjQwIiB2aWV3Qm94PSIwIDAgMjU4IDQwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMjUuNzc5IDI4LjY1N0gxMy4zNTlMMTEuMTczIDM0LjAxMkg1LjY3Mjk3TDE3LjE4MiA3LjA1OTk5SDIxLjk1M0wzMy40NjIgMzQuMDEySDI3Ljk2MkwyNS43NzYgMjguNjU3SDI1Ljc3OVpNMjQuMDY4IDI0LjM5N0wxOS41ODggMTMuNDM0TDE1LjEwNyAyNC4zOTdIMjQuMDY4Wk02Mi4wOTIgMTguODIzSDQ5LjgxN1YyMy4wODZINTYuNzc1QzU2LjU1NSAyNS4yMjIgNTUuNzU1IDI2LjkyNyA1NC4zNzIgMjguMjAyQzUyLjk4OSAyOS40NzYgNTEuMTY2IDMwLjExNSA0OC45MDkgMzAuMTE1QzQ3LjYyMiAzMC4xMTUgNDYuNDUgMjkuODg1IDQ1LjM5MyAyOS40MjNDNDQuMzU4MyAyOC45NzgxIDQzLjQzMjYgMjguMzEzOCA0Mi42OCAyNy40NzZDNDEuOTI3IDI2LjYzOSA0MS4zNDQgMjUuNjMxIDQwLjkzMSAyNC40NTNDNDAuNTE5IDIzLjI3NSA0MC4zMTEgMjEuOTcgNDAuMzExIDIwLjUzN0M0MC4zMTEgMTkuMTA1IDQwLjUxNiAxNy44IDQwLjkzMSAxNi42MjFDNDEuMzQ0IDE1LjQ0MyA0MS45MjcgMTQuNDM2IDQyLjY4IDEzLjU5OEM0My40Mzc2IDEyLjc1NzcgNDQuMzY5NiAxMi4wOTMyIDQ1LjQxMSAxMS42NTFDNDYuNDc4IDExLjE4OSA0Ny42NTYgMTAuOTYgNDguOTQ2IDEwLjk2QzUxLjYxMiAxMC45NiA1My42MzcgMTEuNjAyIDU1LjAyIDEyLjg4NUw1OC4zIDkuNjA0OTlDNTUuODE3IDcuNjY5OTkgNTIuNjc2IDYuNjk5OTkgNDguODcyIDYuNjk5OTlDNDYuNzYgNi42OTk5OSA0NC44NTMgNy4wMzQ5OSA0My4xNTQgNy43MDA5OUM0MS40NTUgOC4zNjc5OSAzOS45OTggOS4zMDM5OSAzOC43ODMgMTAuNTA0QzM3LjU2NyAxMS43MDcgMzYuNjM0IDEzLjE1OCAzNS45NzcgMTQuODU3QzM1LjMxOSAxNi41NTYgMzQuOTk0IDE4LjQ1MSAzNC45OTQgMjAuNTRDMzQuOTk0IDIyLjYzIDM1LjMyOSAyNC40OTQgMzUuOTk1IDI2LjIwNUMzNi42NjIgMjcuOTE2IDM3LjYwNSAyOS4zNzQgMzguODE3IDMwLjU3N0M0MC4wMzIgMzEuNzggNDEuNDg2IDMyLjcxMyA0My4xODggMzMuMzgzQzQ0Ljg4OCAzNC4wNDkgNDYuNzgyIDM0LjM4NCA0OC44NzIgMzQuMzg0QzUwLjk2MSAzNC4zODQgNTIuNzUgMzQuMDQ5IDU0LjM5IDMzLjM4M0M1Ni4wMzEgMzIuNzE2IDU3LjQyNiAzMS43OCA1OC41NzkgMzAuNTc3QzU5LjczMyAyOS4zNzQgNjAuNjE5IDI3LjkxNiA2MS4yMzkgMjYuMjA1QzYxLjg2IDI0LjQ5NCA2Mi4xNyAyMi42MDUgNjIuMTcgMjAuNTRDNjIuMTY5NiAxOS45Njg4IDYyLjE0NDUgMTkuMzk4IDYyLjA5NSAxOC44MjlMNjIuMDkyIDE4LjgyM1pNMTUxLjgxIDE2Ljk4MUMxNTMuNDEgMTQuNjA5IDE1Ny40MTkgMTQuMzU4IDE1OS4wMjIgMTQuMzU4VjE4LjkxQzE1Ni45NTcgMTguOTEgMTU0Ljk4NSAxOC45OTYgMTUzLjc1NyAxOS44OTJDMTUyLjUyOSAyMC43OTIgMTUxLjkxOSAyMS45ODIgMTUxLjkxOSAyMy40NjRWMzMuOTlIMTQ2Ljk2NFYxNC4zNThIMTUxLjczNkwxNTEuODEgMTYuOTgxWk0xNDMuMDExIDE0LjM2MVYzNC4wMzFIMTM4LjI0TDEzOC4xMzEgMzEuMDQ1QzEzNy40NjYgMzIuMDc2IDEzNi41NTEgMzIuOTIxOSAxMzUuNDcxIDMzLjUwNEMxMzQuMzc2IDM0LjA5OSAxMzMuMDY4IDM0LjM5NiAxMzEuNTM2IDM0LjM5NkMxMzAuMiAzNC4zOTYgMTI4Ljk2MyAzNC4xNTIgMTI3LjgyMiAzMy42NjhDMTI2LjcgMzMuMTk2NCAxMjUuNjg5IDMyLjQ5NSAxMjQuODU1IDMxLjYwOUMxMjQuMDE4IDMwLjcyMiAxMjMuMzU0IDI5LjY2MiAxMjIuODcxIDI4LjQyMkMxMjIuMzg0IDI3LjE4NSAxMjIuMTQyIDI1LjgxMSAxMjIuMTQyIDI0LjMwNEMxMjIuMTQyIDIyLjc5OCAxMjIuMzg0IDIxLjM3OCAxMjIuODcxIDIwLjExNkMxMjMuMzU3IDE4Ljg1NCAxMjQuMDE4IDE3Ljc3MiAxMjQuODU1IDE2Ljg3M0MxMjUuNjg4IDE1Ljk3NjQgMTI2LjY5OCAxNS4yNjM2IDEyNy44MjIgMTQuNzhDMTI4Ljk2MyAxNC4yODEgMTMwLjIwMyAxNC4wMzMgMTMxLjUzNiAxNC4wMzNDMTMzLjA0MyAxNC4wMzMgMTM0LjMzIDE0LjMxOCAxMzUuMzk3IDE0Ljg4OEMxMzYuNDYyIDE1LjQ1ODkgMTM3LjM3NSAxNi4yNzggMTM4LjA1NyAxNy4yNzZWMTQuMzYxSDE0My4wMTFaTTEzMi42MzEgMzAuMTMzQzEzNC4yNTYgMzAuMTMzIDEzNS41NjcgMjkuNTk0IDEzNi41NjUgMjguNTEyQzEzNy41NjEgMjcuNDMgMTM4LjA2IDI1Ljk5MSAxMzguMDYgMjQuMTk2QzEzOC4wNiAyMi40MDEgMTM3LjU2MSAyMC45OSAxMzYuNTY1IDE5Ljg5OUMxMzUuNTcgMTguODA3IDEzNC4yNTkgMTguMjU4IDEzMi42MzEgMTguMjU4QzEzMS4wMDMgMTguMjU4IDEyOS43MjkgMTguODA0IDEyOC43MzQgMTkuODk5QzEyNy43MzggMjAuOTkzIDEyNy4yMzkgMjIuNDM4IDEyNy4yMzkgMjQuMjMzQzEyNy4yMzkgMjYuMDI4IDEyNy43MzUgMjcuNDMzIDEyOC43MzQgMjguNTE1QzEyOS43MjkgMjkuNTk0IDEzMS4wMjggMzAuMTM2IDEzMi42MzEgMzAuMTM2VjMwLjEzM1pNOTMuNjk4IDI3Ljg3NkM5My41Nzk1IDI4LjAwMjUgOTMuNDU2NCAyOC4xMjQ2IDkzLjMyOSAyOC4yNDJDOTEuOTQ3IDI5LjUxNiA5MC4xMjMgMzAuMTU1IDg3Ljg2NiAzMC4xNTVDODYuNTggMzAuMTU1IDg1LjQwOCAyOS45MjYgODQuMzUgMjkuNDY0QzgzLjMxNTUgMjkuMDE4OSA4Mi4zODk4IDI4LjM1NDYgODEuNjM3IDI3LjUxN0M4MC44ODQgMjYuNjc5IDgwLjMwMSAyNS42NzIgNzkuODg5IDI0LjQ5NEM3OS40NzYgMjMuMzE1IDc5LjI2OSAyMi4wMSA3OS4yNjkgMjAuNTc4Qzc5LjI2OSAxOS4xNDUgNzkuNDczIDE3Ljg0IDc5Ljg4OSAxNi42NjJDODAuMzAxIDE1LjQ4NCA4MC44ODQgMTQuNDc2IDgxLjYzNyAxMy42MzlDODIuMzk0OSAxMi43OTg3IDgzLjMyNzMgMTIuMTM0MiA4NC4zNjkgMTEuNjkyQzg1LjQzNiAxMS4yMyA4Ni42MTQgMTEgODcuOTAzIDExQzkwLjU3IDExIDkyLjU5NSAxMS42NDIgOTMuOTc3IDEyLjkyNkw5Ny4yNTggOS42NDQ5OUM5NC43NzQgNy43MTA5OSA5MS42MzMgNi43Mzk5OSA4Ny44MjkgNi43Mzk5OUM4NS43MTggNi43Mzk5OSA4My44MTEgNy4wNzQ5OSA4Mi4xMTIgNy43NDE5OUM4MC40MTMgOC40MDc5OSA3OC45NTYgOS4zNDQ5OSA3Ny43NCAxMC41NDVDNzYuNTI1IDExLjc0NyA3NS41OTIgMTMuMTk5IDc0LjkzNCAxNC44OThDNzQuMjc3IDE2LjU5NyA3My45NTEgMTguNDkxIDczLjk1MSAyMC41ODFDNzMuOTUxIDIyLjY3IDc0LjI4NiAyNC41MzQgNzQuOTUzIDI2LjI0NUM3NS42MTkgMjcuOTU3IDc2LjU2MiAyOS40MTQgNzcuNzc0IDMwLjYxN0M3OC45OSAzMS44MiA4MC40NDQgMzIuNzUzIDgyLjE0NiAzMy40MjNDODMuODQ1IDM0LjA5IDg1LjczOSAzNC40MjQgODcuODI5IDM0LjQyNEM4OS45MTkgMzQuNDI0IDkxLjcwOCAzNC4wOSA5My4zNDggMzMuNDIzQzk0LjcxOCAzMi44NjUgOTUuOTE4IDMyLjEyMSA5Ni45NDggMzEuMTkxQzk3LjE0OSAzMS4wMDggOTcuMzQ4IDMwLjgxNSA5Ny41MzcgMzAuNjJMOTMuNzAxIDI3Ljg4NUw5My42OTggMjcuODc2Wk0xMTAuODAyIDE0LjAxNUMxMDkuMTk5IDE0LjAxNSAxMDYuODM2IDE0LjQ3MSAxMDUuNjExIDE2LjE1OEwxMDUuNTM3IDYuMDE1OTlIMTAwLjc2NVYzMy45MzlIMTA1LjcyVjIyLjY0MUMxMDUuNzcxIDIxLjQ2MDcgMTA2LjI4OCAyMC4zNDg4IDEwNy4xNTcgMTkuNTQ4OUMxMDguMDI3IDE4Ljc0OTEgMTA5LjE3OCAxOC4zMjY2IDExMC4zNTggMTguMzc0QzExMy4zOTcgMTguMzc0IDExNC4yNjggMjEuMTU5IDExNC4yNjggMjIuNjQxVjMzLjkzOUgxMTkuMjIzVjIxLjA1OUMxMTkuMjIzIDIxLjA1OSAxMTkuMTQyIDE0LjAxNSAxMTAuODAyIDE0LjAxNVpNMTczLjc2MyAxNC4zNThIMTY5Ljk5OVY4LjcxNDk5SDE2NS4wNDhWMTQuMzU4SDE2MS4yODRWMTguOTE2SDE2NS4wNDhWMzQuMDAzSDE2OS45OTlWMTguOTE2SDE3My43NjNWMTQuMzU4Wk0xOTAuNzg3IDI1LjI2MkMxOTAuMTI5IDI0LjUwMTQgMTg5LjMwNyAyMy44OTk0IDE4OC4zODQgMjMuNTAxQzE4Ny40ODggMjMuMTE3IDE4Ni4zMzEgMjIuNzMyIDE4NC45NDggMjIuMzY0QzE4NC4xNjUgMjIuMTQzOSAxODMuMzkgMjEuODk3OCAxODIuNjIzIDIxLjYyNkMxODIuMTYzIDIxLjQ2MjEgMTgxLjc0MSAyMS4yMDY2IDE4MS4zODMgMjAuODc1QzE4MS4yMzUgMjAuNzQyMSAxODEuMTE4IDIwLjU3ODkgMTgxLjAzOSAyMC4zOTY0QzE4MC45NjEgMjAuMjE0IDE4MC45MjIgMjAuMDE2NiAxODAuOTI3IDE5LjgxOEMxODAuOTI3IDE5LjI3MiAxODEuMTU2IDE4Ljg0NCAxODEuNjI1IDE4LjUxQzE4Mi4xMjEgMTguMTU2IDE4Mi44NjIgMTcuOTc2IDE4My44MjYgMTcuOTc2QzE4NC43OSAxNy45NzYgMTg1LjU4NyAxOC4yMDkgMTg2LjE0OCAxOC42NjhDMTg2LjcwNiAxOS4xMjQgMTg3LjAwNyAxOS43MjUgMTg3LjA3MiAyMC41TDE4Ny4wOTQgMjAuNzgySDE5MS42MzNMMTkxLjYxNyAyMC40NkMxOTEuNTIxIDE4LjQ4NSAxOTAuNzcxIDE2LjkgMTg5LjM4NSAxNS43NUMxODguMDEyIDE0LjYxMiAxODYuMTg1IDE0LjAzMyAxODMuOTYyIDE0LjAzM0MxODIuNDc3IDE0LjAzMyAxODEuMTQxIDE0LjI4NyAxNzkuOTk0IDE0Ljc4NkMxNzguODMxIDE1LjI5MSAxNzcuOTI2IDE1Ljk5NSAxNzcuMjk2IDE2Ljg4MkMxNzYuNjczIDE3Ljc0NTUgMTc2LjMzOCAxOC43ODQgMTc2LjM0MSAxOS44NDlDMTc2LjM0MSAyMS4xNjcgMTc2LjY5OCAyMi4yNDkgMTc3LjM5OSAyMy4wNjRDMTc4LjA2IDIzLjg0MzIgMTc4Ljg5OCAyNC40NTM0IDE3OS44NDIgMjQuODQ0QzE4MC43NDQgMjUuMjE2IDE4MS45MjggMjUuNjA3IDE4My4zNjEgMjZDMTg0LjgwNiAyNi40MSAxODUuODcyIDI2Ljc4NSAxODYuNTMgMjcuMTIzQzE4Ny4xIDI3LjQxNCAxODcuMzc5IDI3Ljg0NSAxODcuMzc5IDI4LjQ0NEMxODcuMzc5IDI5LjA0MiAxODcuMTIyIDI5LjQ2NyAxODYuNTk1IDI5LjgzOUMxODYuMDQzIDMwLjIyNiAxODUuMjM3IDMwLjQyNSAxODQuMjAxIDMwLjQyNUMxODMuMTY2IDMwLjQyNSAxODIuMzk0IDMwLjE3NCAxODEuNzQ5IDI5LjY3NEMxODEuMTEzIDI5LjE4MSAxODAuNzcyIDI4LjU4OSAxODAuNzEgMjcuODY0TDE4MC42ODUgMjcuNTgySDE3Ni4wMTNMMTc2LjAyNSAyNy45MDFDMTc2LjA2NyAyOS4wOTU1IDE3Ni40NzIgMzAuMjQ4NyAxNzcuMTg4IDMxLjIwNkMxNzcuOTA3IDMyLjE4IDE3OC44OTMgMzIuOTU4IDE4MC4xMTggMzMuNTE5QzE4MS4zMzYgMzQuMDc3IDE4Mi43MzIgMzQuMzYyIDE4NC4yNjYgMzQuMzYyQzE4NS44MDEgMzQuMzYyIDE4Ny4xMDkgMzQuMTA4IDE4OC4yMzggMzMuNjA5QzE4OS4zNzYgMzMuMTA0IDE5MC4yNzIgMzIuMzk0IDE5MC45MDEgMzEuNDk0QzE5MS41MzQgMzAuNTkyIDE5MS44NTMgMjkuNTU0IDE5MS44NTMgMjguNDAzQzE5MS44MjggMjcuMTEgMTkxLjQ2NiAyNi4wNTMgMTkwLjc3NyAyNS4yNjJIMTkwLjc4N1oiIGZpbGw9IiM5QjlCOUIiLz4KPHBhdGggZD0iTTI0MS45ODIgMjUuNjU4MlYxNy43MTE3SDIyOC40NDFMMjIwLjQ5NCAyNS42NTgySDI0MS45ODJaIiBmaWxsPSIjOUI5QjlCIi8+CjxwYXRoIGQ9Ik0yNTcuMjM5IDUuOTUwODFIMjQwLjI2NUwyMzIuMjU1IDEzLjg5NzNIMjU3LjIzOVY1Ljk1MDgxWiIgZmlsbD0iIzlCOUI5QiIvPgo8cGF0aCBkPSJNMjEyLjYxMSAzMy42MDQ4TDIxNi42OCAyOS41MzYxSDIzMC40MTJWMzcuNDgyN0gyMTIuNjExVjMzLjYwNDhaIiBmaWxsPSIjOUI5QjlCIi8+CjxwYXRoIGQ9Ik0yMTUuNTk5IDIxLjc4MDNIMjI0LjM3MkwyMzIuMzgyIDEzLjgzMzdIMjE1LjU5OVYyMS43ODAzWiIgZmlsbD0iIzlCOUI5QiIvPgo8cGF0aCBkPSJNMjA2IDMzLjYwNDdIMjEyLjYxMUwyMjAuNDk0IDI1LjY1ODJIMjA2VjMzLjYwNDdaIiBmaWxsPSIjOUI5QjlCIi8+CjxwYXRoIGQ9Ik0yNDAuMjY1IDUuOTUwODFMMjM2LjE5NyAxMC4wMTk0SDIxMC4yNTlWMi4wNzI4OEgyNDAuMjY1VjUuOTUwODFaIiBmaWxsPSIjOUI5QjlCIi8+Cjwvc3ZnPgo=);background-repeat:no-repeat;background-size:170px 40px}>span{padding-left:.7rem}}@keyframes ag-watermark-fadeout{0%{opacity:.5}to{opacity:0}}.ag-charts-dialog{display:flex;flex-direction:column;font-size:var(--ag-charts-chrome-font-size-large)}.ag-charts-dialog__tabs{display:flex;flex-direction:column}.ag-charts-dialog__header{border-bottom:1px solid var(--ag-charts-border-color);display:flex}.ag-charts-dialog__tab-list{display:flex;gap:calc(var(--ag-charts-spacing) * 2)}.ag-charts-dialog__drag-handle{align-items:center;color:inherit;cursor:grab;display:flex;padding:1px 6px;text-align:center}.ag-charts-dialog__drag-handle--dragging{cursor:grabbing}.ag-charts-dialog__tab-button{background:none;border:0;border-bottom:2px solid transparent;border-radius:0;color:var(--ag-charts-panel-subtle-text-color);margin-bottom:-1px;padding:var(--input-padding) calc(var(--input-padding) / 2)}.ag-charts-dialog__tab-button:hover{background:none}.ag-charts-dialog__tab-button--active{border-color:var(--ag-charts-accent-color);color:inherit}.ag-charts-dialog__drag-handle+.ag-charts-dialog__tab-button{margin-left:calc(var(--ag-charts-spacing) * -2)}.ag-charts-button.ag-charts-dialog__close-button{background:none;border:0;margin-left:auto;padding:1px 6px}.ag-charts-dialog__close-button:focus-visible{outline:var(--ag-charts-focus-border);box-shadow:var(--ag-charts-focus-border-shadow);z-index:calc(var(--ag-charts-layer-ui-overlay) + 1)}.ag-charts-dialog__tab-panel{display:none;flex-direction:column;gap:calc(var(--ag-charts-spacing) * 4);margin:0 calc(var(--ag-charts-spacing) * 4);padding:calc(var(--ag-charts-spacing) * 4) 0}.ag-charts-dialog__tab-panel--active{display:flex}.ag-charts-dialog__input-group-line{display:flex;gap:16px 18px;flex-wrap:wrap}.ag-charts-dialog__input-group{align-items:center;display:flex;font-size:var(--ag-charts-chrome-font-size)}.ag-charts-dialog__input-group-label{color:var(--ag-charts-panel-subtle-text-color);margin-right:5px}.ag-charts-dialog__input-group-label[for]{cursor:pointer}.ag-charts-dialog__button{border-radius:0;margin-right:-1px}.ag-charts-dialog__button.ag-charts-dialog__button--active{background:var(--ag-charts-button-focus-background-color);border-color:var(--ag-charts-input-focus-border-color);color:var(--ag-charts-input-focus-text-color);z-index:var(--input-layer-active)}.ag-charts-dialog__button:first-child,.ag-charts-dialog__input-group-label+.ag-charts-dialog__button{border-bottom-left-radius:var(--ag-charts-input-border-radius);border-top-left-radius:var(--ag-charts-input-border-radius)}.ag-charts-dialog__button:last-child{border-bottom-right-radius:var(--ag-charts-input-border-radius);border-top-right-radius:var(--ag-charts-input-border-radius)}.ag-charts-dialog__color-picker-button{--color: #000;background:var(--color);border:none;color:transparent;height:26px;width:26px}.ag-charts-dialog__color-picker-button:hover{background:var(--color)}.ag-charts-dialog__color-picker-button--multi-color,.ag-charts-dialog__color-picker-button--multi-color:hover{background:linear-gradient(135deg,red 0%,#ff0 calc(100% * 1 / 6),#0f0 calc(100% * 2 / 6),#0ff 50%,#00f calc(100% * 4 / 6),#f0f calc(100% * 5 / 6),red 100%)}.ag-charts-color-picker{width:190px;padding:8px;cursor:default;--h: 0;--s: 0;--v: 0;--a: 0;--color: #000;--color-a: #000;--thumb-size: 18px;--inner-width: 172px;--track-height: 12px;--palette-height: 136px;--checker: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="4" height="4"><rect x="0" y="0" width="4" height="4" fill="%23fff"/><path d="M0 0H2V4H4V2H0Z" fill="%23b2b2b2"/></svg>');--multi-color: linear-gradient( 135deg, #f00 0% , #ff0 calc(100% * 1 / 6), #0f0 calc(100% * 2 / 6), #0ff 50% , #00f calc(100% * 4 / 6), #f0f calc(100% * 5 / 6), #f00 100% )}.ag-charts-color-picker__content{display:flex;flex-direction:column}.ag-charts-color-picker__palette{position:relative;width:100%;height:var(--palette-height);margin-bottom:8px;background:linear-gradient(to bottom,#0000,#000),linear-gradient(to right,#fff,#fff0) hsl(var(--h),100%,50%);border-radius:calc(var(--ag-charts-border-radius) * 1.5);box-shadow:inset 0 0 0 1px #0003}.ag-charts-color-picker__palette:after{content:"";position:absolute;display:block;top:calc(var(--thumb-size) * -.5 + (1 - var(--v)) * 100%);left:calc(var(--thumb-size) * -.5 + var(--s) * 100%);background:var(--color);width:var(--thumb-size);height:var(--thumb-size);border-radius:calc(var(--ag-charts-border-radius) * 99);box-shadow:var(--box-shadow);--box-shadow: inset 0 0 0 3px white, inset 0 0 1px 3px #0006, 0 0 5px #00000038}.ag-charts-color-picker__palette:focus-visible:after{outline:var(--ag-charts-focus-border);box-shadow:var(--box-shadow),0 0 0 2px #fff8,var(--ag-charts-focus-border-shadow)}.ag-charts-color-picker__color-row{display:flex;gap:8px;align-items:center;margin-bottom:4px;--inset: calc((var(--thumb-size) - var(--track-height)) / 2)}.ag-charts-color-picker__hue-input,.ag-charts-color-picker__alpha-input{-webkit-appearance:none;display:block;position:relative;padding:0;margin:0 calc(var(--inset) * -1);border:0;height:var(--thumb-size);width:auto;background:transparent;--inset: calc((var(--thumb-size) - var(--track-height)) / 2)}.ag-charts-color-picker__hue-input::-moz-range-thumb,.ag-charts-color-picker__alpha-input::-moz-range-thumb{appearance:none;width:var(--thumb-size);height:var(--thumb-size);border-radius:calc(var(--ag-charts-border-radius) * 99);box-shadow:var(--box-shadow);--box-shadow: inset 0 0 0 3px white, inset 0 0 1px 3px #0006, 0 0 5px #00000038}.ag-charts-color-picker__hue-input::-webkit-slider-thumb,.ag-charts-color-picker__alpha-input::-webkit-slider-thumb{-webkit-appearance:none;width:var(--thumb-size);height:var(--thumb-size);border-radius:calc(var(--ag-charts-border-radius) * 99);box-shadow:var(--box-shadow);--box-shadow: inset 0 0 0 3px white, inset 0 0 1px 3px #0006, 0 0 5px #00000038;transform:translateZ(0)}.ag-charts-color-picker__hue-input::-moz-range-thumb{background:hsl(var(--h),100%,50%)}.ag-charts-color-picker__hue-input::-webkit-slider-thumb{background:hsl(var(--h),100%,50%)}.ag-charts-color-picker__alpha-input::-moz-range-thumb{background:transparent}.ag-charts-color-picker__alpha-input::-webkit-slider-thumb{background:transparent}.ag-charts-color-picker__alpha-input--opaque::-moz-range-thumb{background:var(--color)}.ag-charts-color-picker__alpha-input--opaque::-webkit-slider-thumb{background:var(--color)}.ag-charts-color-picker__hue-input:focus-visible::-moz-range-thumb,.ag-charts-color-picker__alpha-input:focus-visible::-moz-range-thumb{outline:var(--ag-charts-focus-border);box-shadow:var(--box-shadow),var(--ag-charts-focus-border-shadow)}.ag-charts-color-picker__hue-input:focus-visible::-webkit-slider-thumb,.ag-charts-color-picker__alpha-input:focus-visible::-webkit-slider-thumb{outline:var(--ag-charts-focus-border);box-shadow:var(--box-shadow),var(--ag-charts-focus-border-shadow)}.ag-charts-color-picker__hue-input::-moz-range-track,.ag-charts-color-picker__alpha-input::-moz-range-track{position:absolute;content:"";display:block;top:calc(50% - var(--track-height) / 2);left:var(--inset);right:var(--inset);height:var(--track-height);border-radius:calc(var(--ag-charts-border-radius) * 99);box-shadow:inset 0 0 0 1px #0003}.ag-charts-color-picker__hue-input:before,.ag-charts-color-picker__alpha-input:before{position:absolute;content:"";display:block;top:calc(50% - var(--track-height) / 2);left:var(--inset);right:var(--inset);height:var(--track-height);border-radius:calc(var(--ag-charts-border-radius) * 99);box-shadow:inset 0 0 0 1px #0003}.ag-charts-color-picker__multi-color-button{width:36px;margin-left:var(--inset);height:var(--track-height);border-radius:calc(var(--ag-charts-border-radius) * 99);border:0;background:var(--multi-color);box-shadow:inset 0 0 0 1px #0003}.ag-charts-color-picker__multi-color-button--hidden{display:none}.ag-charts-color-picker__multi-color-button--active{box-shadow:inset 0 0 0 1px #0003;outline-offset:1px;outline:2px solid #2196f3}.ag-charts-color-picker__hue-input{flex:1 0 0}.ag-charts-color-picker__hue-input::-moz-range-track{background:linear-gradient(to right,red,red calc((100% - var(--track-height)) * 0 / 6 + var(--track-height) / 2),#ff0 calc((100% - var(--track-height)) * 1 / 6 + var(--track-height) / 2),#0f0 calc((100% - var(--track-height)) * 2 / 6 + var(--track-height) / 2),#0ff calc((100% - var(--track-height)) * 3 / 6 + var(--track-height) / 2),#00f calc((100% - var(--track-height)) * 4 / 6 + var(--track-height) / 2),#f0f calc((100% - var(--track-height)) * 5 / 6 + var(--track-height) / 2),red calc((100% - var(--track-height)) * 6 / 6 + var(--track-height) / 2))}.ag-charts-color-picker__hue-input:before{background:linear-gradient(to right,red,red calc((100% - var(--track-height)) * 0 / 6 + var(--track-height) / 2),#ff0 calc((100% - var(--track-height)) * 1 / 6 + var(--track-height) / 2),#0f0 calc((100% - var(--track-height)) * 2 / 6 + var(--track-height) / 2),#0ff calc((100% - var(--track-height)) * 3 / 6 + var(--track-height) / 2),#00f calc((100% - var(--track-height)) * 4 / 6 + var(--track-height) / 2),#f0f calc((100% - var(--track-height)) * 5 / 6 + var(--track-height) / 2),red calc((100% - var(--track-height)) * 6 / 6 + var(--track-height) / 2))}.ag-charts-color-picker__alpha-input{margin-bottom:7px}.ag-charts-color-picker__alpha-input::-moz-range-track{background:linear-gradient(to right,transparent,var(--color)),var(--checker) top left / 4px 4px}.ag-charts-color-picker__alpha-input:before{background:linear-gradient(to right,transparent,var(--color)),var(--checker) top left / 4px 4px}.ag-charts-color-picker__color-field{display:flex;border:var(--ag-charts-border);background:var(--ag-charts-background-color);border-radius:var(--ag-charts-border-radius);overflow:hidden}.ag-charts-color-picker__color-field:has(:focus-visible){border-color:var(--ag-charts-accent-color);box-shadow:var(--ag-charts-focus-border-shadow)}.ag-charts-color-picker__color-label{width:16px;height:16px;margin:7px 0 7px 7px;color:transparent;background:linear-gradient(to right,var(--color-a),var(--color-a)),var(--checker) top left / 4px 4px;border-radius:calc(var(--ag-charts-border-radius) / 2);box-shadow:inset 0 0 0 1px #0003}.ag-charts-color-picker__color-label--multi-color{background:var(--multi-color)}.ag-charts-color-picker__color-input{flex:1;min-width:0;padding:7px 7px 7px 8px;border:0;margin:0;color:inherit;background:transparent;font-variant:tabular-nums}.ag-charts-color-picker__color-input:focus-visible{border:none;outline:none}.ag-charts-annotations__line-stroke-width-menu,.ag-charts-annotations__line-style-type-menu,.ag-charts-annotations__text-size-menu{border-top-left-radius:0;border-top-right-radius:0;.ag-charts-menu__row:first-child{border-radius:0}}.ag-charts-annotations__text-size-menu{--item-padding: 4px 8px;min-width:34px;text-align:center}.ag-charts-annotations__line-stroke-width-menu{--item-padding: 6px;column-gap:6px}.ag-charts-annotations__line-style-type-menu{--item-padding: 6px;column-gap:0}.ag-charts-annotations__stroke-width-button:before{background:var(--ag-charts-foreground-color);content:"";margin-right:var(--toolbar-button-padding);height:min(var(--stroke-width),20px);width:12px}.ag-charts-annotations__stroke-width-button[aria-disabled=true]:before{filter:grayscale(1);opacity:.5}.ag-charts-annotations__color-picker-button{--emblem: var(--color)}.ag-charts-annotations__color-picker-button--multi-color{--emblem: linear-gradient( to right, #f00 0% , #ff0 calc(100% * 1 / 6), #0f0 calc(100% * 2 / 6), #0ff 50% , #00f calc(100% * 4 / 6), #f0f calc(100% * 5 / 6), #f00 100% )}.ag-charts-annotations__color-picker-button:after{content:"";display:block;position:absolute;bottom:3px;left:5px;right:5px;height:4px;border-radius:99px;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--ag-charts-foreground-color) 10%,transparent);background:var(--emblem)}.ag-charts-annotations__color-picker-button[aria-disabled=true]:after{filter:grayscale(1);opacity:.5}.ag-charts-annotations__toolbar-menu{min-width:200px}.ag-charts-annotations__axis-button--hidden{display:none}.ag-charts-annotations__axis-button{background-color:var(--ag-charts-crosshair-label-background-color);border-radius:calc(var(--ag-charts-border-radius) / 2);border:none;box-sizing:border-box;color:var(--ag-charts-crosshair-label-text-color);cursor:pointer;font-family:var(--ag-charts-button-font-family);font-size:var(--ag-charts-button-font-size);font-weight:var(--ag-charts-button-font-weight);left:0;line-height:16px;overflow:hidden;padding:0;position:absolute;top:0;user-select:none;white-space:nowrap;z-index:var(--ag-charts-layer-annotations)}.ag-charts-annotations__axis-button:hover{opacity:.8;color:var(--ag-charts-background-color)}.ag-charts-dialog--annotation-settings{min-height:233px;width:289px}.ag-charts-dialog--annotation-settings .ag-charts-textarea{height:calc(10px * 2 + var(--textarea-line-height) * 1em * 3 + 2px);overflow-y:auto;resize:vertical}.ag-charts-context-menu{font-family:var(--ag-charts-chrome-font-family);font-size:var(--ag-charts-chrome-font-size);font-weight:var(--ag-charts-chrome-font-weight);z-index:var(--ag-charts-layer-ui-overlay)}.ag-charts-context-menu__cover{position:fixed;left:0;top:0}.ag-charts-context-menu__menu{background:var(--ag-charts-menu-background-color);border-radius:var(--ag-charts-border-radius);border:var(--ag-charts-menu-border);box-shadow:var(--ag-charts-popup-shadow);color:var(--ag-charts-menu-text-color);display:flex;flex-direction:column;padding:.5em 0;transition:transform .1s ease;white-space:nowrap}.ag-charts-context-menu__menu:focus{outline:none}.ag-charts-context-menu__item{align-items:center;background:none;border:none;box-sizing:border-box;color:inherit;cursor:pointer;display:flex;font:inherit;justify-content:space-between;text-align:left;width:100%;-webkit-appearance:none;-moz-appearance:none}.ag-charts-context-menu__icon>img{width:var(--ag-charts-icon-size);height:var(--ag-charts-icon-size)}.ag-charts-context-menu__icon,.ag-charts-context-menu__cell{display:flex;align-items:center;flex-shrink:0}.ag-charts-context-menu__cell{flex-grow:1}.ag-charts-context-menu__cellpadding{padding:.5em 1em}.ag-charts-context-menu__icon{padding-right:0}.ag-charts-context-menu__item[data-focus-override=true],.ag-charts-context-menu__item:focus,.ag-charts-context-menu__item:active{background:var(--ag-charts-focus-color)}.ag-charts-context-menu__item[data-focus-override=false]{background:inherit}.ag-charts-context-menu__item[data-focus-visible-override=true]:focus,.ag-charts-context-menu__item:focus-visible{outline:var(--ag-charts-focus-border);box-shadow:var(--ag-charts-focus-border-shadow);z-index:calc(var(--ag-charts-layer-ui-overlay) + 1)}.ag-charts-context-menu__item[data-focus-visible-override=false]{outline:inherit;box-shadow:inherit;z-index:inherit}.ag-charts-context-menu__item[aria-disabled=true]{border:none;color:color-mix(in srgb,var(--ag-charts-input-text-color) 50%,transparent)}.ag-charts-context-menu__item[aria-disabled=true]:focus{background:inherit;cursor:inherit}.ag-charts-context-menu__divider{padding:5px 0}.ag-charts-context-menu__divider:after{content:"";display:block;border-top:1px solid var(--ag-charts-border-color)}.ag-charts-crosshair-label{position:absolute;left:0;top:0;user-select:none;pointer-events:none;font-family:var(--ag-charts-font-family);font-size:var(--ag-charts-font-size);font-weight:var(--ag-charts-font-weight);overflow:hidden;white-space:nowrap;z-index:var(--ag-charts-layer-crosshair);box-sizing:border-box}.ag-charts-crosshair-label-content{padding:0 8px;border-radius:calc(var(--ag-charts-border-radius) / 2);line-height:calc(var(--ag-charts-font-size) + 8px);background-color:var(--ag-charts-crosshair-label-background-color);color:var(--ag-charts-crosshair-label-text-color)}.ag-charts-crosshair-label--hidden{visibility:hidden!important}.ag-charts-text-input{position:absolute}.ag-charts-text-input__textarea{--placeholder-text-color: var(--ag-charts-input-placeholder-text-color);display:block;height:100%;width:100%;border:0;background:none;line-height:1.38;outline:none;transform:translateY(.09em)}.ag-charts-text-input__textarea[placeholder]:empty:before{content:attr(placeholder);color:var(--placeholder-text-color);font-weight:400}.ag-charts-text-input__textarea[placeholder]:not(:empty):before{content:""}.ag-charts-chart-toolbar__menu{min-width:200px}.ag-charts-range-buttons .ag-charts-toolbar__button{padding:var(--toolbar-button-padding) calc(var(--toolbar-button-padding) * 1.5)}.ag-charts-zoom-buttons{align-items:center;display:flex;height:44px;justify-content:center;overflow:hidden;padding-bottom:10px;pointer-events:none;width:100%;.ag-charts-toolbar{--toolbar-size: 24px;--toolbar-button-padding: 1px;display:flex;font-size:var(--ag-charts-chrome-font-size);height:var(--toolbar-size);justify-content:center;opacity:1;pointer-events:auto;transition:opacity .2s ease-in-out,transform .4s ease-in-out;.ag-charts-toolbar__button--first{border-bottom-left-radius:var(--ag-charts-border-radius);border-top-left-radius:var(--ag-charts-border-radius)}.ag-charts-toolbar__button--last{border-bottom-right-radius:var(--ag-charts-border-radius);border-top-right-radius:var(--ag-charts-border-radius)}.ag-charts-toolbar__label{padding-left:var(--ag-charts-spacing);padding-right:var(--ag-charts-spacing)}.ag-charts-toolbar__icon+.ag-charts-toolbar__label{padding-left:0}.ag-charts-toolbar__button--gap{margin-left:var(--toolbar-gap)}&.ag-charts-zoom-buttons__toolbar--hidden{opacity:0;transition:opacity .4s ease-in-out,transform .4s ease-in-out}}}.ag-charts-shared-toolbar{gap:var(--toolbar-gap);.ag-charts-toolbar__button{border-radius:var(--ag-charts-border-radius);margin:0}.ag-charts-toolbar__button--active+.ag-charts-toolbar__button{border-left-color:var(--ag-charts-border-color)}}
`;
// packages/ag-charts-types/src/chart/navigatorOptions.ts
var __MINI_CHART_SERIES_OPTIONS = void 0;
var __VERIFY_MINI_CHART_SERIES_OPTIONS = void 0;
__VERIFY_MINI_CHART_SERIES_OPTIONS = __MINI_CHART_SERIES_OPTIONS;
// packages/ag-charts-types/src/chart/themeOptions.ts
var __THEME_OVERRIDES = void 0;
var __VERIFY_THEME_OVERRIDES = void 0;
__VERIFY_THEME_OVERRIDES = __THEME_OVERRIDES;
// packages/ag-charts-types/src/chart/tooltipOptions.ts
var AgTooltipAnchorToType = /* @__PURE__ */ ((AgTooltipAnchorToType2) => {
AgTooltipAnchorToType2["POINTER"] = "pointer";
AgTooltipAnchorToType2["NODE"] = "node";
AgTooltipAnchorToType2["CHART"] = "chart";
return AgTooltipAnchorToType2;
})(AgTooltipAnchorToType || {});
var AgTooltipPlacementType = /* @__PURE__ */ ((AgTooltipPlacementType2) => {
AgTooltipPlacementType2["TOP"] = "top";
AgTooltipPlacementType2["RIGHT"] = "right";
AgTooltipPlacementType2["BOTTOM"] = "bottom";
AgTooltipPlacementType2["LEFT"] = "left";
AgTooltipPlacementType2["TOP_RIGHT"] = "top-right";
AgTooltipPlacementType2["BOTTOM_RIGHT"] = "bottom-right";
AgTooltipPlacementType2["BOTTOM_LEFT"] = "bottom-left";
AgTooltipPlacementType2["TOP_LEFT"] = "top-left";
AgTooltipPlacementType2["CENTER"] = "center";
return AgTooltipPlacementType2;
})(AgTooltipPlacementType || {});
// packages/ag-charts-types/src/presets/gauge/commonOptions.ts
var __THEMEABLE_OPTIONS = void 0;
var __VERIFY_THEMEABLE_OPTIONS = void 0;
__VERIFY_THEMEABLE_OPTIONS = __THEMEABLE_OPTIONS;
var __AXIS_LABEL_OPTIONS = void 0;
var __VERIFY_AXIS_LABEL_OPTIONS = void 0;
__VERIFY_AXIS_LABEL_OPTIONS = __AXIS_LABEL_OPTIONS;
// packages/ag-charts-enterprise/src/main.ts
export * from "ag-charts-community";
// packages/ag-charts-enterprise/src/axes/angle-category/angleCategoryAxisModule.ts
import { VERSION, _ModuleSupport as _ModuleSupport9 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/axes/angle-category/angleCategoryAxis.ts
import { _ModuleSupport as _ModuleSupport8 } from "ag-charts-community";
import { Property as Property7, isNumberEqual as isNumberEqual3 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/utils/polar.ts
function walkPairsOutward(items, step, visitPair) {
const middleIndex = Math.floor(items.length / 2);
return walkPairsByStep(items, step, middleIndex, step, visitPair) || walkPairsByStep(items, items.length - step, middleIndex, -step, visitPair);
}
function walkPairsByStep(items, startIndex, endIndex, step, visitPair) {
let previous = items[0];
for (let i = startIndex; step > 0 ? i <= endIndex : i > endIndex; i += step) {
const current = items[i];
if (visitPair(previous, current)) {
return true;
}
previous = current;
}
return false;
}
// packages/ag-charts-enterprise/src/axes/angle-number/angleAxisInterval.ts
import { _ModuleSupport as _ModuleSupport4 } from "ag-charts-community";
import { Property as Property4 } from "ag-charts-core";
var { AxisInterval } = _ModuleSupport4;
var AngleAxisInterval = class extends AxisInterval {
};
__decorateClass([
Property4
], AngleAxisInterval.prototype, "minSpacing", 2);
// packages/ag-charts-enterprise/src/axes/angle/angleAxis.ts
import { _ModuleSupport as _ModuleSupport7 } from "ag-charts-community";
import {
ChartAxisDirection as ChartAxisDirection3,
Property as Property6,
countFractionDigits,
isNumberEqual as isNumberEqual2,
normalizeAngle360 as normalizeAngle3602,
normalizeAngle360Inclusive,
toRadians,
wrapTextOrSegments
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/axes/polar-crosslines/angleCrossLine.ts
import { _ModuleSupport as _ModuleSupport6 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection2, isNumberEqual, normalizeAngle360 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/axes/polar-crosslines/polarCrossLine.ts
import { _ModuleSupport as _ModuleSupport5 } from "ag-charts-community";
import { BaseProperties as BaseProperties2, ChartAxisDirection, Property as Property5, createId } from "ag-charts-core";
var { Group, LabelStyle } = _ModuleSupport5;
var PolarCrossLineLabel = class extends LabelStyle {
constructor() {
super(...arguments);
this.padding = 5;
}
};
__decorateClass([
Property5
], PolarCrossLineLabel.prototype, "enabled", 2);
__decorateClass([
Property5
], PolarCrossLineLabel.prototype, "padding", 2);
__decorateClass([
Property5
], PolarCrossLineLabel.prototype, "text", 2);
__decorateClass([
Property5
], PolarCrossLineLabel.prototype, "parallel", 2);
var PolarCrossLine = class extends BaseProperties2 {
constructor() {
super(...arguments);
this.id = createId(this);
this.defaultColorRange = [];
this.shape = "polygon";
this.label = new PolarCrossLineLabel();
this.scale = void 0;
this.clippedRange = [-Infinity, Infinity];
this.gridLength = 0;
this.sideFlag = -1;
this.parallelFlipRotation = 0;
this.regularFlipRotation = 0;
this.direction = ChartAxisDirection.Angle;
this.axisInnerRadius = 0;
this.axisOuterRadius = 0;
this.lineGroup = new Group({ name: this.id });
this.rangeGroup = new Group({ name: this.id });
this.labelGroup = new Group({ name: this.id });
this._isRange = void 0;
}
assignCrossLineGroup(isRange, crossLineRange) {
if (isRange !== this._isRange) {
if (isRange) {
this.rangeGroup.appendChild(crossLineRange);
} else {
this.lineGroup.appendChild(crossLineRange);
}
}
this._isRange = isRange;
}
setSectorNodeProps(node) {
node.fill = this.fill;
node.fillOpacity = this.fillOpacity ?? 1;
node.stroke = this.stroke;
node.strokeOpacity = this.strokeOpacity ?? 1;
node.strokeWidth = this.strokeWidth ?? 1;
node.lineDash = this.lineDash;
}
setLabelNodeProps(node, x, y, baseline, rotation) {
const { label } = this;
node.x = x;
node.y = y;
node.text = label.text;
node.textAlign = "center";
node.textBaseline = baseline;
node.rotation = rotation;
node.rotationCenterX = x;
node.rotationCenterY = y;
node.fill = label.color;
node.setFont(label);
node.setBoxing(label);
node.visible = true;
}
};
PolarCrossLine.className = "PolarCrossLine";
__decorateClass([
Property5
], PolarCrossLine.prototype, "enabled", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "type", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "range", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "value", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "defaultColorRange", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "fill", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "fillOpacity", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "stroke", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "strokeWidth", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "strokeOpacity", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "lineDash", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "shape", 2);
__decorateClass([
Property5
], PolarCrossLine.prototype, "label", 2);
// packages/ag-charts-enterprise/src/axes/polar-crosslines/angleCrossLine.ts
var { getCrossLineValue, validateCrossLineValue, Group: Group2, Path, Sector, RotatableText, ContinuousScale } = _ModuleSupport6;
var AngleCrossLine = class extends PolarCrossLine {
constructor() {
super();
this.direction = ChartAxisDirection2.Angle;
this.polygonNode = new Path();
this.sectorNode = new Sector();
this.lineNode = new Path();
this.crossLineRange = new Group2();
this.labelNode = new RotatableText();
this.ticks = [];
this.crossLineRange.append(this.polygonNode);
this.crossLineRange.append(this.sectorNode);
this.crossLineRange.append(this.lineNode);
this.labelGroup.append(this.labelNode);
}
visibilityCheck() {
if (!ContinuousScale.is(this.scale)) {
return true;
}
const [d0, d1] = this.scale.domain;
const value = getCrossLineValue(this);
if (this.type === "range") {
const [start, end] = value;
return start >= d0 && start <= d1 && end >= start && end <= d1;
} else {
return value >= d0 && value <= d1;
}
}
update(visible) {
const { scale } = this;
if (!scale || !validateCrossLineValue(this, scale) || !this.visibilityCheck()) {
this.rangeGroup.visible = false;
this.lineGroup.visible = false;
this.labelGroup.visible = false;
return;
}
this.rangeGroup.visible = visible;
this.lineGroup.visible = visible;
this.labelGroup.visible = visible;
this.updateLineNode(visible);
this.updatePolygonNode(visible);
this.updateSectorNode(visible);
this.updateLabelNode(visible);
}
updateLineNode(visible) {
const { scale, type, value, lineNode: line } = this;
if (!visible || type !== "line" || !scale) {
line.visible = false;
return;
}
const angle = scale.convert(value);
if (Number.isNaN(angle)) {
line.visible = false;
return;
}
const { axisInnerRadius, axisOuterRadius } = this;
line.visible = true;
line.stroke = this.stroke;
line.strokeOpacity = this.strokeOpacity ?? 1;
line.strokeWidth = this.strokeWidth ?? 1;
line.fill = void 0;
line.lineDash = this.lineDash;
const x = axisOuterRadius * Math.cos(angle);
const y = axisOuterRadius * Math.sin(angle);
const x0 = axisInnerRadius * Math.cos(angle);
const y0 = axisInnerRadius * Math.sin(angle);
line.path.clear(true);
line.path.moveTo(x0, y0);
line.path.lineTo(x, y);
this.assignCrossLineGroup(false, this.crossLineRange);
}
updatePolygonNode(visible) {
const { polygonNode: polygon, range: range2, scale, shape, type, ticks } = this;
if (!visible || type !== "range" || shape !== "polygon" || !scale || !range2) {
polygon.visible = false;
return;
}
const { axisInnerRadius, axisOuterRadius } = this;
const startIndex = ticks.indexOf(range2[0]);
const endIndex = ticks.indexOf(range2[1]);
const stops = startIndex <= endIndex ? ticks.slice(startIndex, endIndex + 1) : ticks.slice(startIndex).concat(ticks.slice(0, endIndex + 1));
const angles = stops.map((value) => scale.convert(value));
polygon.visible = true;
this.setSectorNodeProps(polygon);
const { path } = polygon;
path.clear(true);
for (const [index, angle] of angles.entries()) {
const x = axisOuterRadius * Math.cos(angle);
const y = axisOuterRadius * Math.sin(angle);
if (index === 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
}
if (axisInnerRadius === 0) {
path.lineTo(0, 0);
} else {
const reversedAngles = angles.slice().reverse();
for (const angle of reversedAngles) {
const x = axisInnerRadius * Math.cos(angle);
const y = axisInnerRadius * Math.sin(angle);
path.lineTo(x, y);
}
}
polygon.path.closePath();
this.assignCrossLineGroup(true, this.crossLineRange);
}
updateSectorNode(visible) {
const { sectorNode: sector, range: range2, scale, shape, type } = this;
if (!visible || type !== "range" || shape !== "circle" || !scale || !range2) {
sector.visible = false;
return;
}
const { axisInnerRadius, axisOuterRadius } = this;
const angles = range2.map((value) => scale.convert(value));
const step = scale.step ?? 0;
const padding2 = scale instanceof _ModuleSupport6.BandScale ? step / 2 : 0;
sector.visible = true;
this.setSectorNodeProps(sector);
sector.centerX = 0;
sector.centerY = 0;
sector.innerRadius = axisInnerRadius;
sector.outerRadius = axisOuterRadius;
sector.startAngle = angles[0] - padding2;
sector.endAngle = angles[1] + padding2;
this.assignCrossLineGroup(true, this.crossLineRange);
}
updateLabelNode(visible) {
const { label, labelNode: node, range: range2, scale, type, ticks } = this;
if (!visible || label.enabled === false || !label.text || !scale || type === "range" && !range2) {
node.visible = false;
return;
}
node.visible = true;
const { axisInnerRadius, axisOuterRadius } = this;
let labelX;
let labelY;
let rotation;
let textBaseline;
if (type === "line") {
const angle = normalizeAngle360(scale.convert(this.value));
const angle270 = 1.5 * Math.PI;
const isRightSide = isNumberEqual(angle, angle270) || angle > angle270 || angle < Math.PI / 2;
const midX = (axisInnerRadius + axisOuterRadius) / 2 * Math.cos(angle);
const midY = (axisInnerRadius + axisOuterRadius) / 2 * Math.sin(angle);
labelX = midX + label.padding * Math.cos(angle + Math.PI / 2);
labelY = midY + label.padding * Math.sin(angle + Math.PI / 2);
textBaseline = isRightSide ? "top" : "bottom";
rotation = isRightSide ? angle : angle - Math.PI;
} else {
const [startAngle, endAngle] = range2.map((value) => normalizeAngle360(scale.convert(value)));
let angle = (startAngle + endAngle) / 2;
if (startAngle > endAngle) {
angle -= Math.PI;
}
angle = normalizeAngle360(angle);
const isBottomSide = (isNumberEqual(angle, 0) || angle > 0) && angle < Math.PI;
let distance;
if (this.shape === "circle" || ticks.length < 3) {
distance = axisOuterRadius - label.padding;
} else {
distance = axisOuterRadius * Math.cos(Math.PI / ticks.length) - label.padding;
}
labelX = distance * Math.cos(angle);
labelY = distance * Math.sin(angle);
textBaseline = isBottomSide ? "bottom" : "top";
rotation = isBottomSide ? angle - Math.PI / 2 : angle + Math.PI / 2;
}
this.setLabelNodeProps(node, labelX, labelY, textBaseline, rotation);
}
};
AngleCrossLine.className = "AngleCrossLine";
// packages/ag-charts-enterprise/src/axes/angle/angleAxis.ts
var { Path: Path2, RotatableText: RotatableText2, Transformable, BBox, Selection, Line } = _ModuleSupport7;
var AngleAxisLabel = class extends _ModuleSupport7.AxisLabel {
constructor() {
super(...arguments);
this.orientation = "fixed";
}
};
__decorateClass([
Property6
], AngleAxisLabel.prototype, "orientation", 2);
var AngleAxis = class extends _ModuleSupport7.PolarAxis {
constructor(moduleCtx, scale) {
super(moduleCtx, scale);
this.startAngle = 0;
this.endAngle = void 0;
this.tickLineGroupSelection = Selection.select(
this.tickLineGroup,
Line,
false
);
this.gridLineGroupSelection = Selection.select(
this.gridLineGroup,
Line,
false
);
this.labelData = [];
this.tickData = [];
this.radiusLineGroup = this.axisGroup.appendChild(new _ModuleSupport7.TransformableGroup());
this.radiusLine = this.radiusLineGroup.appendChild(new Path2());
this.includeInvisibleDomains = true;
}
get direction() {
return ChartAxisDirection3.Angle;
}
createLabel() {
return new AngleAxisLabel();
}
calculateRotations() {
const rotation = toRadians(this.startAngle);
const parallelFlipRotation = normalizeAngle3602(rotation);
const regularFlipRotation = normalizeAngle3602(rotation - Math.PI / 2);
return { rotation, parallelFlipRotation, regularFlipRotation };
}
calculateTickLayout(domain) {
const { nice, scale } = this;
const ticksParams = {
nice: [nice, nice],
interval: void 0,
tickCount: void 0,
minTickCount: 0,
maxTickCount: Infinity
};
const niceDomain = nice ? scale.niceDomain(ticksParams, domain) : domain;
const tickData = this.generateAngleTicks(niceDomain);
this.tickData = tickData;
const ticks = tickData.map((t) => t.value);
const fractionDigits = ticks.reduce(
(f, t) => Math.max(typeof t === "number" ? countFractionDigits(t) : 0, f),
0
);
return {
niceDomain,
tickDomain: niceDomain,
ticks,
rawTickCount: void 0,
fractionDigits,
timeInterval: void 0,
bbox: this.getBBox()
};
}
update() {
super.update();
this.updateRadiusLine();
this.updateGridLines();
this.updateTickLines();
}
normalizedAngles() {
const startAngle = normalizeAngle3602(-Math.PI / 2 + toRadians(this.startAngle));
const sweep = this.endAngle == null ? 2 * Math.PI : normalizeAngle360Inclusive(toRadians(this.endAngle) - toRadians(this.startAngle));
const endAngle = startAngle + sweep;
return [startAngle, endAngle];
}
computeRange() {
this.range = this.normalizedAngles();
}
updateSelections() {
const data = this.tickData;
this.gridLineGroupSelection.update(this.gridLength && this.gridLine.enabled ? data : []);
this.tickLineGroupSelection.update(this.tick.enabled ? data : []);
this.tickLabelGroupSelection.update(this.label.enabled ? data : []);
this.gridLineGroupSelection.cleanup();
this.tickLineGroupSelection.cleanup();
this.tickLabelGroupSelection.cleanup();
}
updatePosition() {
super.updatePosition();
const { translation, radiusLineGroup } = this;
const translationX = Math.floor(translation.x);
const translationY = Math.floor(translation.y);
radiusLineGroup.translationX = translationX;
radiusLineGroup.translationY = translationY;
}
updateRadiusLine() {
const node = this.radiusLine;
const { path } = node;
path.clear(true);
const { points, closePath } = this.getAxisLinePoints();
for (const { x, y, moveTo: moveTo2, arc, radius = 0, startAngle = 0, endAngle = 0 } of points) {
if (arc) {
path.arc(x, y, radius, startAngle, endAngle);
} else if (moveTo2) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
}
if (closePath) {
path.closePath();
}
node.visible = this.line.enabled;
node.stroke = this.line.stroke;
node.strokeWidth = this.line.width;
node.fill = void 0;
}
getAxisLinePoints() {
const { scale, shape, gridLength: radius } = this;
const [startAngle, endAngle] = this.range;
const isFullCircle = isNumberEqual2(endAngle - startAngle, 2 * Math.PI);
const points = [];
if (shape === "circle") {
if (isFullCircle) {
points.push(
{ x: radius, y: 0, moveTo: true },
{
x: 0,
y: 0,
radius,
startAngle: 0,
endAngle: 2 * Math.PI,
arc: true,
moveTo: false
}
);
} else {
points.push(
{
x: radius * Math.cos(startAngle),
y: radius * Math.sin(startAngle),
moveTo: true
},
{
x: 0,
y: 0,
radius,
startAngle: normalizeAngle3602(startAngle),
endAngle: normalizeAngle3602(endAngle),
arc: true,
moveTo: false
}
);
}
} else if (shape === "polygon") {
const angles = scale.ticks({
nice: [this.nice, this.nice],
interval: void 0,
tickCount: void 0,
minTickCount: 0,
maxTickCount: Infinity
})?.ticks?.map((value) => scale.convert(value));
if (angles && angles.length > 2) {
for (const [i, angle] of angles.entries()) {
const x = radius * Math.cos(angle);
const y = radius * Math.sin(angle);
const moveTo2 = i === 0;
points.push({ x, y, moveTo: moveTo2 });
}
}
}
return { points, closePath: isFullCircle };
}
updateGridLines() {
const {
scale,
gridLength: radius,
gridLine: { style, width },
innerRadiusRatio
} = this;
if (!(style && radius > 0)) {
return;
}
const innerRadius = radius * innerRadiusRatio;
const styleCount = style.length;
this.gridLineGroupSelection.each((line, datum, index) => {
const { value } = datum;
const { stroke: stroke3, lineDash } = style[index % styleCount];
const angle = scale.convert(value);
line.x1 = innerRadius * Math.cos(angle);
line.y1 = innerRadius * Math.sin(angle);
line.x2 = radius * Math.cos(angle);
line.y2 = radius * Math.sin(angle);
line.stroke = stroke3;
line.strokeWidth = width;
line.lineDash = lineDash;
line.fill = void 0;
});
this.gridLineGroupSelection.cleanup();
}
updateLabels() {
const { label, tickLabelGroupSelection } = this;
tickLabelGroupSelection.each((node, _, index) => {
const labelDatum = this.labelData[index];
if (!labelDatum || labelDatum.hidden) {
node.visible = false;
return;
}
node.text = labelDatum.text;
node.setFont(label);
node.fill = label.color;
node.x = labelDatum.x;
node.y = labelDatum.y;
node.setAlign(labelDatum);
node.setBoxing(label);
node.visible = true;
if (labelDatum.rotation) {
node.rotation = labelDatum.rotation;
node.rotationCenterX = labelDatum.x;
node.rotationCenterY = labelDatum.y;
} else {
node.rotation = 0;
}
});
}
updateTickLines() {
const { scale, gridLength: radius, tick, tickLineGroupSelection } = this;
tickLineGroupSelection.each((line, datum) => {
const { value } = datum;
const angle = scale.convert(value);
const cos = Math.cos(angle);
const sin = Math.sin(angle);
line.x1 = radius * cos;
line.y1 = radius * sin;
line.x2 = (radius + tick.size) * cos;
line.y2 = (radius + tick.size) * sin;
line.stroke = tick.stroke;
line.strokeWidth = tick.width;
});
}
createLabelNodeData(ticks, options, seriesRect) {
const { label, gridLength: radius, scale, tick } = this;
if (!label.enabled) {
return [];
}
const tempText = new RotatableText2();
const seriesLeft = seriesRect.x - this.translation.x;
const seriesRight = seriesRect.x + seriesRect.width - this.translation.x;
const { fractionDigits } = this.layout.label;
const axisTickFormatter = this.tickFormatter(this.scale.domain, this.tickData, false, fractionDigits);
const labelData = ticks.map((datum, index) => {
const { value } = datum;
const distance = radius + label.spacing + tick.size;
const angle = scale.convert(value);
const cos = Math.cos(angle);
const sin = Math.sin(angle);
const x = distance * cos;
const y = distance * sin;
const { textAlign, textBaseline } = this.getLabelAlign(angle);
const isLastTickOverFirst = index === ticks.length - 1 && value !== ticks[0] && isNumberEqual2(normalizeAngle3602(angle), normalizeAngle3602(scale.convert(ticks[0])));
const rotation = this.getLabelRotation(angle);
let text2 = axisTickFormatter(value, index);
tempText.text = text2;
tempText.x = x;
tempText.y = y;
tempText.setFont(label);
tempText.textAlign = textAlign;
tempText.textBaseline = textBaseline;
tempText.rotation = rotation;
if (rotation) {
tempText.rotationCenterX = x;
tempText.rotationCenterY = y;
}
let box = rotation ? Transformable.toCanvas(tempText) : tempText.getBBox();
if (box && options.hideWhenNecessary && !rotation) {
const overflowLeft = seriesLeft - box.x;
const overflowRight = box.x + box.width - seriesRight;
const pixelError = 1;
if (overflowLeft > pixelError || overflowRight > pixelError) {
const availWidth = box.width - Math.max(overflowLeft, overflowRight);
const wrapOptions = { maxWidth: availWidth, font: label, textWrap: "never" };
text2 = wrapTextOrSegments(text2, wrapOptions);
tempText.text = text2;
box = tempText.getBBox();
}
}
return {
text: text2,
x,
y,
textAlign,
textBaseline,
hidden: text2 === "" || (datum.hidden ?? isLastTickOverFirst),
rotation,
box
};
});
if (label.avoidCollisions) {
this.avoidLabelCollisions(labelData);
}
return labelData;
}
computeLabelsBBox(options, seriesRect) {
this.labelData = this.createLabelNodeData(this.tickData, options, seriesRect);
const textBoxes = this.labelData.map(({ box }) => box).filter((box) => box != null);
if (!this.label.enabled || textBoxes.length === 0) {
return null;
}
return BBox.merge(textBoxes);
}
getLabelOrientation() {
const { label } = this;
return label instanceof AngleAxisLabel ? label.orientation : "fixed";
}
getLabelRotation(tickAngle) {
let rotation = toRadians(this.label.rotation ?? 0);
tickAngle = normalizeAngle3602(tickAngle);
const orientation = this.getLabelOrientation();
if (orientation === "parallel") {
rotation += tickAngle;
if (tickAngle >= 0 && tickAngle < Math.PI) {
rotation -= Math.PI / 2;
} else {
rotation += Math.PI / 2;
}
} else if (orientation === "perpendicular") {
rotation += tickAngle;
if (tickAngle >= Math.PI / 2 && tickAngle < 1.5 * Math.PI) {
rotation += Math.PI;
}
}
return rotation;
}
getLabelAlign(tickAngle) {
const cos = Math.cos(tickAngle);
const sin = Math.sin(tickAngle);
let textAlign;
let textBaseline;
const orientation = this.getLabelOrientation();
const isCos0 = isNumberEqual2(cos, 0);
const isSin0 = isNumberEqual2(sin, 0);
const isCos1 = isNumberEqual2(cos, 1);
const isSinMinus1 = isNumberEqual2(sin, -1);
const isCosPositive = cos > 0 && !isCos0;
const isSinPositive = sin > 0 && !isSin0;
if (orientation === "parallel") {
textAlign = "center";
textBaseline = isCos1 && isSin0 || isSinPositive ? "top" : "bottom";
} else if (orientation === "perpendicular") {
textAlign = isSinMinus1 || isCosPositive ? "left" : "right";
textBaseline = "middle";
} else {
textAlign = "right";
if (isCos0) {
textAlign = "center";
} else if (isCosPositive) {
textAlign = "left";
}
textBaseline = "bottom";
if (isSin0) {
textBaseline = "middle";
} else if (isSinPositive) {
textBaseline = "top";
}
}
return { textAlign, textBaseline };
}
updateCrossLines() {
const { shape, gridLength: radius, innerRadiusRatio } = this;
for (const crossLine of this.crossLines) {
if (crossLine instanceof AngleCrossLine) {
crossLine.ticks = this.tickData.map((t) => t.value);
crossLine.shape = shape;
crossLine.axisOuterRadius = radius;
crossLine.axisInnerRadius = radius * innerRadiusRatio;
}
}
super.updateCrossLines();
}
};
AngleAxis.CrossLineConstructor = AngleCrossLine;
__decorateClass([
Property6
], AngleAxis.prototype, "startAngle", 2);
__decorateClass([
Property6
], AngleAxis.prototype, "endAngle", 2);
// packages/ag-charts-enterprise/src/axes/angle-category/angleCategoryAxis.ts
var { CategoryScale } = _ModuleSupport8;
var AngleCategoryAxis = class extends AngleAxis {
constructor(moduleCtx) {
super(moduleCtx, new CategoryScale());
this.groupPaddingInner = 0;
this.paddingInner = 0;
this.interval = new AngleAxisInterval();
}
hasDefinedDomain() {
return false;
}
generateAngleTicks(domain) {
const { scale, gridLength: radius } = this;
const { values, minSpacing } = this.interval;
const tickParams = {
nice: [this.nice, this.nice],
interval: void 0,
tickCount: void 0,
minTickCount: 0,
maxTickCount: Infinity
};
const ticks = values ?? scale.ticks(tickParams, domain)?.ticks ?? [];
if (ticks.length < 2 || minSpacing == null) {
return ticks.map((value) => {
return { value, visible: true };
});
}
const startTick = ticks[0];
const startAngle = scale.convert(startTick);
const startX = radius * Math.cos(startAngle);
const startY = radius * Math.sin(startAngle);
for (let step = 1; step < ticks.length - 1; step++) {
const nextTick = ticks[step];
const nextAngle = scale.convert(nextTick);
if (nextAngle - startAngle > Math.PI) {
break;
}
const nextX = radius * Math.cos(nextAngle);
const nextY = radius * Math.sin(nextAngle);
const spacing = Math.hypot(nextX - startX, nextY - startY);
if (spacing > minSpacing) {
const visibleTicks = /* @__PURE__ */ new Set([startTick]);
walkPairsOutward(ticks, step, (_, next) => {
visibleTicks.add(next);
});
return ticks.map((value) => {
const visible = visibleTicks.has(value);
return { value, visible };
});
}
}
return [{ value: startTick, visible: true }];
}
avoidLabelCollisions(labelData) {
const { minSpacing } = this.label;
if (labelData.length < 3)
return;
const labelsCollide = (prev, next) => {
if (prev.hidden || next.hidden) {
return false;
} else if (minSpacing == null) {
return prev.box.collidesBBox(next.box);
}
const prevBox = prev.box.clone().grow(minSpacing / 2);
const nextBox = next.box.clone().grow(minSpacing / 2);
return prevBox.collidesBBox(nextBox);
};
const firstLabel = labelData[0];
const lastLabel = labelData.at(-1);
const visibleLabels = /* @__PURE__ */ new Set([firstLabel]);
const lastLabelIsOverFirst = isNumberEqual3(firstLabel.x, lastLabel.x) && isNumberEqual3(firstLabel.y, lastLabel.y);
const maxStep = Math.floor(labelData.length / 2);
for (let step = 1; step <= maxStep; step++) {
const labels = lastLabelIsOverFirst ? labelData.slice(0, -1) : labelData;
const collisionDetected = walkPairsOutward(labels, step, labelsCollide);
if (!collisionDetected) {
walkPairsOutward(labels, step, (_, next) => {
visibleLabels.add(next);
});
break;
}
}
for (const datum of labelData) {
if (!visibleLabels.has(datum)) {
datum.hidden = true;
datum.box = void 0;
}
}
}
tickFormatParams() {
return { type: "category" };
}
datumFormatParams(value, params) {
const { datum, seriesId, legendItemName, key, source, property, domain, boundSeries } = params;
return { type: "category", value, datum, seriesId, legendItemName, key, source, property, domain, boundSeries };
}
};
AngleCategoryAxis.className = "AngleCategoryAxis";
AngleCategoryAxis.type = "angle-category";
__decorateClass([
Property7
], AngleCategoryAxis.prototype, "groupPaddingInner", 2);
__decorateClass([
Property7
], AngleCategoryAxis.prototype, "paddingInner", 2);
__decorateClass([
Property7
], AngleCategoryAxis.prototype, "interval", 2);
// packages/ag-charts-enterprise/src/axes/angle-category/angleCategoryAxisModule.ts
var AngleCategoryAxisModule = {
type: "axis",
name: "angle-category",
chartType: "polar",
enterprise: true,
version: VERSION,
options: _ModuleSupport9.angleCategoryAxisOptionsDefs,
themeTemplate: {
label: { spacing: 5 },
gridLine: { enabled: false },
shape: { $findFirstSiblingNotOperation: void 0 }
},
create: (ctx) => new AngleCategoryAxis(ctx)
};
// packages/ag-charts-enterprise/src/axes/angle-number/angleNumberAxisModule.ts
import { VERSION as VERSION2, _ModuleSupport as _ModuleSupport12 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/axes/angle-number/angleNumberAxis.ts
import "ag-charts-community";
import {
Property as Property8,
angleBetween,
findMinMax,
isNumberEqual as isNumberEqual5,
normalisedExtentWithMetadata
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/axes/angle-number/linearAngleScale.ts
import { _ModuleSupport as _ModuleSupport10 } from "ag-charts-community";
import { isDenseInterval, isNumberEqual as isNumberEqual4, range } from "ag-charts-core";
var { LinearScale } = _ModuleSupport10;
var LinearAngleScale = class _LinearAngleScale extends LinearScale {
constructor() {
super(...arguments);
this.arcLength = 0;
}
static getNiceStepAndTickCount(ticks, domain) {
const [start, stop] = domain;
let step = LinearScale.getTickStep(start, stop, ticks);
const maxTickCount = Number.isNaN(ticks.maxTickCount) ? Infinity : ticks.maxTickCount;
const expectedTickCount = Math.abs(stop - start) / step;
let niceTickCount = Math.pow(2, Math.ceil(Math.log(expectedTickCount) / Math.log(2)));
if (niceTickCount > maxTickCount) {
niceTickCount /= 2;
step *= 2;
}
return { count: niceTickCount, step };
}
ticks(ticks, domain = this.domain) {
const { arcLength } = this;
if (!domain || domain.length < 2 || domain.some((d) => !Number.isFinite(d)) || arcLength <= 0) {
return { ticks: [], count: 0 };
}
const { nice, interval } = ticks;
const [d0, d1] = domain;
if (interval) {
const step2 = Math.abs(interval);
const availableRange = this.getPixelRange();
if (!isDenseInterval((d1 - d0) / step2, availableRange)) {
const result2 = range(d0, d1, step2);
return { ticks: result2.ticks, count: result2.count };
}
}
let step;
if (nice && this.hasNiceRange()) {
const linearNiceDomain = super.niceDomain(ticks, domain);
step = _LinearAngleScale.getNiceStepAndTickCount(ticks, linearNiceDomain).step;
} else {
step = LinearScale.getTickStep(d0, d1, ticks);
}
const result = range(d0, d1, step);
return { ticks: result.ticks, count: result.count };
}
hasNiceRange() {
const sortedRange = this.range.slice().sort((a, b) => a - b);
const niceRanges = [Math.PI, 2 * Math.PI];
return niceRanges.some((r) => isNumberEqual4(r, sortedRange[1] - sortedRange[0]));
}
niceDomain(ticks, domain = this.domain) {
const linearNiceDomain = super.niceDomain(ticks, domain);
if (!this.hasNiceRange())
return linearNiceDomain;
const reversed = linearNiceDomain[0] > linearNiceDomain[1];
const start = reversed ? linearNiceDomain[1] : linearNiceDomain[0];
const { step, count } = _LinearAngleScale.getNiceStepAndTickCount(ticks, linearNiceDomain);
const s = 1 / step;
const stop = step >= 1 ? Math.ceil(start / step + count) * step : Math.ceil((start + count * step) * s) / s;
return reversed ? [stop, start] : [start, stop];
}
getPixelRange() {
return this.arcLength;
}
};
// packages/ag-charts-enterprise/src/axes/angle-number/angleNumberAxis.ts
var AngleNumberAxis = class extends AngleAxis {
constructor(moduleCtx) {
super(moduleCtx, new LinearAngleScale());
this.shape = "circle";
this.interval = new AngleAxisInterval();
}
hasDefinedDomain() {
const { min, max } = this;
return min != null && max != null && min < max;
}
normaliseDataDomain(d) {
const { min, max, preferredMin, preferredMax } = this;
const { extent: extent4, clipped } = normalisedExtentWithMetadata(
d.domain,
min,
max,
preferredMin,
preferredMax,
void 0,
d.sortMetadata?.sortOrder
);
return { domain: extent4, clipped };
}
getDomainExtentsNice() {
return [this.min == null && this.nice, this.max == null && this.nice];
}
updateScale() {
super.updateScale();
this.scale.arcLength = this.getRangeArcLength();
}
getRangeArcLength() {
const { range: requestedRange } = this;
const min = Math.min(...requestedRange);
const max = Math.max(...requestedRange);
const rotation = angleBetween(min, max) || 2 * Math.PI;
const radius = this.gridLength;
return rotation * radius;
}
generateAngleTicks(domain) {
const { scale, range: requestedRange, nice } = this;
const { values, step, minSpacing, maxSpacing } = this.interval;
let rawTicks;
if (values == null) {
const { arcLength } = scale;
const minTickCount = maxSpacing ? Math.floor(arcLength / maxSpacing) : 1;
const maxTickCount = minSpacing ? Math.floor(arcLength / minSpacing) : Infinity;
const preferredTickCount = Math.floor(4 / Math.PI * Math.abs(requestedRange[0] - requestedRange[1]));
const tickCount = Math.max(minTickCount, Math.min(maxTickCount, preferredTickCount));
const tickParams = {
nice: [nice, nice],
interval: step,
tickCount,
minTickCount,
maxTickCount
};
rawTicks = scale.ticks(tickParams, domain)?.ticks ?? [];
} else {
const [d0, d1] = findMinMax(domain.map(Number));
rawTicks = values.filter((value) => value >= d0 && value <= d1).sort((a, b) => a - b);
}
return rawTicks.map((value) => ({ value, visible: true }));
}
avoidLabelCollisions(labelData) {
const { minSpacing } = this.label;
const labelsCollide = (prev, next) => {
if (prev.hidden || next.hidden) {
return false;
} else if (minSpacing == null) {
return prev.box.collidesBBox(next.box);
}
const prevBox = prev.box.clone().grow(minSpacing / 2);
const nextBox = next.box.clone().grow(minSpacing / 2);
return prevBox.collidesBBox(nextBox);
};
const firstLabel = labelData[0];
const lastLabel = labelData.at(-1);
if (firstLabel !== lastLabel && isNumberEqual5(firstLabel.x, lastLabel.x) && isNumberEqual5(firstLabel.y, lastLabel.y)) {
lastLabel.hidden = true;
}
for (let step = 1; step < labelData.length; step *= 2) {
let collisionDetected = false;
for (let i = step; i < labelData.length; i += step) {
const next = labelData[i];
const prev = labelData[i - step];
if (labelsCollide(prev, next)) {
collisionDetected = true;
break;
}
}
if (!collisionDetected) {
for (const [i, datum] of labelData.entries()) {
if (i % step > 0) {
datum.hidden = true;
datum.box = void 0;
}
}
return;
}
}
for (const [i, datum] of labelData.entries()) {
if (i > 0) {
datum.hidden = true;
datum.box = void 0;
}
}
}
tickFormatParams(_domain, _ticks, fractionDigits) {
return { type: "number", visibleDomain: void 0, fractionDigits };
}
datumFormatParams(value, params, fractionDigits) {
const { datum, seriesId, legendItemName, key, source, property, domain, boundSeries } = params;
return {
type: "number",
value,
datum,
seriesId,
legendItemName,
key,
source,
property,
domain,
boundSeries,
fractionDigits,
visibleDomain: void 0
};
}
};
AngleNumberAxis.className = "AngleNumberAxis";
AngleNumberAxis.type = "angle-number";
__decorateClass([
Property8
], AngleNumberAxis.prototype, "min", 2);
__decorateClass([
Property8
], AngleNumberAxis.prototype, "max", 2);
__decorateClass([
Property8
], AngleNumberAxis.prototype, "preferredMin", 2);
__decorateClass([
Property8
], AngleNumberAxis.prototype, "preferredMax", 2);
__decorateClass([
Property8
], AngleNumberAxis.prototype, "interval", 2);
// packages/ag-charts-enterprise/src/axes/angle-number/angleNumberAxisModule.ts
var AngleNumberAxisModule = {
type: "axis",
name: "angle-number",
chartType: "polar",
enterprise: true,
version: VERSION2,
options: _ModuleSupport12.angleNumberAxisOptionsDefs,
themeTemplate: {
label: { spacing: 5 },
gridLine: { enabled: false }
},
create: (ctx) => new AngleNumberAxis(ctx)
};
// packages/ag-charts-enterprise/src/axes/ordinal/ordinalTimeAxisModule.ts
import { VERSION as VERSION3, _ModuleSupport as _ModuleSupport14 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/axes/ordinal/ordinalTimeAxis.ts
import {
_ModuleSupport as _ModuleSupport13
} from "ag-charts-community";
import {
Property as Property9,
dateTruncationForDomain,
intervalEpoch,
intervalMilliseconds,
intervalStep,
intervalUnit,
lowestGranularityUnitForTicks,
lowestGranularityUnitForValue
} from "ag-charts-core";
var {
OrdinalTimeScale,
ApproximateOrdinalTimeScale,
APPROXIMATE_THRESHOLD,
TimeAxisParentLevel,
minimumTimeAxisDatumGranularity
} = _ModuleSupport13;
var OrdinalTimeAxis = class extends _ModuleSupport13.DiscreteTimeAxis {
constructor(moduleCtx) {
const accurateScale = new OrdinalTimeScale();
super(moduleCtx, accurateScale);
this.parentLevel = new TimeAxisParentLevel();
this.accurateScale = accurateScale;
this.approximateScale = new ApproximateOrdinalTimeScale();
this.approximateScale.setSourceScale(accurateScale);
Object.defineProperty(this, "scale", {
get: () => this.getActiveScale(),
configurable: true
});
}
get primaryLabel() {
return this.parentLevel.enabled ? this.parentLevel.label : void 0;
}
get primaryTick() {
return this.parentLevel.enabled ? this.parentLevel.tick : void 0;
}
/**
* Returns the active scale based on visible range and data uniformity.
* Use approximate scale when data is uniform and visible datum count is large.
*/
getActiveScale() {
const visibleBandCount = this.accurateScale.bandCount(this.visibleRange);
const isUniform = this.accurateScale.getUniformityCache(this.visibleRange)?.isUniform ?? false;
if (isUniform && visibleBandCount >= APPROXIMATE_THRESHOLD) {
return this.approximateScale;
}
return this.accurateScale;
}
processData() {
super.processData();
const { boundSeries, direction } = this;
this.minimumTimeGranularity = minimumTimeAxisDatumGranularity(boundSeries, direction, void 0, void 0);
}
tickFormatParams(domain, ticks, _fractionDigits, timeInterval) {
timeInterval ?? (timeInterval = lowestGranularityUnitForTicks(ticks));
const truncateDate = dateTruncationForDomain(domain);
const unit = intervalUnit(timeInterval);
const step = intervalStep(timeInterval);
const epoch = intervalEpoch(timeInterval);
return { type: "date", unit, step, epoch, truncateDate };
}
datumFormatParams(value, params, _fractionDigits, timeInterval, style) {
if (typeof value === "number")
value = new Date(value);
if (timeInterval == null) {
const { minimumTimeGranularity } = this;
const datumGranularity = lowestGranularityUnitForValue(value);
if (minimumTimeGranularity != null && intervalMilliseconds(minimumTimeGranularity) < intervalMilliseconds(datumGranularity)) {
timeInterval = minimumTimeGranularity;
} else {
timeInterval = datumGranularity;
}
}
const { datum, seriesId, legendItemName, key, source, property, domain, boundSeries } = params;
const unit = intervalUnit(timeInterval);
const step = intervalStep(timeInterval);
const epoch = intervalEpoch(timeInterval);
return {
type: "date",
value,
datum,
seriesId,
legendItemName,
key,
source,
property,
domain,
boundSeries,
unit,
step,
epoch,
style
};
}
};
OrdinalTimeAxis.className = "OrdinalTimeAxis";
OrdinalTimeAxis.type = "ordinal-time";
__decorateClass([
Property9
], OrdinalTimeAxis.prototype, "parentLevel", 2);
// packages/ag-charts-enterprise/src/axes/ordinal/ordinalTimeAxisModule.ts
var OrdinalTimeAxisModule = {
type: "axis",
name: "ordinal-time",
chartType: "cartesian",
enterprise: true,
version: VERSION3,
options: _ModuleSupport14.ordinalTimeAxisOptionsDefs,
themeTemplate: {
groupPaddingInner: 0,
label: { autoRotate: false, minSpacing: 40 },
gridLine: { enabled: false },
interval: { placement: "between" }
},
create: (ctx) => new OrdinalTimeAxis(ctx)
};
// packages/ag-charts-enterprise/src/axes/radius-category/radiusCategoryAxisModule.ts
import { VERSION as VERSION4, _ModuleSupport as _ModuleSupport18 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/axes/radius-category/radiusCategoryAxis.ts
import { _ModuleSupport as _ModuleSupport17 } from "ag-charts-community";
import { Property as Property12, ProxyPropertyOnWrite as ProxyPropertyOnWrite2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/axes/radius/radiusAxis.ts
import { _ModuleSupport as _ModuleSupport16 } from "ag-charts-community";
import {
ChartAxisDirection as ChartAxisDirection5,
Property as Property11,
ZIndexMap as ZIndexMap2,
isNumberEqual as isNumberEqual7,
normalizeAngle360 as normalizeAngle3603,
toRadians as toRadians2
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/axes/polar-crosslines/radiusCrossLine.ts
import { _ModuleSupport as _ModuleSupport15 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection4, Property as Property10, clamp, isNumberEqual as isNumberEqual6, normalizeAngle360FromDegrees } from "ag-charts-core";
var { validateCrossLineValue: validateCrossLineValue2, Group: Group3, Path: Path3, Sector: Sector2, RotatableText: RotatableText3 } = _ModuleSupport15;
var RadiusCrossLineLabel = class extends PolarCrossLineLabel {
constructor() {
super(...arguments);
this.positionAngle = void 0;
}
};
__decorateClass([
Property10
], RadiusCrossLineLabel.prototype, "positionAngle", 2);
var RadiusCrossLine = class extends PolarCrossLine {
constructor() {
super();
this.direction = ChartAxisDirection4.Radius;
this.label = new RadiusCrossLineLabel();
this.polygonNode = new Path3();
this.sectorNode = new Sector2();
this.crossLineRange = new Group3();
this.labelNode = new RotatableText3();
this.outerRadius = 0;
this.innerRadius = 0;
this.crossLineRange.append(this.polygonNode);
this.crossLineRange.append(this.sectorNode);
this.labelGroup.append(this.labelNode);
}
update(visible) {
const { scale } = this;
if (!scale || !validateCrossLineValue2(this, scale)) {
this.rangeGroup.visible = false;
this.lineGroup.visible = false;
this.labelGroup.visible = false;
return;
}
this.updateRadii();
const { innerRadius, outerRadius } = this;
visible && (visible = innerRadius >= this.axisInnerRadius && outerRadius <= this.axisOuterRadius);
this.rangeGroup.visible = visible;
this.lineGroup.visible = visible;
this.labelGroup.visible = visible;
this.updatePolygonNode(visible);
this.updateSectorNode(visible);
this.updateLabelNode(visible);
this.assignCrossLineGroup(this.type === "range", this.crossLineRange);
}
updateRadii() {
const { range: range2, scale, type, axisInnerRadius, axisOuterRadius } = this;
if (!scale)
return { innerRadius: 0, outerRadius: 0 };
const getRadius = (value) => axisOuterRadius + axisInnerRadius - value;
let outerRadius, innerRadius;
if (type === "line") {
outerRadius = getRadius(scale.convert(this.value));
innerRadius = outerRadius;
} else {
const bandwidth = Math.abs(scale?.bandwidth ?? 0);
const convertedRange = range2.map((r) => scale.convert(r));
outerRadius = getRadius(Math.max(...convertedRange));
innerRadius = getRadius(Math.min(...convertedRange)) + bandwidth;
}
this.outerRadius = outerRadius;
this.innerRadius = innerRadius;
}
drawPolygon(radius, angles, polygon) {
for (const [index, angle] of angles.entries()) {
const x = radius * Math.cos(angle);
const y = radius * Math.sin(angle);
if (index === 0) {
polygon.path.moveTo(x, y);
} else {
polygon.path.lineTo(x, y);
}
}
polygon.path.closePath();
}
updatePolygonNode(visible) {
const { gridAngles, polygonNode: polygon, scale, shape, type, innerRadius, outerRadius } = this;
if (!visible || shape !== "polygon" || !scale || !gridAngles) {
polygon.visible = false;
return;
}
polygon.visible = true;
const padding2 = this.getPadding();
polygon.path.clear(true);
this.drawPolygon(outerRadius - padding2, gridAngles, polygon);
const reversedAngles = gridAngles.slice().reverse();
const innerPolygonRadius = type === "line" ? outerRadius - padding2 : innerRadius + padding2;
this.drawPolygon(innerPolygonRadius, reversedAngles, polygon);
this.setSectorNodeProps(polygon);
}
updateSectorNode(visible) {
const { axisInnerRadius, axisOuterRadius, scale, sectorNode: sector, shape, innerRadius, outerRadius } = this;
if (!visible || shape !== "circle" || !scale) {
sector.visible = false;
return;
}
sector.visible = true;
sector.startAngle = 0;
sector.endAngle = 2 * Math.PI;
const padding2 = this.getPadding();
const r0 = clamp(axisInnerRadius, innerRadius + padding2, axisOuterRadius);
const r1 = clamp(axisInnerRadius, outerRadius - padding2, axisOuterRadius);
sector.innerRadius = Math.min(r0, r1);
sector.outerRadius = Math.max(r0, r1);
this.setSectorNodeProps(sector);
}
updateLabelNode(visible) {
const { innerRadius, label, labelNode: node, scale, shape, type } = this;
if (!visible || label.enabled === false || !label.text || !scale) {
node.visible = false;
return;
}
const angle = normalizeAngle360FromDegrees((label.positionAngle ?? 0) - 90);
const isBottomSide = (isNumberEqual6(angle, 0) || angle > 0) && angle < Math.PI;
const rotation = isBottomSide ? angle - Math.PI / 2 : angle + Math.PI / 2;
let distance;
const angles = this.gridAngles ?? [];
if (type === "line") {
distance = innerRadius + label.padding;
} else if (shape === "circle" || angles.length < 3) {
distance = innerRadius - label.padding;
} else {
distance = innerRadius * Math.cos(Math.PI / angles.length) - label.padding;
}
const labelX = distance * Math.cos(angle);
const labelY = distance * Math.sin(angle);
let textBaseline;
if (type === "line") {
textBaseline = isBottomSide ? "top" : "bottom";
} else {
textBaseline = isBottomSide ? "bottom" : "top";
}
this.setLabelNodeProps(node, labelX, labelY, textBaseline, rotation);
}
getPadding() {
const { scale } = this;
if (!scale)
return 0;
const bandwidth = Math.abs(scale.bandwidth ?? 0);
const step = Math.abs(scale.step ?? 0);
return scale instanceof _ModuleSupport15.BandScale ? (step - bandwidth) / 2 : 0;
}
};
RadiusCrossLine.className = "RadiusCrossLine";
// packages/ag-charts-enterprise/src/axes/radius/radiusAxis.ts
var { Caption, Group: Group4, TransformableGroup, Path: Path4, Line: Line2, Selection: Selection2, generateTicks, AxisGroupZIndexMap } = _ModuleSupport16;
var RadiusAxisLabel = class extends _ModuleSupport16.AxisLabel {
constructor() {
super(...arguments);
this.autoRotateAngle = 335;
}
};
__decorateClass([
Property11
], RadiusAxisLabel.prototype, "autoRotate", 2);
__decorateClass([
Property11
], RadiusAxisLabel.prototype, "autoRotateAngle", 2);
var RadiusAxis = class extends _ModuleSupport16.PolarAxis {
constructor(moduleCtx, scale) {
super(moduleCtx, scale);
this.positionAngle = 0;
this.gridLineGroupSelection = Selection2.select(
this.gridLineGroup,
Line2,
false
);
this.generatedTicks = void 0;
this.headingLabelGroup = this.axisGroup.appendChild(
new TransformableGroup({ name: `${this.id}-Axis-heading` })
);
this.lineNodeGroup = this.axisGroup.appendChild(
new TransformableGroup({ name: `${this.id}-Axis-line` })
);
this.lineNode = this.lineNodeGroup.appendChild(
new Line2({
name: `${this.id}-Axis-line`,
zIndex: AxisGroupZIndexMap.AxisLine
})
);
this.gridPathGroup = this.gridGroup.appendChild(
new Group4({
name: `${this.id}-gridPaths`,
zIndex: ZIndexMap2.AXIS_GRID
})
);
this.gridPathSelection = Selection2.select(this.gridPathGroup, Path4);
this.headingLabelGroup.appendChild(this.title.caption.node);
this.cleanup.register(this.title.caption.registerInteraction(this.moduleCtx, "afterend"));
}
get direction() {
return ChartAxisDirection5.Radius;
}
getAxisTransform() {
const maxRadius = this.scale.range[0];
const { translation, positionAngle, innerRadiusRatio } = this;
const innerRadius = maxRadius * innerRadiusRatio;
const rotation = toRadians2(positionAngle);
return {
translationX: translation.x,
translationY: translation.y - maxRadius - innerRadius,
rotation,
rotationCenterX: 0,
rotationCenterY: maxRadius + innerRadius
};
}
update() {
super.update();
this.updateTitle();
this.updateGridLines();
const { enabled, stroke: stroke3, width } = this.line;
this.lineNode.setProperties({
stroke: stroke3,
strokeWidth: enabled ? width : 0,
x1: 0,
y1: this.range[0],
x2: 0,
y2: this.range[1]
});
}
updatePosition() {
super.updatePosition();
const axisTransform = this.getAxisTransform();
this.tickLineGroup.setProperties(axisTransform);
this.tickLabelGroup.setProperties(axisTransform);
this.lineNodeGroup.setProperties(axisTransform);
this.headingLabelGroup.setProperties(axisTransform);
}
calculateRotations() {
const rotation = 0;
const parallelFlipRotation = 0;
const regularFlipRotation = -Math.PI / 2;
return { rotation, parallelFlipRotation, regularFlipRotation };
}
calculateTickLayout(domain, niceMode, _visibleRange) {
const visibleRange = [0, 1];
const sideFlag = this.label.getSideFlag();
const labelX = sideFlag * (this.getTickSize() + this.label.spacing + this.seriesAreaPadding);
const { range: range2, reverse, defaultTickMinSpacing } = this;
const tickGenerationResult = generateTicks({
scale: this.scale,
label: this.label,
interval: this.interval,
tickFormatter: (...args) => this.tickFormatter(...args),
domain,
range: range2,
reverse,
niceMode,
visibleRange,
defaultTickMinSpacing,
labelOffset: labelX,
sideFlag,
axisRotation: 0,
sizeLimit: void 0,
primaryTickCount: void 0
});
const { tickData } = tickGenerationResult;
const { ticks, rawTicks, rawTickCount, tickDomain, fractionDigits, niceDomain = domain } = tickData;
const labels = ticks.map((d) => this.getTickLabelProps(d, tickGenerationResult));
this.generatedTicks = { ticks, labels };
return { ticks: rawTicks, tickDomain, niceDomain, rawTickCount, fractionDigits, timeInterval: void 0 };
}
updateSelections() {
const { generatedTicks } = this;
if (!generatedTicks)
return;
const { ticks, labels } = generatedTicks;
this.gridLineGroupSelection.update(this.gridLength ? ticks : []);
this.tickLabelGroupSelection.update(labels);
this.gridPathSelection.update(this.gridLine.enabled ? this.prepareGridPathTickData(ticks) : []);
this.gridLineGroupSelection.cleanup();
this.tickLabelGroupSelection.cleanup();
this.gridPathSelection.cleanup();
}
// TODO - abstract out
updateLabels() {
if (!this.label.enabled)
return;
const axisLabelPositionFn = _ModuleSupport16.resetAxisLabelSelectionFn();
this.tickLabelGroupSelection.each((node, datum) => {
node.fill = datum.color;
node.text = datum.text;
node.textBaseline = datum.textBaseline;
node.textAlign = datum.textAlign ?? "center";
node.setFont(datum);
node.setBoxing(datum);
node.setProperties(axisLabelPositionFn(node, datum));
});
}
updateGridLines() {
const {
gridLine: { style, width },
shape,
generatedTicks
} = this;
if (!style || !generatedTicks) {
return;
}
const styleCount = style.length;
const setStyle = (node, index) => {
const { stroke: stroke3, lineDash } = style[index % styleCount];
node.stroke = stroke3;
node.strokeWidth = width;
node.lineDash = lineDash;
node.fill = void 0;
};
const [startAngle, endAngle] = this.gridRange ?? [0, 2 * Math.PI];
const isFullCircle = isNumberEqual7(endAngle - startAngle, 2 * Math.PI);
const drawCircleShape = (node, value) => {
const { path } = node;
path.clear(true);
const radius = this.getTickRadius(value);
if (isFullCircle) {
path.moveTo(radius, 0);
path.arc(0, 0, radius, 0, 2 * Math.PI);
} else {
path.moveTo(radius * Math.cos(startAngle), radius * Math.sin(startAngle));
path.arc(0, 0, radius, normalizeAngle3603(startAngle), normalizeAngle3603(endAngle));
}
if (isFullCircle) {
path.closePath();
}
};
const drawPolygonShape = (node, value) => {
const { path } = node;
const angles = this.gridAngles;
path.clear(true);
if (!angles || angles.length < 3) {
return;
}
const radius = this.getTickRadius(value);
for (const [idx, angle] of angles.entries()) {
const x = radius * Math.cos(angle);
const y = radius * Math.sin(angle);
if (idx === 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
for (const [innerIdx, innerAngle] of angles.entries()) {
const x2 = radius * Math.cos(innerAngle);
const y2 = radius * Math.sin(innerAngle);
if (innerIdx === 0) {
path.moveTo(x2, y2);
} else {
path.lineTo(x2, y2);
}
}
path.closePath();
}
path.closePath();
};
const drawFn = shape === "circle" ? drawCircleShape : drawPolygonShape;
this.gridPathSelection.each((node, value, index) => {
setStyle(node, index);
drawFn(node, value);
});
}
updateTitle() {
const identityFormatter = (params) => params.defaultValue;
const { title, range: requestedRange } = this;
const { formatter = identityFormatter } = this.title;
title.caption.enabled = title.enabled;
title.caption.fontFamily = title.fontFamily;
title.caption.fontSize = title.fontSize;
title.caption.fontStyle = title.fontStyle;
title.caption.fontWeight = title.fontWeight;
title.caption.color = title.color;
title.caption.wrapping = title.wrapping;
let titleVisible = false;
const titleNode = title.caption.node;
if (title.enabled) {
titleVisible = true;
titleNode.rotation = Math.PI / 2;
titleNode.x = Math.floor((requestedRange[0] + requestedRange[1]) / 2);
titleNode.y = -Caption.SMALL_PADDING;
titleNode.textAlign = "center";
titleNode.textBaseline = "bottom";
titleNode.text = this.cachedCallWithContext(formatter, this.getTitleFormatterParams(this.scale.domain));
}
titleNode.visible = titleVisible;
}
updateCrossLines() {
for (const crossLine of this.crossLines) {
if (crossLine instanceof RadiusCrossLine) {
const { shape, gridAngles, range: range2, innerRadiusRatio } = this;
const radius = range2[0];
crossLine.shape = shape;
crossLine.gridAngles = gridAngles;
crossLine.axisOuterRadius = radius;
crossLine.axisInnerRadius = radius * innerRadiusRatio;
}
}
super.updateCrossLines();
}
createLabel() {
return new RadiusAxisLabel();
}
// TODO - abstract out (shared with cartesian axis)
getTickLabelProps(datum, tickGenerationResult) {
const { label } = this;
const { rotation, textBaseline, textAlign } = tickGenerationResult;
const range2 = this.scale.range;
const text2 = datum.tickLabel ?? "";
const sideFlag = label.getSideFlag();
const labelX = sideFlag * (this.getTickSize() + label.spacing + this.seriesAreaPadding);
const visible = text2 !== "" && text2 != null;
const combinedRotation = rotation;
return {
...this.getLabelStyles({ value: datum.tick, formattedValue: datum.tickLabel }),
tickId: datum.tickId,
rotation: combinedRotation,
text: text2,
textAlign,
textBaseline,
visible,
x: labelX,
y: datum.translation,
rotationCenterX: labelX,
rotationCenterY: datum.translation,
range: range2
};
}
};
RadiusAxis.CrossLineConstructor = RadiusCrossLine;
__decorateClass([
Property11
], RadiusAxis.prototype, "positionAngle", 2);
// packages/ag-charts-enterprise/src/axes/radius-category/radiusCategoryAxis.ts
var { CategoryScale: CategoryScale2 } = _ModuleSupport17;
var RadiusCategoryAxis = class extends RadiusAxis {
constructor(moduleCtx) {
super(moduleCtx, new CategoryScale2());
this.shape = "circle";
this.groupPaddingInner = 0;
this.paddingInner = 0;
this.paddingOuter = 0;
}
hasDefinedDomain() {
return false;
}
normaliseDataDomain(d) {
return { domain: d.domain, clipped: false };
}
prepareGridPathTickData(data) {
return data.slice().reverse();
}
getTickRadius(tickDatum) {
const { scale, innerRadiusRatio } = this;
const maxRadius = scale.range[0];
const minRadius = maxRadius * innerRadiusRatio;
if (CategoryScale2.is(scale)) {
const ticks = scale.domain;
const index = ticks.length - 1 - ticks.indexOf(tickDatum.tick);
return index === 0 ? minRadius : scale.inset + scale.step * (index - 0.5) + scale.bandwidth / 2;
} else {
const tickRange = (maxRadius - minRadius) / scale.domain.length;
return maxRadius - tickDatum.translation + minRadius - tickRange / 2;
}
}
tickFormatParams() {
return { type: "category" };
}
datumFormatParams(value, params) {
const { datum, seriesId, legendItemName, key, source, property, domain, boundSeries } = params;
return { type: "category", value, datum, seriesId, legendItemName, key, source, property, domain, boundSeries };
}
};
RadiusCategoryAxis.className = "RadiusCategoryAxis";
RadiusCategoryAxis.type = "radius-category";
__decorateClass([
Property12
], RadiusCategoryAxis.prototype, "groupPaddingInner", 2);
__decorateClass([
ProxyPropertyOnWrite2("scale", "paddingInner"),
Property12
], RadiusCategoryAxis.prototype, "paddingInner", 2);
__decorateClass([
ProxyPropertyOnWrite2("scale", "paddingOuter"),
Property12
], RadiusCategoryAxis.prototype, "paddingOuter", 2);
// packages/ag-charts-enterprise/src/axes/radius-category/radiusCategoryAxisModule.ts
var RadiusCategoryAxisModule = {
type: "axis",
name: "radius-category",
chartType: "polar",
enterprise: true,
version: VERSION4,
options: _ModuleSupport18.radiusCategoryAxisOptionsDefs,
themeTemplate: {
positionAngle: 0,
line: { enabled: false },
label: { minSpacing: 5 }
},
create: (ctx) => new RadiusCategoryAxis(ctx)
};
// packages/ag-charts-enterprise/src/axes/radius-number/radiusNumberAxisModule.ts
import { VERSION as VERSION5, _ModuleSupport as _ModuleSupport20 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/axes/radius-number/radiusNumberAxis.ts
import { _ModuleSupport as _ModuleSupport19 } from "ag-charts-community";
import { Property as Property13, normalisedExtentWithMetadata as normalisedExtentWithMetadata2 } from "ag-charts-core";
var { LinearScale: LinearScale2 } = _ModuleSupport19;
var RadiusNumberAxis = class extends RadiusAxis {
constructor(moduleCtx) {
super(moduleCtx, new LinearScale2());
this.shape = "polygon";
}
hasDefinedDomain() {
const { min, max } = this;
return min != null && max != null && min < max;
}
prepareGridPathTickData(data) {
const { scale } = this;
const domainTop = scale.domain[1];
return data.filter(({ tick }) => tick !== domainTop).sort((a, b) => b.tick - a.tick);
}
getTickRadius(tickDatum) {
const { scale } = this;
const maxRadius = scale.range[0];
const minRadius = maxRadius * this.innerRadiusRatio;
return maxRadius - tickDatum.translation + minRadius;
}
normaliseDataDomain(d) {
const { min, max, preferredMin, preferredMax } = this;
const { extent: extent4, clipped } = normalisedExtentWithMetadata2(
d.domain,
min,
max,
preferredMin,
preferredMax,
void 0,
d.sortMetadata?.sortOrder
);
return { domain: extent4, clipped };
}
getDomainExtentsNice() {
return [this.min == null && this.nice, this.max == null && this.nice];
}
tickFormatParams(_domain, _ticks, fractionDigits) {
return { type: "number", visibleDomain: void 0, fractionDigits };
}
datumFormatParams(value, params, fractionDigits) {
const { datum, seriesId, legendItemName, key, source, property, domain, boundSeries } = params;
return {
type: "number",
value,
datum,
seriesId,
legendItemName,
key,
source,
property,
domain,
boundSeries,
fractionDigits,
visibleDomain: void 0
};
}
};
RadiusNumberAxis.className = "RadiusNumberAxis";
RadiusNumberAxis.type = "radius-number";
__decorateClass([
Property13
], RadiusNumberAxis.prototype, "min", 2);
__decorateClass([
Property13
], RadiusNumberAxis.prototype, "max", 2);
__decorateClass([
Property13
], RadiusNumberAxis.prototype, "preferredMin", 2);
__decorateClass([
Property13
], RadiusNumberAxis.prototype, "preferredMax", 2);
// packages/ag-charts-enterprise/src/axes/radius-number/radiusNumberAxisModule.ts
var RadiusNumberAxisModule = {
type: "axis",
name: "radius-number",
chartType: "polar",
enterprise: true,
version: VERSION5,
options: _ModuleSupport20.radiusNumberAxisOptionsDefs,
themeTemplate: {
positionAngle: 0,
line: { enabled: false },
shape: { $findFirstSiblingNotOperation: void 0 },
label: { minSpacing: 5 }
},
create: (ctx) => new RadiusNumberAxis(ctx)
};
// packages/ag-charts-enterprise/src/features/animation/animationModule.ts
import { VERSION as VERSION6 } from "ag-charts-community";
import { boolean, positiveNumber, undocumented } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/animation/animation.ts
import "ag-charts-community";
import { AbstractModuleInstance, ObserveChanges as ObserveChanges2, Property as Property14 } from "ag-charts-core";
var Animation = class extends AbstractModuleInstance {
constructor(ctx) {
super();
this.ctx = ctx;
this.enabled = true;
ctx.animationManager.skip(false);
this.cleanup.register(() => ctx.animationManager.skip(true));
}
};
__decorateClass([
ObserveChanges2((target, newValue) => {
target.ctx.animationManager.skip(!newValue);
}),
Property14
], Animation.prototype, "enabled", 2);
__decorateClass([
ObserveChanges2((target, newValue) => {
if (newValue != null) {
target.ctx.animationManager.defaultDuration = newValue;
}
}),
Property14
], Animation.prototype, "duration", 2);
__decorateClass([
ObserveChanges2((target, newValue) => {
target.ctx.animationManager.maxAnimatableItems = newValue ?? Infinity;
}),
Property14
], Animation.prototype, "maxAnimatableItems", 2);
// packages/ag-charts-enterprise/src/features/animation/animationModule.ts
var AnimationModule = {
type: "plugin",
name: "animation",
enterprise: true,
version: VERSION6,
options: {
enabled: boolean,
duration: positiveNumber
},
themeTemplate: {
enabled: true
},
create: (ctx) => new Animation(ctx)
};
AnimationModule.options.maxAnimatableItems = undocumented(positiveNumber);
// packages/ag-charts-enterprise/src/features/annotations/annotationsModule.ts
import { VERSION as VERSION7, _ModuleSupport as _ModuleSupport65 } from "ag-charts-community";
import "ag-charts-core";
// packages/ag-charts-enterprise/src/features/shared-toolbar/sharedToolbar.ts
import { _ModuleSupport as _ModuleSupport22 } from "ag-charts-community";
import { AbstractModuleInstance as AbstractModuleInstance2 } from "ag-charts-core";
var _SharedToolbar = class _SharedToolbar extends AbstractModuleInstance2 {
constructor(ctx) {
super();
this.ctx = ctx;
this.activeSections = /* @__PURE__ */ new Set();
this.sectionButtons = {
annotations: [],
chartToolbar: []
};
this.container = this.ctx.domManager.addChild("canvas-overlay", "shared-toolbar");
this.container.role = "presentation";
}
getSharedToolbar(section) {
if (!this.sharedToolbar) {
this.createSharedToolbar();
}
if (section === "chartToolbar" && this.sharedToolbar) {
this.sharedToolbar.setAriaLabelId("ariaLabelFinancialCharts");
}
return this.toolbarWithSection(section);
}
createSharedToolbar() {
this.sharedToolbar = new _ModuleSupport22.Toolbar(this.ctx, "ariaLabelAnnotationsToolbar", "vertical");
this.sharedToolbar.addClass("ag-charts-shared-toolbar");
this.container.append(this.sharedToolbar.getElement());
this.cleanup.register(() => {
if (!this.sharedToolbar)
return;
this.sharedToolbar.getElement().remove();
this.sharedToolbar.destroy();
this.sharedToolbar = void 0;
});
}
toolbarWithSection(section) {
const sharedToolbar = this.sharedToolbar;
const withSection = {
layout: (layoutBox, padding2) => {
if (this.firstLayoutSection != null && this.firstLayoutSection !== section && this.activeSections.has(this.firstLayoutSection)) {
return;
}
this.firstLayoutSection = section;
const width = sharedToolbar.getBounds().width;
sharedToolbar.setBounds({
x: layoutBox.x,
y: layoutBox.y,
width
});
layoutBox.shrink({ left: width + sharedToolbar.horizontalSpacing + (padding2 ?? 0) });
},
addToolbarListener: (eventType, handler) => {
return sharedToolbar.addToolbarListener(eventType, (sharedEvent) => {
const sectionIndex = this.getSectionIndex(section, sharedEvent.button.index);
if (sectionIndex < 0)
return;
const event = {
...sharedEvent,
button: this.sectionButtons[section][sectionIndex]
};
handler(event);
});
},
updateButtons: (buttons) => {
this.sectionButtons[section] = buttons;
const sharedButtons = _SharedToolbar.SECTION_ORDER.flatMap((order) => this.sectionButtons[order]);
sharedToolbar.updateButtons(sharedButtons);
},
updateButtonByIndex: (index, button) => {
sharedToolbar.updateButtonByIndex(this.getIndex(section, index), button);
},
toggleActiveButtonByIndex: (index) => {
sharedToolbar.toggleActiveButtonByIndex(this.getIndex(section, index));
},
toggleButtonEnabledByIndex: (index, enabled) => {
sharedToolbar.toggleButtonEnabledByIndex(this.getIndex(section, index), enabled);
},
setHidden: (hidden) => {
if (hidden) {
this.activeSections.delete(section);
} else {
this.activeSections.add(section);
}
let sum = 0;
for (const order of _SharedToolbar.SECTION_ORDER) {
if (order !== section) {
sum += this.sectionButtons[order].length;
continue;
}
for (const index of this.sectionButtons[section].keys()) {
sharedToolbar.setButtonHiddenByIndex(sum + index, hidden);
}
}
},
destroy: () => {
withSection.setHidden(true);
if (this.activeSections.size === 0) {
this.destroy();
}
},
clearActiveButton: sharedToolbar.clearActiveButton.bind(sharedToolbar),
addListener: sharedToolbar.addListener.bind(sharedToolbar),
removeListener: sharedToolbar.removeListener.bind(sharedToolbar)
};
withSection.setHidden(false);
return withSection;
}
getIndex(section, index) {
let sum = 0;
for (const order of _SharedToolbar.SECTION_ORDER) {
if (order === section)
return sum + index;
sum += this.sectionButtons[order].length;
}
return -1;
}
getSectionIndex(section, index) {
let sum = 0;
for (const order of _SharedToolbar.SECTION_ORDER) {
if (order === section) {
if (index >= sum + this.sectionButtons[section].length)
return -1;
return index - sum;
}
sum += this.sectionButtons[order].length;
}
return -1;
}
};
_SharedToolbar.SECTION_ORDER = ["chartToolbar", "annotations"];
var SharedToolbar = _SharedToolbar;
// packages/ag-charts-enterprise/src/features/annotations/annotations.ts
import {
_ModuleSupport as _ModuleSupport64
} from "ag-charts-community";
import {
AbstractModuleInstance as AbstractModuleInstance4,
ChartAxisDirection as ChartAxisDirection9,
ChartUpdateType as ChartUpdateType3,
ObserveChanges as ObserveChanges3,
PropertiesArray as PropertiesArray3,
Property as Property37,
Vec2 as Vec219,
isValidDate
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/text-input/textInput.ts
import { _ModuleSupport as _ModuleSupport23 } from "ag-charts-community";
import { CleanupRegistry, attachListener, ceilTo, focusCursorAtEnd, setAttributes } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/text-input/textInputTemplate.html
var textInputTemplate_default = '<div contenteditable="plaintext-only" class="ag-charts-text-input__textarea" tabindex="0"></div>';
// packages/ag-charts-enterprise/src/features/text-input/textInput.ts
var moduleId = "text-input";
var canvasOverlay = "canvas-overlay";
var TextInput = class {
constructor(ctx) {
this.ctx = ctx;
this.cleanup = new CleanupRegistry();
this.layout = {
getTextInputCoords: () => ({ x: 0, y: 0 }),
getTextPosition: () => "center",
alignment: "center",
textAlign: "center"
};
this.visible = false;
this.element = ctx.domManager.addChild(canvasOverlay, moduleId);
this.element.classList.add("ag-charts-text-input");
this.cleanup.register(() => ctx.domManager.removeChild(canvasOverlay, moduleId));
}
setKeyDownHandler(handler) {
this.cleanup.register(attachListener(this.element, "keydown", handler));
}
show(opts) {
this.element.innerHTML = textInputTemplate_default;
const textArea = this.element.firstElementChild;
setAttributes(textArea, {
role: "textbox",
// AG-15233
"data-preventdefault": false
// AG-13715
});
if (!textArea.isContentEditable) {
textArea.contentEditable = "true";
}
textArea.setAttribute(
"placeholder",
this.ctx.localeManager.t(opts.placeholderText ?? "inputTextareaPlaceholder")
);
if (opts.styles?.placeholderColor) {
textArea.style.setProperty("--placeholder-text-color", opts.styles?.placeholderColor);
}
textArea.innerText = opts.text ?? "";
textArea.style.color = opts.styles?.color ?? "inherit";
textArea.style.fontFamily = opts.styles?.fontFamily ?? "inherit";
textArea.style.fontSize = opts.styles?.fontSize ? `${opts.styles.fontSize}px` : "inherit";
textArea.style.fontStyle = opts.styles?.fontStyle ?? "inherit";
textArea.style.fontWeight = typeof opts.styles?.fontWeight === "number" ? `${opts.styles.fontWeight}` : opts.styles?.fontWeight ?? "inherit";
focusCursorAtEnd(textArea);
textArea.addEventListener("input", () => {
this.updatePosition();
opts.onChange?.(this.getValue(), this.getBBox());
});
textArea.addEventListener("click", (event) => {
event.stopPropagation();
});
if (opts.layout) {
this.layout = opts.layout;
this.updatePosition();
}
opts.onChange?.(this.getValue(), this.getBBox());
this.visible = true;
}
hide() {
this.element.innerHTML = "";
this.layout = {
getTextInputCoords: () => ({ x: 0, y: 0 }),
getTextPosition: () => "center",
alignment: "center",
textAlign: "center"
};
this.visible = false;
}
isVisible() {
return this.visible;
}
updateColor(color7) {
if (!this.element.firstElementChild)
return;
this.element.firstElementChild.style.color = color7;
}
updateFontSize(fontSize) {
if (!this.element.firstElementChild)
return;
this.element.firstElementChild.style.fontSize = `${fontSize}px`;
this.updatePosition();
return this.getBBox();
}
getValue() {
if (!this.element.firstElementChild)
return;
return this.element.firstElementChild.innerText.trim();
}
updatePosition() {
const { element } = this;
const textArea = element.firstElementChild;
if (!textArea)
return;
const sceneRect = this.ctx.domManager.getBoundingClientRect();
const { width, getTextInputCoords, getTextPosition, alignment, textAlign } = this.layout;
element.style.setProperty("width", width ? `${width}px` : "unset");
const textRect = textArea.getBoundingClientRect();
const point = getTextInputCoords(textRect.height);
let horizontalPosition = point.x;
if (alignment === "center") {
horizontalPosition -= (width ?? textRect.width) / 2;
} else if (alignment === "right") {
horizontalPosition -= width ?? textRect.width;
}
const position = getTextPosition();
let verticalPosition = point.y;
if (position === "center") {
verticalPosition -= textRect.height / 2;
} else if (position === "bottom") {
verticalPosition -= textRect.height;
}
element.style.setProperty("top", `${verticalPosition}px`);
element.style.setProperty("left", `${horizontalPosition}px`);
element.style.setProperty("max-width", `${sceneRect.width - horizontalPosition}px`);
element.style.setProperty("text-align", alignment);
textArea.style.setProperty("text-align", textAlign);
}
getBBox() {
const { left, top, width, height } = this.element.getBoundingClientRect();
return new _ModuleSupport23.BBox(left, top, ceilTo(width, 2), height);
}
destroy() {
this.cleanup.flush();
}
};
// packages/ag-charts-enterprise/src/features/annotations/annotationAxesButtons.ts
import { BaseProperties as BaseProperties3, Property as Property15 } from "ag-charts-core";
var AxesButtons = class extends BaseProperties3 {
constructor() {
super(...arguments);
this.enabled = false;
this.axes = "y";
}
};
__decorateClass([
Property15
], AxesButtons.prototype, "enabled", 2);
__decorateClass([
Property15
], AxesButtons.prototype, "axes", 2);
// packages/ag-charts-enterprise/src/features/annotations/annotationDefaults.ts
import "ag-charts-community";
import { deepClone } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/annotationTypes.ts
var AnnotationType = /* @__PURE__ */ ((AnnotationType2) => {
AnnotationType2["Line"] = "line";
AnnotationType2["HorizontalLine"] = "horizontal-line";
AnnotationType2["VerticalLine"] = "vertical-line";
AnnotationType2["DisjointChannel"] = "disjoint-channel";
AnnotationType2["ParallelChannel"] = "parallel-channel";
AnnotationType2["FibonacciRetracement"] = "fibonacci-retracement";
AnnotationType2["FibonacciRetracementTrendBased"] = "fibonacci-retracement-trend-based";
AnnotationType2["Callout"] = "callout";
AnnotationType2["Comment"] = "comment";
AnnotationType2["Note"] = "note";
AnnotationType2["Text"] = "text";
AnnotationType2["Arrow"] = "arrow";
AnnotationType2["ArrowUp"] = "arrow-up";
AnnotationType2["ArrowDown"] = "arrow-down";
AnnotationType2["DateRange"] = "date-range";
AnnotationType2["PriceRange"] = "price-range";
AnnotationType2["DatePriceRange"] = "date-price-range";
AnnotationType2["QuickDatePriceRange"] = "quick-date-price-range";
return AnnotationType2;
})(AnnotationType || {});
var ANNOTATION_TYPES = Object.values(AnnotationType);
function stringToAnnotationType(value) {
for (const t of ANNOTATION_TYPES) {
if (t === value)
return t;
}
}
// packages/ag-charts-enterprise/src/features/annotations/utils/has.ts
import { isObject as isObject12 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/callout/calloutProperties.ts
import { Color, Property as Property18, isObject } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/annotationProperties.ts
import "ag-charts-community";
import { BaseProperties as BaseProperties4, FONT_SIZE, Property as Property16, generateUUID } from "ag-charts-core";
var PointProperties = class extends BaseProperties4 {
};
__decorateClass([
Property16
], PointProperties.prototype, "x", 2);
__decorateClass([
Property16
], PointProperties.prototype, "y", 2);
var ChannelAnnotationMiddleProperties = class extends Stroke(LineStyle(Visible(BaseProperties4))) {
};
var AxisLabelProperties = class extends Stroke(LineStyle(Fill(Label(Font(BaseProperties4))))) {
constructor() {
super(...arguments);
this.cornerRadius = 2;
}
};
__decorateClass([
Property16
], AxisLabelProperties.prototype, "enabled", 2);
__decorateClass([
Property16
], AxisLabelProperties.prototype, "cornerRadius", 2);
var BackgroundProperties = class extends Fill(BaseProperties4) {
};
var HandleProperties = class extends Stroke(LineStyle(Fill(BaseProperties4))) {
};
var LineTextProperties = class extends Font(BaseProperties4) {
constructor() {
super(...arguments);
this.label = "";
this.position = "top";
this.alignment = "left";
}
};
__decorateClass([
Property16
], LineTextProperties.prototype, "label", 2);
__decorateClass([
Property16
], LineTextProperties.prototype, "position", 2);
__decorateClass([
Property16
], LineTextProperties.prototype, "alignment", 2);
var LabelTextProperties = class extends Font(BaseProperties4) {
};
var ChannelTextProperties = class extends Font(BaseProperties4) {
constructor() {
super(...arguments);
this.label = "";
}
};
__decorateClass([
Property16
], ChannelTextProperties.prototype, "label", 2);
__decorateClass([
Property16
], ChannelTextProperties.prototype, "position", 2);
__decorateClass([
Property16
], ChannelTextProperties.prototype, "alignment", 2);
function Annotation(Parent) {
class AnnotationInternal extends Writeable(Visible(Parent)) {
constructor() {
super(...arguments);
// A uuid is required, over the usual incrementing index, as annotations can be restored from external databases
this.id = generateUUID();
}
}
return AnnotationInternal;
}
function Line3(Parent) {
class LineInternal extends Parent {
constructor() {
super(...arguments);
this.start = new PointProperties();
this.end = new PointProperties();
}
}
__decorateClass([
Property16
], LineInternal.prototype, "start", 2);
__decorateClass([
Property16
], LineInternal.prototype, "end", 2);
return LineInternal;
}
function Point(Parent) {
class PointInternal extends Parent {
}
__decorateClass([
Property16
], PointInternal.prototype, "x", 2);
__decorateClass([
Property16
], PointInternal.prototype, "y", 2);
return PointInternal;
}
function Value(Parent) {
class ValueInternal extends Parent {
}
__decorateClass([
Property16
], ValueInternal.prototype, "value", 2);
return ValueInternal;
}
function Background2(Parent) {
class BackgroundInternal extends Parent {
constructor() {
super(...arguments);
this.background = new BackgroundProperties();
}
}
__decorateClass([
Property16
], BackgroundInternal.prototype, "background", 2);
return BackgroundInternal;
}
function Handle(Parent) {
class HandleInternal extends Parent {
constructor() {
super(...arguments);
this.handle = new HandleProperties();
}
}
__decorateClass([
Property16
], HandleInternal.prototype, "handle", 2);
return HandleInternal;
}
function AxisLabel(Parent) {
class AxisLabelInternal extends Parent {
constructor() {
super(...arguments);
this.axisLabel = new AxisLabelProperties();
}
}
__decorateClass([
Property16
], AxisLabelInternal.prototype, "axisLabel", 2);
return AxisLabelInternal;
}
function Label(Parent) {
class LabelInternal extends Parent {
constructor() {
super(...arguments);
this.padding = void 0;
this.textAlign = "center";
this.formatter = void 0;
}
// TODO: making this generic causes issues with mixins sequence
}
__decorateClass([
Property16
], LabelInternal.prototype, "padding", 2);
__decorateClass([
Property16
], LabelInternal.prototype, "textAlign", 2);
__decorateClass([
Property16
], LabelInternal.prototype, "formatter", 2);
return LabelInternal;
}
function Cappable(Parent) {
class CappableInternal extends Parent {
}
return CappableInternal;
}
function Extendable(Parent) {
class ExtendableInternal extends Parent {
}
__decorateClass([
Property16
], ExtendableInternal.prototype, "extendStart", 2);
__decorateClass([
Property16
], ExtendableInternal.prototype, "extendEnd", 2);
return ExtendableInternal;
}
function Writeable(Parent) {
class WriteableInternal extends Parent {
isWriteable() {
return !this.locked && !this.readOnly;
}
isHoverable() {
return !this.readOnly;
}
}
__decorateClass([
Property16
], WriteableInternal.prototype, "locked", 2);
__decorateClass([
Property16
], WriteableInternal.prototype, "readOnly", 2);
return WriteableInternal;
}
function Localisable(Parent) {
class LocalisableInternal extends Parent {
setLocaleManager(localeManager) {
this.localeManager ?? (this.localeManager = localeManager);
}
}
return LocalisableInternal;
}
function Visible(Parent) {
class VisibleInternal extends Parent {
}
__decorateClass([
Property16
], VisibleInternal.prototype, "visible", 2);
return VisibleInternal;
}
function Fill(Parent) {
class FillInternal extends Parent {
}
__decorateClass([
Property16
], FillInternal.prototype, "fill", 2);
__decorateClass([
Property16
], FillInternal.prototype, "fillOpacity", 2);
return FillInternal;
}
function Stroke(Parent) {
class StrokeInternal extends Parent {
}
__decorateClass([
Property16
], StrokeInternal.prototype, "stroke", 2);
__decorateClass([
Property16
], StrokeInternal.prototype, "strokeOpacity", 2);
__decorateClass([
Property16
], StrokeInternal.prototype, "strokeWidth", 2);
return StrokeInternal;
}
function LineStyle(Parent) {
class LineDashInternal extends Parent {
constructor() {
super(...arguments);
this.lineCap = void 0;
this.computedLineDash = void 0;
}
}
__decorateClass([
Property16
], LineDashInternal.prototype, "lineDash", 2);
__decorateClass([
Property16
], LineDashInternal.prototype, "lineDashOffset", 2);
__decorateClass([
Property16
], LineDashInternal.prototype, "lineStyle", 2);
return LineDashInternal;
}
function Font(Parent) {
class FontInternal extends Parent {
constructor() {
super(...arguments);
this.fontSize = FONT_SIZE.SMALL;
this.fontFamily = "Verdana, sans-serif";
}
}
__decorateClass([
Property16
], FontInternal.prototype, "fontStyle", 2);
__decorateClass([
Property16
], FontInternal.prototype, "fontWeight", 2);
__decorateClass([
Property16
], FontInternal.prototype, "fontSize", 2);
__decorateClass([
Property16
], FontInternal.prototype, "fontFamily", 2);
__decorateClass([
Property16
], FontInternal.prototype, "color", 2);
return FontInternal;
}
// packages/ag-charts-enterprise/src/features/annotations/properties/textualStartEndProperties.ts
import { Property as Property17 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/utils/scale.ts
import { isDate, isNumber, isString } from "ag-charts-core";
function getGrouping(d) {
if (isNumber(d) || isString(d) || isDate(d)) {
return { value: d, groupPercentage: 0 };
}
return d ?? { value: void 0, groupPercentage: 0 };
}
function getGroupingValue(d) {
return getGrouping(d)?.value;
}
// packages/ag-charts-enterprise/src/features/annotations/utils/values.ts
function convertLine(datum, context) {
if (datum.start == null || datum.end == null)
return;
const start = convertPoint(datum.start, context);
const end = convertPoint(datum.end, context);
if (start == null || end == null)
return;
return { x1: start.x, y1: start.y, x2: end.x, y2: end.y };
}
function convertPoint(point, context) {
const x = convert(point.x, context.xAxis);
const y = convert(point.y, context.yAxis);
return { x, y };
}
function convert(p, context) {
if (p == null)
return 0;
const { value, groupPercentage } = getGrouping(p);
const { scale, snapToGroup } = context;
const width = scale.bandwidth === 0 ? scale.step ?? 0 : scale.bandwidth ?? 0;
const offset = snapToGroup ? width / 2 : width * groupPercentage;
return scale.convert(value) + offset;
}
function invertCoords(coords, context) {
const x = invert(coords.x, context.xAxis);
const y = invert(coords.y, context.yAxis);
return { x, y };
}
function invert(n, context) {
const { scale } = context;
if (context.continuous && scale.step == null) {
return context.scaleInvert(n);
}
const value = context.scaleInvertNearest(n);
const width = scale.bandwidth === 0 ? scale.step : scale.bandwidth ?? 0;
const bandStart = scale.convert(value);
const bandEnd = bandStart + width;
const groupPercentage = bandStart === bandEnd ? 0 : (n - bandStart) / (bandEnd - bandStart);
return { value, groupPercentage };
}
// packages/ag-charts-enterprise/src/features/annotations/properties/startEndProperties.ts
import { BaseProperties as BaseProperties5 } from "ag-charts-core";
var StartEndProperties = class extends Annotation(Line3(Handle(BaseProperties5))) {
constructor() {
super(...arguments);
this.snapToAngle = 45;
}
getDefaultColor(_colorPickerType) {
return void 0;
}
getDefaultOpacity(_colorPickerType) {
return void 0;
}
};
// packages/ag-charts-enterprise/src/features/annotations/properties/textualStartEndProperties.ts
var TextualStartEndProperties = class extends Localisable(Label(Font(StartEndProperties))) {
constructor() {
super(...arguments);
this.text = "";
this.position = "top";
this.alignment = "left";
this.placement = "inside";
this.placeholderText = "inputTextareaPlaceholder";
}
getDefaultColor(_colorPickerType) {
return this.color;
}
getDefaultOpacity(_colorPickerType) {
return void 0;
}
getPlaceholderColor() {
return void 0;
}
getPadding() {
const { padding: padding2 = 0 } = this;
return {
top: padding2,
right: padding2,
bottom: padding2,
left: padding2
};
}
getText() {
const isPlaceholder = this.text.length == 0;
let text2 = this.text;
if (isPlaceholder) {
text2 = this.placeholderText ?? "";
if (this.localeManager)
text2 = this.localeManager.t(text2);
}
return {
text: text2,
isPlaceholder
};
}
getTextInputCoords(context, _height) {
return convertPoint(this.end, context);
}
getTextPosition() {
return this.position;
}
};
__decorateClass([
Property17
], TextualStartEndProperties.prototype, "text", 2);
// packages/ag-charts-enterprise/src/features/annotations/callout/calloutProperties.ts
var DEFAULT_CALLOUT_PADDING = {
top: 6,
right: 12,
bottom: 9,
left: 12
};
var CalloutProperties = class extends Fill(Stroke(TextualStartEndProperties)) {
constructor() {
super(...arguments);
this.type = "callout" /* Callout */;
this.position = "bottom";
this.alignment = "left";
}
static is(value) {
return isObject(value) && value.type === "callout" /* Callout */;
}
getDefaultColor(colorPickerType) {
switch (colorPickerType) {
case `fill-color`:
return this.fill;
case `line-color`:
return this.stroke;
case `text-color`:
default:
return this.color;
}
}
getDefaultOpacity(colorPickerType) {
switch (colorPickerType) {
case `fill-color`:
return this.fillOpacity;
case `line-color`:
return this.strokeOpacity;
case `text-color`:
default:
return void 0;
}
}
getPlaceholderColor() {
const { r, g, b } = Color.fromString(this.color ?? "#888888");
return new Color(r, g, b, 0.66).toString();
}
getPadding() {
const { padding: padding2 } = this;
if (padding2 == null) {
return { ...DEFAULT_CALLOUT_PADDING };
}
return {
top: padding2,
right: padding2,
bottom: padding2,
left: padding2
};
}
getTextInputCoords(context, height) {
const coords = super.getTextInputCoords(context, height);
const padding2 = this.getPadding();
const paddingLeft = padding2.left ?? 0;
const paddingBottom = padding2.bottom ?? 0;
return {
x: coords.x + paddingLeft,
y: coords.y - paddingBottom
};
}
};
__decorateClass([
Property18
], CalloutProperties.prototype, "type", 2);
// packages/ag-charts-enterprise/src/features/annotations/comment/commentProperties.ts
import { Color as Color2, Property as Property20, isObject as isObject2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/properties/textualPointProperties.ts
import { BaseProperties as BaseProperties6, Property as Property19 } from "ag-charts-core";
var TextualPointProperties = class extends Annotation(Point(Handle(Label(Font(BaseProperties6))))) {
constructor() {
super(...arguments);
this.text = "";
this.position = "top";
this.alignment = "left";
this.placement = "inside";
this.placeholderText = "inputTextareaPlaceholder";
}
getDefaultColor(_colorPickerType) {
return this.color;
}
getDefaultOpacity(_colorPickerType) {
return void 0;
}
getPlaceholderColor() {
return void 0;
}
getPadding() {
const { padding: padding2 = 0 } = this;
return {
top: padding2,
right: padding2,
bottom: padding2,
left: padding2
};
}
getText() {
const isPlaceholder = this.text.length == 0;
const text2 = isPlaceholder ? this.placeholderText ?? "" : this.text;
return {
text: text2,
isPlaceholder
};
}
getTextInputCoords(context, _height) {
return convertPoint(this, context);
}
getTextPosition() {
return this.position;
}
};
__decorateClass([
Property19
], TextualPointProperties.prototype, "text", 2);
// packages/ag-charts-enterprise/src/features/annotations/comment/commentProperties.ts
var DEFAULT_COMMENT_PADDING = {
top: 8,
right: 14,
bottom: 8,
left: 14
};
var CommentProperties = class extends Fill(Stroke(TextualPointProperties)) {
constructor() {
super(...arguments);
this.type = "comment" /* Comment */;
this.position = "bottom";
this.alignment = "left";
}
static is(value) {
return isObject2(value) && value.type === "comment" /* Comment */;
}
getDefaultColor(colorPickerType) {
switch (colorPickerType) {
case `fill-color`:
return this.fill;
case `line-color`:
return this.stroke;
case `text-color`:
default:
return this.color;
}
}
getDefaultOpacity(colorPickerType) {
switch (colorPickerType) {
case `fill-color`:
return this.fillOpacity;
case `line-color`:
return this.strokeOpacity;
case `text-color`:
default:
return void 0;
}
}
getPlaceholderColor() {
const { r, g, b } = Color2.fromString(this.color ?? "#888888");
return new Color2(r, g, b, 0.66).toString();
}
getPadding() {
const { padding: padding2, fontSize } = this;
if (padding2 == null) {
return {
top: Math.max(fontSize * 0.4, DEFAULT_COMMENT_PADDING.top),
bottom: Math.max(fontSize * 0.4, DEFAULT_COMMENT_PADDING.bottom),
left: Math.max(fontSize * 0.8, DEFAULT_COMMENT_PADDING.left),
right: Math.max(fontSize * 0.8, DEFAULT_COMMENT_PADDING.right)
};
}
return {
top: padding2,
right: padding2,
bottom: padding2,
left: padding2
};
}
getTextInputCoords(context, height) {
const coords = super.getTextInputCoords(context, height);
const padding2 = this.getPadding();
return {
x: coords.x + padding2.left,
y: coords.y - padding2.bottom
};
}
};
__decorateClass([
Property20
], CommentProperties.prototype, "type", 2);
// packages/ag-charts-enterprise/src/features/annotations/measurer/measurerProperties.ts
import "ag-charts-community";
import { BaseProperties as BaseProperties7, Property as Property21, isObject as isObject3 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/utils/line.ts
import { Vec2 } from "ag-charts-core";
function getLineStyle(lineDash, lineStyle) {
return lineDash ? "dashed" : lineStyle ?? "solid";
}
function getComputedLineDash(strokeWidth, styleType) {
switch (styleType) {
case "solid":
return [];
case "dashed":
return [strokeWidth * 4, strokeWidth * 2];
case "dotted":
return [0, strokeWidth * 2];
}
}
function getLineDash(lineDash, computedLineDash, lineStyle, strokeWidth) {
const styleType = getLineStyle(lineDash, lineStyle);
return computedLineDash ?? lineDash ?? getComputedLineDash(strokeWidth ?? 1, styleType);
}
function getLineCap(lineCap, lineDash, lineStyle) {
const styleType = getLineStyle(lineDash, lineStyle);
return lineCap ?? styleType === "dotted" ? "round" : void 0;
}
function boundsIntersections(coords, bounds) {
const [p1, p2] = Vec2.from(coords);
const reflection = bounds.height;
const gradient = Vec2.gradient(p2, p1, reflection);
const intercept = Vec2.intercept(p2, gradient, reflection);
const fallback = [
{ x: p1.x, y: reflection ?? 0 },
{ x: p1.x, y: reflection == null ? bounds.height : reflection - bounds.height }
];
if (gradient === Infinity) {
return fallback;
}
let points = [
Vec2.intersectAtY(gradient, intercept, 0, reflection),
Vec2.intersectAtY(gradient, intercept, bounds.height, reflection),
Vec2.intersectAtX(gradient, intercept, 0, reflection),
Vec2.intersectAtX(gradient, intercept, bounds.width, reflection)
];
points = points.filter((p) => p.x >= bounds.x && p.x <= bounds.width && p.y >= bounds.y && p.y <= bounds.height).sort((a, b) => {
if (a.x === b.x)
return 0;
return a.x < b.x ? -1 : 1;
});
if (points.length !== 2) {
return fallback;
}
return points;
}
// packages/ag-charts-enterprise/src/features/annotations/measurer/measurerProperties.ts
var MeasurerStatisticsDivider = class extends Stroke(BaseProperties7) {
};
var MeasurerStatistics = class extends Font(Fill(Stroke(BaseProperties7))) {
constructor() {
super(...arguments);
this.divider = new MeasurerStatisticsDivider();
}
};
__decorateClass([
Property21
], MeasurerStatistics.prototype, "divider", 2);
var MeasurerDirectionProperties = class extends Fill(Stroke(Handle(BaseProperties7))) {
constructor() {
super(...arguments);
this.statistics = new MeasurerStatistics();
}
};
__decorateClass([
Property21
], MeasurerDirectionProperties.prototype, "statistics", 2);
var MeasurerTypeProperties = class extends Localisable(Background2(Stroke(LineStyle(StartEndProperties)))) {
constructor() {
super(...arguments);
this.direction = "both";
this.hasDateRange = false;
this.hasPriceRange = false;
this.statistics = new MeasurerStatistics();
this.getVolume = () => void 0;
this.text = new LineTextProperties();
}
getDefaultColor(colorPickerType) {
switch (colorPickerType) {
case `fill-color`:
return this.background.fill;
case `line-color`:
return this.stroke;
case `text-color`:
return this.text.color;
}
}
getDefaultOpacity(colorPickerType) {
switch (colorPickerType) {
case `fill-color`:
return this.background.fillOpacity;
case `line-color`:
return this.strokeOpacity;
}
}
getLineDash() {
return getLineDash(this.lineDash, this.computedLineDash, this.lineStyle, this.strokeWidth);
}
getLineCap() {
return getLineCap(this.lineCap, this.lineDash, this.lineStyle);
}
};
__decorateClass([
Property21
], MeasurerTypeProperties.prototype, "statistics", 2);
__decorateClass([
Property21
], MeasurerTypeProperties.prototype, "text", 2);
function DateRange(Parent) {
class DateRangeInternal extends Parent {
constructor() {
super(...arguments);
this.hasDateRange = true;
}
}
return DateRangeInternal;
}
function PriceRange(Parent) {
class PriceRangeInternal extends Parent {
constructor() {
super(...arguments);
this.hasPriceRange = true;
}
}
return PriceRangeInternal;
}
var DateRangeProperties = class extends DateRange(MeasurerTypeProperties) {
constructor() {
super(...arguments);
this.type = "date-range" /* DateRange */;
this.direction = "horizontal";
}
static is(value) {
return isObject3(value) && value.type === "date-range" /* DateRange */;
}
};
__decorateClass([
Property21
], DateRangeProperties.prototype, "type", 2);
__decorateClass([
Property21
], DateRangeProperties.prototype, "extendAbove", 2);
__decorateClass([
Property21
], DateRangeProperties.prototype, "extendBelow", 2);
var PriceRangeProperties = class extends PriceRange(MeasurerTypeProperties) {
constructor() {
super(...arguments);
this.type = "price-range" /* PriceRange */;
this.direction = "vertical";
}
static is(value) {
return isObject3(value) && value.type === "price-range" /* PriceRange */;
}
};
__decorateClass([
Property21
], PriceRangeProperties.prototype, "type", 2);
__decorateClass([
Property21
], PriceRangeProperties.prototype, "extendLeft", 2);
__decorateClass([
Property21
], PriceRangeProperties.prototype, "extendRight", 2);
var DatePriceRangeProperties = class extends DateRange(PriceRange(MeasurerTypeProperties)) {
constructor() {
super(...arguments);
this.type = "date-price-range" /* DatePriceRange */;
this.direction = "both";
}
static is(value) {
return isObject3(value) && value.type === "date-price-range" /* DatePriceRange */;
}
};
__decorateClass([
Property21
], DatePriceRangeProperties.prototype, "type", 2);
var QuickDatePriceRangeProperties = class extends DateRange(PriceRange(MeasurerTypeProperties)) {
constructor() {
super(...arguments);
this.type = "quick-date-price-range" /* QuickDatePriceRange */;
this.up = new MeasurerDirectionProperties();
this.down = new MeasurerDirectionProperties();
this.direction = "both";
}
static is(value) {
return isObject3(value) && value.type === "quick-date-price-range" /* QuickDatePriceRange */;
}
};
__decorateClass([
Property21
], QuickDatePriceRangeProperties.prototype, "type", 2);
__decorateClass([
Property21
], QuickDatePriceRangeProperties.prototype, "up", 2);
__decorateClass([
Property21
], QuickDatePriceRangeProperties.prototype, "down", 2);
// packages/ag-charts-enterprise/src/features/annotations/note/noteProperties.ts
import { BaseProperties as BaseProperties8, Property as Property22, clamp as clamp2, isObject as isObject4 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/text/util.ts
import { _ModuleSupport as _ModuleSupport26 } from "ag-charts-community";
import { cachedTextMeasurer, calcLineHeight, wrapText } from "ag-charts-core";
var { BBox: BBox2 } = _ModuleSupport26;
var ANNOTATION_TEXT_LINE_HEIGHT = 1.38;
function maybeWrapText(options, text2, maxWidth) {
return maxWidth ? wrapText(text2, { maxWidth, font: options, textWrap: "always", avoidOrphans: false }) : text2;
}
function measureAnnotationText(options, text2) {
const { lineMetrics, width } = cachedTextMeasurer(options).measureLines(text2);
const height = lineMetrics.length * calcLineHeight(options.fontSize, ANNOTATION_TEXT_LINE_HEIGHT);
return { width, height };
}
function getBBox(options, text2, coords, bbox) {
let width = bbox?.width ?? 0;
let height = bbox?.height ?? 0;
if (!bbox) {
const wrappedText = options.width == null ? text2 : maybeWrapText(options, text2, options.width);
({ width, height } = measureAnnotationText(options, wrappedText));
}
return new BBox2(coords.x, coords.y, width, height);
}
function updateTextNode(node, text2, isPlaceholder, config, { x, y }, textBaseline) {
const { visible = true, fontFamily, fontSize = 14, fontStyle, fontWeight, textAlign } = config;
const lineHeight = calcLineHeight(fontSize, ANNOTATION_TEXT_LINE_HEIGHT);
textBaseline ?? (textBaseline = config.position == "center" ? "middle" : config.position);
const fill = isPlaceholder ? config.getPlaceholderColor() : config.color;
node.setProperties({
x,
y,
visible,
text: text2,
fill,
fontFamily,
fontSize,
fontStyle,
fontWeight,
textAlign,
lineHeight,
textBaseline
});
}
// packages/ag-charts-enterprise/src/features/annotations/note/noteProperties.ts
var DEFAULT_NOTE_PADDING = 10;
var HANDLE_SIZE = 11;
var ICON_HEIGHT = 20;
var ICON_WIDTH = 22;
var ICON_SPACING = 10;
var LABEL_OFFSET = ICON_HEIGHT + ICON_SPACING;
var TOOLBAR_OFFSET = 34;
var NoteBackgroundProperties = class extends Fill(Stroke(BaseProperties8)) {
};
var NoteProperties = class extends Fill(Stroke(TextualPointProperties)) {
constructor() {
super(...arguments);
this.type = "note" /* Note */;
this.background = new NoteBackgroundProperties();
this.position = "bottom";
this.alignment = "center";
this.width = 200;
}
static is(value) {
return isObject4(value) && value.type === "note" /* Note */;
}
getDefaultColor(colorPickerType) {
switch (colorPickerType) {
case `line-color`:
return this.fill;
case `text-color`:
return this.color;
}
}
getDefaultOpacity(colorPickerType) {
switch (colorPickerType) {
case `line-color`:
return this.fillOpacity;
case `text-color`:
return void 0;
}
}
getPadding() {
const padding2 = this.padding ?? DEFAULT_NOTE_PADDING;
return {
top: padding2,
right: padding2,
bottom: padding2,
left: padding2
};
}
getTextInputCoords(context, height) {
const { width, text: text2 } = this;
const textInputCoords = super.getTextInputCoords(context, height);
const padding2 = this.getPadding().top;
const bbox = getBBox(this, text2, textInputCoords);
bbox.x = clamp2(width / 2, bbox.x, context.seriesRect.width - width / 2);
const topY = bbox.y - LABEL_OFFSET - padding2 * 2;
const bottomY = bbox.y + HANDLE_SIZE + padding2 * 2;
const textHeight = Math.max(bbox.height, height);
if (topY - textHeight - TOOLBAR_OFFSET < 0) {
bbox.y = bottomY;
this.position = "top";
} else {
bbox.y = topY + padding2;
this.position = "bottom";
}
return {
x: bbox.x,
y: bbox.y
};
}
isHoverable() {
return true;
}
};
__decorateClass([
Property22
], NoteProperties.prototype, "type", 2);
__decorateClass([
Property22
], NoteProperties.prototype, "background", 2);
// packages/ag-charts-enterprise/src/features/annotations/properties/pointProperties.ts
import { BaseProperties as BaseProperties9 } from "ag-charts-core";
var PointProperties2 = class extends Annotation(Point(Handle(BaseProperties9))) {
getDefaultColor(_colorPickerType) {
return void 0;
}
getDefaultOpacity(_colorPickerType) {
return void 0;
}
};
// packages/ag-charts-enterprise/src/features/annotations/properties/shapePointProperties.ts
var ShapePointProperties = class _ShapePointProperties extends Fill(PointProperties2) {
constructor() {
super(...arguments);
this.size = 32;
}
static is(value) {
return value instanceof _ShapePointProperties;
}
getDefaultColor(colorPickerType) {
return colorPickerType === `fill-color` ? this.fill : void 0;
}
getDefaultOpacity(colorPickerType) {
return colorPickerType === `fill-color` ? this.fillOpacity : void 0;
}
};
// packages/ag-charts-enterprise/src/features/annotations/cross-line/crossLineProperties.ts
import "ag-charts-community";
import { BaseProperties as BaseProperties10, Property as Property23, isObject as isObject5 } from "ag-charts-core";
var HorizontalLineProperties = class extends Annotation(Value(Handle(AxisLabel(Stroke(LineStyle(BaseProperties10)))))) {
constructor() {
super(...arguments);
this.direction = "horizontal";
this.type = "horizontal-line" /* HorizontalLine */;
this.text = new LineTextProperties();
}
static is(value) {
return isObject5(value) && value.type === "horizontal-line" /* HorizontalLine */;
}
getDefaultColor() {
return this.stroke;
}
getDefaultOpacity() {
return this.strokeOpacity;
}
getLineDash() {
return getLineDash(this.lineDash, this.computedLineDash, this.lineStyle, this.strokeWidth);
}
getLineCap() {
return getLineCap(this.lineCap, this.lineDash, this.lineStyle);
}
};
__decorateClass([
Property23
], HorizontalLineProperties.prototype, "type", 2);
__decorateClass([
Property23
], HorizontalLineProperties.prototype, "text", 2);
var VerticalLineProperties = class extends Annotation(Value(Handle(AxisLabel(Stroke(LineStyle(BaseProperties10)))))) {
constructor() {
super(...arguments);
this.direction = "vertical";
this.type = "vertical-line" /* VerticalLine */;
this.text = new LineTextProperties();
}
static is(value) {
return isObject5(value) && value.type === "vertical-line" /* VerticalLine */;
}
getDefaultColor() {
return this.stroke;
}
getDefaultOpacity() {
return this.strokeOpacity;
}
getLineDash() {
return getLineDash(this.lineDash, this.computedLineDash, this.lineStyle, this.strokeWidth);
}
getLineCap() {
return getLineCap(this.lineCap, this.lineDash, this.lineStyle);
}
};
__decorateClass([
Property23
], VerticalLineProperties.prototype, "type", 2);
__decorateClass([
Property23
], VerticalLineProperties.prototype, "text", 2);
// packages/ag-charts-enterprise/src/features/annotations/disjoint-channel/disjointChannelProperties.ts
import "ag-charts-community";
import { BaseProperties as BaseProperties11, Logger, Property as Property24, isObject as isObject6 } from "ag-charts-core";
var DisjointChannelProperties = class extends Annotation(
Background2(Line3(Handle(Extendable(Stroke(LineStyle(BaseProperties11))))))
) {
constructor() {
super(...arguments);
this.type = "disjoint-channel" /* DisjointChannel */;
this.text = new ChannelTextProperties();
this.snapToAngle = 45;
}
static is(value) {
return isObject6(value) && value.type === "disjoint-channel" /* DisjointChannel */;
}
get bottom() {
const bottom = {
start: { x: this.start.x, y: this.start.y },
end: { x: this.end.x, y: this.end.y }
};
if (typeof bottom.start.y === "number" && typeof bottom.end.y === "number") {
bottom.start.y -= this.startHeight;
bottom.end.y -= this.endHeight;
} else {
Logger.warnOnce(`Annotation [${this.type}] can only be used with a numeric y-axis.`);
}
return bottom;
}
getDefaultColor(colorPickerType) {
switch (colorPickerType) {
case `fill-color`:
return this.background.fill;
case `line-color`:
return this.stroke;
case "text-color":
return this.text.color;
}
}
getDefaultOpacity(colorPickerType) {
switch (colorPickerType) {
case `fill-color`:
return this.background.fillOpacity;
case `line-color`:
return this.strokeOpacity;
}
}
getLineDash() {
return getLineDash(this.lineDash, this.computedLineDash, this.lineStyle, this.strokeWidth);
}
getLineCap() {
return getLineCap(this.lineCap, this.lineDash, this.lineStyle);
}
};
__decorateClass([
Property24
], DisjointChannelProperties.prototype, "type", 2);
__decorateClass([
Property24
], DisjointChannelProperties.prototype, "startHeight", 2);
__decorateClass([
Property24
], DisjointChannelProperties.prototype, "endHeight", 2);
__decorateClass([
Property24
], DisjointChannelProperties.prototype, "text", 2);
// packages/ag-charts-enterprise/src/features/annotations/fibonacci-retracement-trend-based/fibonacciRetracementTrendBasedProperties.ts
import { Property as Property27, isObject as isObject8 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/properties/fibonacciProperties.ts
import { Property as Property26 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/line/lineProperties.ts
import "ag-charts-community";
import { Property as Property25, isObject as isObject7 } from "ag-charts-core";
var LineTypeProperties = class extends Localisable(
Cappable(Extendable(Stroke(LineStyle(StartEndProperties))))
) {
constructor() {
super(...arguments);
this.text = new LineTextProperties();
}
getDefaultColor(colorPickerType) {
switch (colorPickerType) {
case "line-color":
return this.stroke;
case "text-color":
return this.text.color;
}
}
getDefaultOpacity() {
return this.strokeOpacity;
}
getLineDash() {
return getLineDash(this.lineDash, this.computedLineDash, this.lineStyle, this.strokeWidth);
}
getLineCap() {
return getLineCap(this.lineCap, this.lineDash, this.lineStyle);
}
};
__decorateClass([
Property25
], LineTypeProperties.prototype, "text", 2);
var ArrowProperties = class extends LineTypeProperties {
constructor() {
super(...arguments);
this.type = "arrow" /* Arrow */;
this.endCap = "arrow";
}
static is(value) {
return isObject7(value) && value.type === "arrow" /* Arrow */;
}
};
__decorateClass([
Property25
], ArrowProperties.prototype, "type", 2);
var LineProperties = class extends LineTypeProperties {
constructor() {
super(...arguments);
this.type = "line" /* Line */;
}
static is(value) {
return isObject7(value) && value.type === "line" /* Line */;
}
};
__decorateClass([
Property25
], LineProperties.prototype, "type", 2);
// packages/ag-charts-enterprise/src/features/annotations/properties/fibonacciProperties.ts
var FibonacciProperties = class extends LineTypeProperties {
constructor() {
super(...arguments);
this.label = new LabelTextProperties();
this.reverse = false;
this.showFill = true;
this.isMultiColor = true;
this.strokes = [];
this.bands = 10;
}
getDefaultColor(colorPickerType) {
switch (colorPickerType) {
case "line-color":
return this.rangeStroke ?? this.stroke;
case "text-color":
return this.text.color;
}
}
};
__decorateClass([
Property26
], FibonacciProperties.prototype, "label", 2);
__decorateClass([
Property26
], FibonacciProperties.prototype, "reverse", 2);
__decorateClass([
Property26
], FibonacciProperties.prototype, "showFill", 2);
__decorateClass([
Property26
], FibonacciProperties.prototype, "isMultiColor", 2);
__decorateClass([
Property26
], FibonacciProperties.prototype, "strokes", 2);
__decorateClass([
Property26
], FibonacciProperties.prototype, "rangeStroke", 2);
__decorateClass([
Property26
], FibonacciProperties.prototype, "bands", 2);
// packages/ag-charts-enterprise/src/features/annotations/fibonacci-retracement-trend-based/fibonacciRetracementTrendBasedProperties.ts
var FibonacciRetracementTrendBasedProperties = class extends FibonacciProperties {
constructor() {
super(...arguments);
this.type = "fibonacci-retracement-trend-based" /* FibonacciRetracementTrendBased */;
this.endRetracement = new PointProperties();
}
static is(value) {
return isObject8(value) && value.type === "fibonacci-retracement-trend-based" /* FibonacciRetracementTrendBased */;
}
};
__decorateClass([
Property27
], FibonacciRetracementTrendBasedProperties.prototype, "type", 2);
__decorateClass([
Property27
], FibonacciRetracementTrendBasedProperties.prototype, "endRetracement", 2);
// packages/ag-charts-enterprise/src/features/annotations/fibonacci-retracement/fibonacciRetracementProperties.ts
import { Property as Property28, isObject as isObject9 } from "ag-charts-core";
var FibonacciRetracementProperties = class extends FibonacciProperties {
constructor() {
super(...arguments);
this.type = "fibonacci-retracement" /* FibonacciRetracement */;
}
static is(value) {
return isObject9(value) && value.type === "fibonacci-retracement" /* FibonacciRetracement */;
}
};
__decorateClass([
Property28
], FibonacciRetracementProperties.prototype, "type", 2);
// packages/ag-charts-enterprise/src/features/annotations/parallel-channel/parallelChannelProperties.ts
import "ag-charts-community";
import { BaseProperties as BaseProperties12, Logger as Logger2, Property as Property29, isObject as isObject10 } from "ag-charts-core";
var ParallelChannelProperties = class extends Annotation(
Background2(Line3(Handle(Extendable(Stroke(LineStyle(BaseProperties12))))))
) {
constructor() {
super(...arguments);
this.type = "parallel-channel" /* ParallelChannel */;
this.middle = new ChannelAnnotationMiddleProperties();
this.text = new ChannelTextProperties();
this.snapToAngle = 45;
}
static is(value) {
return isObject10(value) && value.type === "parallel-channel" /* ParallelChannel */;
}
get bottom() {
const bottom = {
start: { x: this.start.x, y: this.start.y },
end: { x: this.end.x, y: this.end.y }
};
if (typeof bottom.start.y === "number" && typeof bottom.end.y === "number") {
bottom.start.y -= this.height;
bottom.end.y -= this.height;
} else {
Logger2.warnOnce(`Annotation [${this.type}] can only be used with a numeric y-axis.`);
}
return bottom;
}
getDefaultColor(colorPickerType) {
switch (colorPickerType) {
case `fill-color`:
return this.background.fill;
case `line-color`:
return this.stroke;
case "text-color":
return this.text.color;
}
}
getDefaultOpacity(colorPickerType) {
switch (colorPickerType) {
case `fill-color`:
return this.background.fillOpacity;
case `line-color`:
return this.strokeOpacity;
}
}
getLineDash() {
return getLineDash(this.lineDash, this.computedLineDash, this.lineStyle, this.strokeWidth);
}
getLineCap() {
return getLineCap(this.lineCap, this.lineDash, this.lineStyle);
}
};
__decorateClass([
Property29
], ParallelChannelProperties.prototype, "type", 2);
__decorateClass([
Property29
], ParallelChannelProperties.prototype, "height", 2);
__decorateClass([
Property29
], ParallelChannelProperties.prototype, "middle", 2);
__decorateClass([
Property29
], ParallelChannelProperties.prototype, "text", 2);
// packages/ag-charts-enterprise/src/features/annotations/text/textProperties.ts
import { Property as Property30, isObject as isObject11 } from "ag-charts-core";
var TextProperties = class extends TextualPointProperties {
constructor() {
super(...arguments);
this.type = "text" /* Text */;
this.position = "bottom";
}
static is(value) {
return isObject11(value) && value.type === "text" /* Text */;
}
};
__decorateClass([
Property30
], TextProperties.prototype, "type", 2);
// packages/ag-charts-enterprise/src/features/annotations/utils/types.ts
function isEphemeralType(datum) {
return QuickDatePriceRangeProperties.is(datum);
}
function isLineType(datum) {
return LineProperties.is(datum) || HorizontalLineProperties.is(datum) || VerticalLineProperties.is(datum) || ArrowProperties.is(datum) || isFibonacciType(datum);
}
function isChannelType(datum) {
return DisjointChannelProperties.is(datum) || ParallelChannelProperties.is(datum);
}
function isFibonacciType(datum) {
return FibonacciRetracementProperties.is(datum) || FibonacciRetracementTrendBasedProperties.is(datum);
}
function isTextType(datum) {
return CalloutProperties.is(datum) || CommentProperties.is(datum) || NoteProperties.is(datum) || TextProperties.is(datum);
}
function isMeasurerType(datum) {
return DateRangeProperties.is(datum) || PriceRangeProperties.is(datum) || DatePriceRangeProperties.is(datum) || QuickDatePriceRangeProperties.is(datum);
}
// packages/ag-charts-enterprise/src/features/annotations/utils/has.ts
function hasFontSize(datum) {
return isTextType(datum) && !NoteProperties.is(datum);
}
function hasLineStyle(datum) {
return isLineType(datum) || isChannelType(datum) || isMeasurerType(datum) && !QuickDatePriceRangeProperties.is(datum);
}
function hasLineColor(datum) {
return isLineType(datum) || isChannelType(datum) || isMeasurerType(datum) || CalloutProperties.is(datum) || NoteProperties.is(datum);
}
function hasIconColor(datum) {
return NoteProperties.is(datum);
}
function hasFillColor(datum) {
return isChannelType(datum) || isMeasurerType(datum) || CalloutProperties.is(datum) || CommentProperties.is(datum) || ShapePointProperties.is(datum);
}
function hasTextColor(datum) {
return isTextType(datum) && !NoteProperties.is(datum);
}
function hasLineText(datum) {
return (isLineType(datum) || isChannelType(datum) || isMeasurerType(datum)) && !isEphemeralType(datum) && isObject12(datum.text);
}
// packages/ag-charts-enterprise/src/features/annotations/utils/styles.ts
function setFontSize(datum, fontSize) {
if ("fontSize" in datum)
datum.fontSize = fontSize;
if (hasLineText(datum))
datum.text.fontSize = fontSize;
}
function setLineStyle(datum, style) {
const strokeWidth = style?.strokeWidth ?? datum.strokeWidth ?? 1;
const lineType = style?.type ?? datum.lineStyle;
const lineStyle = lineType ?? getLineStyle(datum.lineDash, lineType);
const computedLineDash = getComputedLineDash(strokeWidth, lineStyle);
datum.strokeWidth = strokeWidth;
datum.computedLineDash = computedLineDash;
datum.lineStyle = lineStyle;
datum.lineCap = lineStyle === "dotted" ? "round" : void 0;
}
function setColor(datum, colorPickerType, colorOpacity, color7, opacity, isMultiColor) {
switch (colorPickerType) {
case `fill-color`: {
if ("fill" in datum)
datum.fill = color7;
if ("fillOpacity" in datum)
datum.fillOpacity = opacity;
if ("background" in datum) {
datum.background.fill = color7;
datum.background.fillOpacity = opacity;
}
break;
}
case `line-color`: {
if ("axisLabel" in datum) {
datum.axisLabel.fill = color7;
datum.axisLabel.fillOpacity = opacity;
datum.axisLabel.stroke = color7;
datum.axisLabel.strokeOpacity = opacity;
}
if ("fill" in datum && "fillOpacity" in datum && hasIconColor(datum)) {
datum.fill = color7;
datum.fillOpacity = opacity;
} else {
if ("strokeOpacity" in datum)
datum.strokeOpacity = opacity;
if ("isMultiColor" in datum && "rangeStroke" in datum) {
datum.isMultiColor = isMultiColor;
datum.rangeStroke = color7;
} else if ("stroke" in datum) {
datum.stroke = color7;
}
}
break;
}
case `text-color`: {
if ("color" in datum)
datum.color = colorOpacity;
if (hasLineText(datum))
datum.text.color = color7;
break;
}
}
}
// packages/ag-charts-enterprise/src/features/annotations/annotationDefaults.ts
var AnnotationDefaults = class {
constructor() {
this.mementoOriginatorKey = "annotation-defaults";
this.colors = new Map(
Object.values(AnnotationType).map((type) => [
type,
/* @__PURE__ */ new Map([
["line-color", void 0],
["fill-color", void 0],
["text-color", void 0]
])
])
);
this.fontSizes = /* @__PURE__ */ new Map([
["callout" /* Callout */, void 0],
["comment" /* Comment */, void 0],
["text" /* Text */, void 0],
["arrow" /* Arrow */, void 0],
["line" /* Line */, void 0],
["disjoint-channel" /* DisjointChannel */, void 0],
["parallel-channel" /* ParallelChannel */, void 0],
["date-range" /* DateRange */, void 0],
["price-range" /* PriceRange */, void 0],
["date-price-range" /* DatePriceRange */, void 0]
]);
this.lineStyles = /* @__PURE__ */ new Map([
["line" /* Line */, void 0],
["horizontal-line" /* HorizontalLine */, void 0],
["vertical-line" /* VerticalLine */, void 0],
["disjoint-channel" /* DisjointChannel */, void 0],
["parallel-channel" /* ParallelChannel */, void 0],
["arrow" /* Arrow */, void 0],
["date-range" /* DateRange */, void 0],
["price-range" /* PriceRange */, void 0],
["date-price-range" /* DatePriceRange */, void 0]
]);
this.lineTextAlignments = /* @__PURE__ */ new Map([
["line" /* Line */, void 0],
["horizontal-line" /* HorizontalLine */, void 0],
["vertical-line" /* VerticalLine */, void 0],
["disjoint-channel" /* DisjointChannel */, void 0],
["parallel-channel" /* ParallelChannel */, void 0],
["arrow" /* Arrow */, void 0],
["date-range" /* DateRange */, void 0],
["price-range" /* PriceRange */, void 0],
["date-price-range" /* DatePriceRange */, void 0]
]);
this.lineTextPositions = /* @__PURE__ */ new Map([
["line" /* Line */, void 0],
["horizontal-line" /* HorizontalLine */, void 0],
["vertical-line" /* VerticalLine */, void 0],
["disjoint-channel" /* DisjointChannel */, void 0],
["parallel-channel" /* ParallelChannel */, void 0],
["arrow" /* Arrow */, void 0],
["date-range" /* DateRange */, void 0],
["price-range" /* PriceRange */, void 0],
["date-price-range" /* DatePriceRange */, void 0]
]);
this.fibonacciOptions = /* @__PURE__ */ new Map([
[
"fibonacci-retracement" /* FibonacciRetracement */,
{
bands: void 0,
reverse: void 0,
showFill: void 0
}
],
[
"fibonacci-retracement-trend-based" /* FibonacciRetracementTrendBased */,
{
bands: void 0,
reverse: void 0,
showFill: void 0
}
]
]);
}
createMemento() {
return {
colors: deepClone(this.colors),
fontSizes: deepClone(this.fontSizes),
lineStyles: deepClone(this.lineStyles),
lineTextAlignments: deepClone(this.lineTextAlignments),
lineTextPositions: deepClone(this.lineTextPositions),
fibonacciOptions: deepClone(this.fibonacciOptions)
};
}
guardMemento(_blob) {
return true;
}
restoreMemento(_version, _mementoVersion, blob) {
this.colors = deepClone(blob.colors);
this.fontSizes = deepClone(blob.fontSizes);
this.lineStyles = deepClone(blob.lineStyles);
this.lineTextAlignments = deepClone(blob.lineTextAlignments);
this.lineTextPositions = deepClone(blob.lineTextPositions);
this.fibonacciOptions = deepClone(blob.fibonacciOptions);
}
setDefaultColor(type, colorType, colorOpacity, color7, opacity, isMultiColor) {
this.colors.get(type)?.set(colorType, [colorOpacity, color7, opacity, isMultiColor]);
}
setDefaultFontSize(type, fontSize) {
this.fontSizes.set(type, fontSize);
}
setDefaultLineStyleType(type, lineStyleType) {
const defaultStyle = this.lineStyles.get(type);
if (defaultStyle) {
defaultStyle.type = lineStyleType;
} else {
this.lineStyles.set(type, { type: lineStyleType });
}
}
setDefaultLineStyleWidth(type, strokeWidth) {
const defaultStyle = this.lineStyles.get(type);
if (defaultStyle) {
defaultStyle.strokeWidth = strokeWidth;
} else {
this.lineStyles.set(type, { strokeWidth });
}
}
setDefaultLineTextAlignment(type, alignment) {
this.lineTextAlignments.set(type, alignment);
}
setDefaultLineTextPosition(type, position) {
this.lineTextPositions.set(type, position);
}
setDefaultFibonacciOptions(type, key, value) {
if (type != "fibonacci-retracement" /* FibonacciRetracement */ && type != "fibonacci-retracement-trend-based" /* FibonacciRetracementTrendBased */)
return;
const options = this.fibonacciOptions.get(type);
options[key] = value;
this.fibonacciOptions.set(type, options);
}
applyDefaults(datum) {
for (const [annotationType, colors] of this.colors) {
if (datum.type !== annotationType)
continue;
for (const [colorPickerType, [colorOpacity, color7, opacity, isMultiColor] = []] of colors) {
if (colorOpacity && color7 && opacity != null && isMultiColor != null) {
setColor(datum, colorPickerType, colorOpacity, color7, opacity, isMultiColor);
}
}
}
for (const [annotationType, size] of this.fontSizes) {
if (datum.type !== annotationType || size == null)
continue;
setFontSize(datum, size);
}
for (const [annotationType, style] of this.lineStyles) {
if (datum.type !== annotationType || style == null)
continue;
setLineStyle(datum, style);
}
for (const [annotationType, position] of this.lineTextPositions) {
if (datum.type !== annotationType || position == null)
continue;
datum.text.position = position;
}
for (const [annotationType, alignment] of this.lineTextAlignments) {
if (datum.type !== annotationType || alignment == null)
continue;
datum.text.alignment = alignment;
}
for (const [annotationType, options] of this.fibonacciOptions) {
if (datum.type !== annotationType || options == null)
continue;
for (const option of Object.keys(options)) {
const value = options[option];
if (value == null) {
continue;
}
datum.set({ [option]: value });
}
}
}
};
// packages/ag-charts-enterprise/src/features/annotations/annotationOptionsToolbar.ts
import { _ModuleSupport as _ModuleSupport33 } from "ag-charts-community";
import {
BaseProperties as BaseProperties14,
CleanupRegistry as CleanupRegistry2,
Color as Color4,
EventEmitter,
PropertiesArray,
Property as Property32
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/components/color-picker/colorPicker.ts
import { _ModuleSupport as _ModuleSupport31 } from "ag-charts-community";
import { Color as Color3, attachListener as attachListener2, clamp as clamp3, createElement as createElement3, getWindow } from "ag-charts-core";
// packages/ag-charts-enterprise/src/components/color-picker/colorPickerTemplate.html
var colorPickerTemplate_default = '<div class="ag-charts-color-picker__palette" role="slider" tabindex="0"></div><div class="ag-charts-color-picker__color-row" role="presentation"><button class="ag-charts-color-picker__multi-color-button" tabindex="0" type="button" role="switch"></button> <input class="ag-charts-color-picker__hue-input" tabindex="0" type="range" min="0" max="360" value="0"></div><input class="ag-charts-color-picker__alpha-input" tabindex="0" type="range" min="0" max="1" value="1" step="0.01"> <label class="ag-charts-color-picker__color-field" role="presentation"><span class="ag-charts-color-picker__color-label" aria-hidden="true"></span> <input class="ag-charts-color-picker__color-input" tabindex="0" value="#000"></label>';
// packages/ag-charts-enterprise/src/components/color-picker/colorPicker.ts
var getHsva = (input) => {
try {
const color7 = Color3.fromString(input);
const [h, s, v] = color7.toHSB();
return [h, s, v, color7.a];
} catch {
return;
}
};
var ColorPicker = class extends _ModuleSupport31.AnchoredPopover {
constructor(ctx, options) {
super(ctx, "color-picker", options);
this.hasChanged = false;
this.hideFns.push(() => {
this.i18nUpdater = void 0;
if (this.hasChanged)
this.onChangeHide?.();
});
this.cleanup.register(this.ctx.eventsHub.on("locale:change", () => this.i18nUpdater?.()));
}
show(options) {
this.hasChanged = false;
this.onChangeHide = options.onChangeHide;
const { element, initialFocus } = this.createColorPicker(options);
const popover = this.showWithChildren([element], { initialFocus, ...options });
popover.classList.add("ag-charts-color-picker");
popover.setAttribute("role", "dialog");
}
createColorPicker(opts) {
const { localeManager } = this.ctx;
let isMultiColor = opts.isMultiColor ?? false;
let [h, s, v, a] = getHsva(opts.color ?? "#f00") ?? [0, 1, 0.5, 1];
a = opts.opacity ?? a;
const colorPicker = createElement3("div", "ag-charts-color-picker__content");
colorPicker.innerHTML = colorPickerTemplate_default;
colorPicker.ariaLabel = this.ctx.localeManager.t("ariaLabelColorPicker");
const paletteInput = colorPicker.querySelector(".ag-charts-color-picker__palette");
const hueInput = colorPicker.querySelector(".ag-charts-color-picker__hue-input");
const multiColorButton = colorPicker.querySelector(
".ag-charts-color-picker__multi-color-button"
);
const alphaInput = colorPicker.querySelector(".ag-charts-color-picker__alpha-input");
const colorInput = colorPicker.querySelector(".ag-charts-color-picker__color-input");
const colorInputLabel = colorPicker.querySelector(".ag-charts-color-picker__color-label");
const updatePaletteInputAriaValue = (first) => {
const key = { s: "ariaValueColorPalette", v: "ariaValueColorPaletteFirstV" }[first];
paletteInput.ariaValueText = localeManager.t(key, { s, v });
};
this.i18nUpdater = () => {
paletteInput.ariaRoleDescription = localeManager.t("ariaRoleDescription2DSlider");
paletteInput.ariaLabel = localeManager.t("ariaLabelColorPickerPalette");
hueInput.ariaLabel = localeManager.t("ariaLabelColorPickerHue");
multiColorButton.ariaLabel = localeManager.t("ariaLabelColorPickerMultiColor");
alphaInput.ariaLabel = localeManager.t("ariaLabelColorPickerAlpha");
colorInput.ariaLabel = localeManager.t("ariaLabelColor");
updatePaletteInputAriaValue("s");
};
this.i18nUpdater();
multiColorButton.classList.toggle(
"ag-charts-color-picker__multi-color-button--hidden",
!opts.hasMultiColorOption
);
const update = (trackChange = true) => {
const color7 = Color3.fromHSB(h, s, v, a);
const colorString = color7.toHexString();
colorPicker.style.setProperty("--h", `${h}`);
colorPicker.style.setProperty("--s", `${s}`);
colorPicker.style.setProperty("--v", `${v}`);
colorPicker.style.setProperty("--a", `${a}`);
colorPicker.style.setProperty("--color", colorString.slice(0, 7));
colorPicker.style.setProperty("--color-a", colorString);
hueInput.value = `${h}`;
alphaInput.value = `${a}`;
alphaInput.classList.toggle("ag-charts-color-picker__alpha-input--opaque", a === 1);
multiColorButton.classList.toggle("ag-charts-color-picker__multi-color-button--active", isMultiColor);
colorInputLabel.classList.toggle("ag-charts-color-picker__color-label--multi-color", isMultiColor);
if (document.activeElement !== colorInput) {
multiColorButton.ariaChecked = isMultiColor.toString();
colorInput.value = isMultiColor ? localeManager.t("ariaLabelColorPickerMultiColor") : colorString.toUpperCase();
}
if (trackChange || opts.color == null) {
const plainColor = Color3.fromHSB(h, s, v, 1).toHexString();
opts.onChange?.(colorString, plainColor, a, isMultiColor);
}
if (trackChange)
this.hasChanged = true;
};
update(false);
const preventDefault = (event) => event.preventDefault();
const stopPropagation = (event) => event.stopPropagation();
const beginPaletteInteraction = (e) => {
e.preventDefault();
const currentTarget = e.currentTarget;
currentTarget.focus();
const rect = currentTarget.getBoundingClientRect();
const pointerMove = ({ clientX, clientY }) => {
isMultiColor = false;
s = Math.min(Math.max((clientX - rect.left) / rect.width, 0), 1);
v = 1 - Math.min(Math.max((clientY - rect.top) / rect.height, 0), 1);
update();
updatePaletteInputAriaValue("s");
};
pointerMove(e);
const pointerUp = attachListener2(getWindow(), "pointermove", pointerMove);
getWindow().addEventListener("pointerup", pointerUp, { once: true });
};
colorPicker.addEventListener("mousedown", stopPropagation);
colorPicker.addEventListener("touchstart", stopPropagation);
colorPicker.addEventListener("touchmove", stopPropagation);
colorPicker.addEventListener("keydown", (e) => {
e.stopPropagation();
switch (e.key) {
case "Enter":
case "Escape":
this.hide();
break;
default:
return;
}
e.preventDefault();
});
paletteInput.addEventListener("pointerdown", beginPaletteInteraction);
paletteInput.addEventListener("touchstart", preventDefault, { passive: false });
paletteInput.addEventListener("touchmove", preventDefault, { passive: false });
paletteInput.addEventListener("keydown", (e) => {
if (e.key === "ArrowLeft") {
s = clamp3(0, s - 0.01, 1);
updatePaletteInputAriaValue("s");
} else if (e.key === "ArrowRight") {
s = clamp3(0, s + 0.01, 1);
updatePaletteInputAriaValue("s");
} else if (e.key === "ArrowUp") {
v = clamp3(0, v + 0.01, 1);
updatePaletteInputAriaValue("v");
} else if (e.key === "ArrowDown") {
v = clamp3(0, v - 0.01, 1);
updatePaletteInputAriaValue("v");
} else {
return;
}
e.preventDefault();
update();
});
paletteInput.addEventListener("focus", () => {
updatePaletteInputAriaValue("s");
});
multiColorButton.addEventListener("click", () => {
isMultiColor = !isMultiColor;
update();
});
hueInput.addEventListener("input", (e) => {
isMultiColor = false;
h = e.currentTarget.valueAsNumber ?? 0;
update();
});
alphaInput.addEventListener("input", (e) => {
isMultiColor = false;
a = e.currentTarget.valueAsNumber ?? 0;
update();
});
colorInput.addEventListener("input", (e) => {
isMultiColor = false;
const hsva = getHsva(e.currentTarget.value);
if (hsva == null)
return;
[h, s, v, a] = hsva;
update();
});
colorInput.addEventListener("blur", () => update());
colorInput.addEventListener("keydown", (e) => {
if (e.key === "Enter") {
e.currentTarget.blur();
update();
}
});
return { element: colorPicker, initialFocus: paletteInput };
}
};
// packages/ag-charts-enterprise/src/features/toolbar/buttonProperties.ts
import { BaseProperties as BaseProperties13, Property as Property31 } from "ag-charts-core";
var ToolbarButtonProperties = class extends BaseProperties13 {
};
__decorateClass([
Property31
], ToolbarButtonProperties.prototype, "icon", 2);
__decorateClass([
Property31
], ToolbarButtonProperties.prototype, "label", 2);
__decorateClass([
Property31
], ToolbarButtonProperties.prototype, "ariaLabel", 2);
__decorateClass([
Property31
], ToolbarButtonProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/features/annotations/annotationsMenuOptions.ts
import { _ModuleSupport as _ModuleSupport32 } from "ag-charts-community";
function channelMenuItemVisible(scale) {
return !(scale instanceof _ModuleSupport32.LogScale) && !(scale instanceof _ModuleSupport32.BandScale);
}
var LINE_ANNOTATION_ITEMS = [
{
label: "toolbarAnnotationsTrendLine",
icon: "trend-line-drawing",
value: "line" /* Line */
},
{
label: "toolbarAnnotationsHorizontalLine",
icon: "horizontal-line-drawing",
value: "horizontal-line" /* HorizontalLine */
},
{
label: "toolbarAnnotationsVerticalLine",
icon: "vertical-line-drawing",
value: "vertical-line" /* VerticalLine */
},
{
label: "toolbarAnnotationsParallelChannel",
icon: "parallel-channel-drawing",
value: "parallel-channel" /* ParallelChannel */,
visible: channelMenuItemVisible
},
{
label: "toolbarAnnotationsDisjointChannel",
icon: "disjoint-channel-drawing",
value: "disjoint-channel" /* DisjointChannel */,
visible: channelMenuItemVisible
}
];
var FIBONACCI_ANNOTATION_ITEMS = [
{
label: "toolbarAnnotationsFibonacciRetracement",
icon: "fibonacci-retracement-drawing",
value: "fibonacci-retracement" /* FibonacciRetracement */
},
{
label: "toolbarAnnotationsFibonacciRetracementTrendBased",
icon: "fibonacci-retracement-trend-based-drawing",
value: "fibonacci-retracement-trend-based" /* FibonacciRetracementTrendBased */
}
];
var FIBONACCI_RATIO_ITEMS = [
{ label: "Fibonacci - Extended", value: 10 },
{ label: "Fibonacci - 6 Band", value: 6 },
{ label: "Fibonacci - 4 Band", value: 4 }
];
var TEXT_ANNOTATION_ITEMS = [
{ label: "toolbarAnnotationsText", icon: "text-annotation", value: "text" /* Text */ },
{ label: "toolbarAnnotationsComment", icon: "comment-annotation", value: "comment" /* Comment */ },
{ label: "toolbarAnnotationsCallout", icon: "callout-annotation", value: "callout" /* Callout */ },
{ label: "toolbarAnnotationsNote", icon: "note-annotation", value: "note" /* Note */ }
];
var SHAPE_ANNOTATION_ITEMS = [
{ label: "toolbarAnnotationsArrow", icon: "arrow-drawing", value: "arrow" /* Arrow */ },
{ label: "toolbarAnnotationsArrowUp", icon: "arrow-up-drawing", value: "arrow-up" /* ArrowUp */ },
{ label: "toolbarAnnotationsArrowDown", icon: "arrow-down-drawing", value: "arrow-down" /* ArrowDown */ }
];
var MEASURER_ANNOTATION_ITEMS = [
{
label: "toolbarAnnotationsQuickDatePriceRange",
icon: "measurer-drawing",
value: "quick-date-price-range" /* QuickDatePriceRange */
},
{ label: "toolbarAnnotationsDateRange", icon: "date-range-drawing", value: "date-range" /* DateRange */ },
{ label: "toolbarAnnotationsPriceRange", icon: "price-range-drawing", value: "price-range" /* PriceRange */ },
{
label: "toolbarAnnotationsDatePriceRange",
icon: "date-price-range-drawing",
value: "date-price-range" /* DatePriceRange */
}
];
var LINE_STROKE_WIDTH_ITEMS = [
{ strokeWidth: 1, label: "1", value: 1 },
{ strokeWidth: 2, label: "2", value: 2 },
{ strokeWidth: 3, label: "3", value: 3 },
{ strokeWidth: 4, label: "4", value: 4 },
{ strokeWidth: 8, label: "8", value: 8 }
];
var LINE_STYLE_TYPE_ITEMS = [
{ icon: "line-style-solid", altText: "iconAltTextLineStyleSolid", value: "solid" },
{ icon: "line-style-dashed", altText: "iconAltTextLineStyleDashed", value: "dashed" },
{ icon: "line-style-dotted", altText: "iconAltTextLineStyleDotted", value: "dotted" }
];
var TEXT_SIZE_ITEMS = [
{ label: "10", value: 10 },
{ label: "12", value: 12 },
{ label: "14", value: 14 },
{ label: "16", value: 16 },
{ label: "18", value: 18 },
{ label: "22", value: 22 },
{ label: "28", value: 28 },
{ label: "36", value: 36 },
{ label: "46", value: 46 }
];
// packages/ag-charts-enterprise/src/features/annotations/annotationOptionsToolbar.ts
var { FloatingToolbar, Menu, ToolbarButtonWidget } = _ModuleSupport33;
var AnnotationOptionsButtonProperties = class extends ToolbarButtonProperties {
constructor() {
super(...arguments);
this.checkedOverrides = new ToolbarButtonProperties();
}
};
__decorateClass([
Property32
], AnnotationOptionsButtonProperties.prototype, "value", 2);
__decorateClass([
Property32
], AnnotationOptionsButtonProperties.prototype, "checkedOverrides", 2);
__decorateClass([
Property32
], AnnotationOptionsButtonProperties.prototype, "color", 2);
__decorateClass([
Property32
], AnnotationOptionsButtonProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property32
], AnnotationOptionsButtonProperties.prototype, "isMultiColor", 2);
var AnnotationOptionsButtonWidget = class extends ToolbarButtonWidget {
update(options) {
super.update(options);
if (options.value === "line-stroke-width" /* LineStrokeWidth */) {
this.updateLineStrokeWidth(options);
}
if (options.value === "fill-color" /* FillColor */ || options.value === "line-color" /* LineColor */ || options.value === "text-color" /* TextColor */) {
this.updateFillColor(options);
}
}
updateFillColor(options) {
const element = this.getElement();
element.classList.add("ag-charts-annotations__color-picker-button");
element.classList.toggle("ag-charts-annotations__color-picker-button--multi-color", options.isMultiColor);
element.style.setProperty("--color", options.color ?? null);
}
updateLineStrokeWidth(options) {
const element = this.getElement();
element.classList.add("ag-charts-annotations__stroke-width-button");
element.style.setProperty("--stroke-width", `${options.strokeWidth}px`);
}
};
var FloatingAnnotationOptionsToolbar = class extends FloatingToolbar {
createButtonWidget() {
return new AnnotationOptionsButtonWidget(this.localeManager);
}
};
var AnnotationOptionsToolbar = class extends BaseProperties14 {
constructor(ctx, getActiveDatum) {
super();
this.ctx = ctx;
this.getActiveDatum = getActiveDatum;
this.enabled = true;
this.buttons = new PropertiesArray(AnnotationOptionsButtonProperties);
this.cleanup = new CleanupRegistry2();
this.events = new EventEmitter();
this.visibleButtons = [];
this.toolbar = new FloatingAnnotationOptionsToolbar(
this.ctx,
"ariaLabelAnnotationOptionsToolbar",
"annotation-options"
);
this.colorPicker = new ColorPicker(this.ctx);
this.textSizeMenu = new Menu(this.ctx, "text-size");
this.lineStyleTypeMenu = new Menu(this.ctx, "annotations-line-style-type");
this.lineStrokeWidthMenu = new Menu(this.ctx, "annotations-line-stroke-width");
this.cleanup.register(
this.toolbar.addToolbarListener("button-pressed", this.onButtonPress.bind(this)),
this.toolbar.addToolbarListener("toolbar-moved", this.onToolbarMoved.bind(this)),
ctx.widgets.seriesWidget.addListener("drag-start", this.onDragStart.bind(this)),
ctx.widgets.seriesWidget.addListener("drag-end", this.onDragEnd.bind(this)),
() => {
this.colorPicker.destroy();
this.toolbar.destroy();
}
);
}
onDragStart() {
this.toolbar.ignorePointerEvents();
}
onDragEnd() {
this.toolbar.capturePointerEvents();
}
destroy() {
this.cleanup.flush();
}
show() {
if (!this.enabled)
return;
this.toolbar.show();
}
hide() {
this.toolbar.hide();
}
updateButtons(datum) {
if (!this.enabled)
return;
const visible = {
["line-style-type" /* LineStyleType */]: hasLineStyle(datum),
["line-stroke-width" /* LineStrokeWidth */]: hasLineStyle(datum),
["line-color" /* LineColor */]: hasLineColor(datum),
["text-color" /* TextColor */]: hasTextColor(datum),
["fill-color" /* FillColor */]: hasFillColor(datum),
["text-size" /* TextSize */]: hasFontSize(datum),
["settings" /* Settings */]: hasLineText(datum),
["lock" /* Lock */]: true,
["delete" /* Delete */]: true
};
this.visibleButtons = this.buttons.filter((button) => visible[button.value]);
this.toolbar.clearButtons();
this.toolbar.updateButtons(this.visibleButtons);
this.refreshButtons(datum);
}
setAnchorScene(scene) {
if (this.toolbar.hasBeenDragged())
return;
this.toolbar.setAnchor(scene.getAnchor());
}
hideOverlays() {
this.toolbar.clearActiveButton();
this.colorPicker.hide({ lastFocus: null });
this.textSizeMenu.hide();
this.lineStyleTypeMenu.hide();
this.lineStrokeWidthMenu.hide();
this.events.emit("hid-overlays", null);
}
clearActiveButton() {
this.toolbar.clearActiveButton();
}
updateColors(datum) {
this.updateColorPickerColor(
"line-color" /* LineColor */,
datum.getDefaultColor("line-color" /* LineColor */),
datum.getDefaultOpacity("line-color" /* LineColor */),
"isMultiColor" in datum && datum?.isMultiColor
);
this.updateColorPickerColor(
"fill-color" /* FillColor */,
datum.getDefaultColor("fill-color" /* FillColor */),
datum.getDefaultOpacity("fill-color" /* FillColor */),
"isMultiColor" in datum && datum?.isMultiColor
);
this.updateColorPickerColor(
"text-color" /* TextColor */,
datum.getDefaultColor("text-color" /* TextColor */),
datum.getDefaultOpacity("text-color" /* TextColor */),
"isMultiColor" in datum && datum?.isMultiColor
);
}
updateColorPickerColor(colorPickerType, color7, opacity, isMultiColor) {
if (color7 != null && opacity != null) {
const { r, g, b } = Color4.fromString(color7);
color7 = Color4.fromArray([r, g, b, opacity]).toHexString();
}
this.updateButtonByValue(colorPickerType, { color: color7, isMultiColor });
}
updateFontSize(fontSize) {
this.updateButtonByValue("text-size" /* TextSize */, {
label: fontSize == null ? void 0 : String(fontSize)
});
}
updateLineStyleType(item) {
this.updateButtonByValue("line-style-type" /* LineStyleType */, {
icon: item.icon
});
}
updateStrokeWidth(item) {
this.updateButtonByValue("line-stroke-width" /* LineStrokeWidth */, {
label: item.label,
strokeWidth: item.value
});
}
onButtonPress({
event,
button,
buttonWidget
}) {
const datum = this.getActiveDatum();
if (!datum)
return;
this.hideOverlays();
switch (button.value) {
case "line-style-type" /* LineStyleType */: {
const lineStyle = hasLineStyle(datum) ? getLineStyle(datum.lineDash, datum.lineStyle) : void 0;
this.lineStyleTypeMenu.show(buttonWidget, {
items: LINE_STYLE_TYPE_ITEMS,
ariaLabel: this.ctx.localeManager.t("toolbarAnnotationsLineStyle"),
value: lineStyle,
onPress: (item) => this.onLineStyleTypeMenuPress(item, datum),
class: "ag-charts-annotations__line-style-type-menu"
});
break;
}
case "line-stroke-width" /* LineStrokeWidth */: {
const strokeWidth = hasLineStyle(datum) ? datum.strokeWidth : void 0;
this.lineStrokeWidthMenu.show(buttonWidget, {
items: LINE_STROKE_WIDTH_ITEMS,
ariaLabel: this.ctx.localeManager.t("toolbarAnnotationsLineStrokeWidth"),
value: strokeWidth,
onPress: (item) => this.onLineStrokeWidthMenuPress(item, datum),
class: "ag-charts-annotations__line-stroke-width-menu"
});
break;
}
case "line-color" /* LineColor */:
case "fill-color" /* FillColor */:
case "text-color" /* TextColor */: {
this.toolbar.toggleActiveButtonByIndex(button.index);
this.colorPicker.show({
color: datum?.getDefaultColor(button.value),
opacity: datum?.getDefaultOpacity(button.value),
sourceEvent: event.sourceEvent,
hasMultiColorOption: "isMultiColor" in datum,
isMultiColor: "isMultiColor" in datum && datum?.isMultiColor,
onChange: datum == null ? void 0 : this.onColorPickerChange.bind(this, button.value, datum),
onChangeHide: ((type) => {
this.events.emit("saved-color", {
type: datum.type,
colorPickerType: button.value,
color: datum.getDefaultColor(type)
});
}).bind(this, button.value)
});
break;
}
case "text-size" /* TextSize */: {
const fontSize = isTextType(datum) ? datum.fontSize : void 0;
this.textSizeMenu.show(buttonWidget, {
items: TEXT_SIZE_ITEMS,
ariaLabel: this.ctx.localeManager.t("toolbarAnnotationsTextSize"),
value: fontSize,
onPress: (item) => this.onTextSizeMenuPress(item, datum),
class: "ag-charts-annotations__text-size-menu"
});
break;
}
case "delete" /* Delete */: {
this.events.emit("pressed-delete", null);
break;
}
case "lock" /* Lock */: {
datum.locked = !datum.locked;
this.refreshButtons(datum);
this.events.emit("pressed-lock", { locked: datum.locked });
break;
}
case "settings" /* Settings */: {
this.toolbar.toggleActiveButtonByIndex(button.index);
this.events.emit("pressed-settings", event);
break;
}
}
}
onToolbarMoved(event) {
const { buttonBounds, popoverBounds } = event;
const colorPickerAnchor = { x: popoverBounds.x, y: popoverBounds.y + popoverBounds.height + 4 };
const colorPickerFallbackAnchor = { y: popoverBounds.y - 4 };
this.colorPicker.setAnchor(colorPickerAnchor, colorPickerFallbackAnchor);
for (const [index, bounds] of buttonBounds.entries()) {
const button = this.visibleButtons.at(index);
if (!button)
continue;
const anchor = { x: bounds.x, y: bounds.y + bounds.height - 1 };
const fallbackAnchor = { y: bounds.y };
switch (button.value) {
case "line-stroke-width" /* LineStrokeWidth */:
this.lineStrokeWidthMenu.setAnchor(anchor, fallbackAnchor);
break;
case "line-style-type" /* LineStyleType */:
this.lineStyleTypeMenu.setAnchor(anchor, fallbackAnchor);
break;
case "text-size" /* TextSize */:
this.textSizeMenu.setAnchor(anchor, fallbackAnchor);
break;
}
}
}
onColorPickerChange(colorPickerType, datum, colorOpacity, color7, opacity, isMultiColor) {
this.events.emit("updated-color", {
type: datum.type,
colorPickerType,
colorOpacity,
color: color7,
opacity,
isMultiColor
});
this.updateColorPickerColor(colorPickerType, colorOpacity, opacity, isMultiColor);
}
onTextSizeMenuPress(item, datum) {
if (!hasFontSize(datum))
return;
const fontSize = item.value;
this.events.emit("updated-font-size", { type: datum.type, fontSize });
this.textSizeMenu.hide();
this.updateFontSize(fontSize);
}
onLineStyleTypeMenuPress(item, datum) {
if (!hasLineStyle(datum))
return;
const type = item.value;
this.events.emit("updated-line-style", { type: datum.type, lineStyleType: type });
this.lineStyleTypeMenu.hide();
this.updateLineStyleType(item);
}
onLineStrokeWidthMenuPress(item, datum) {
if (!hasLineStyle(datum)) {
return;
}
const strokeWidth = item.value;
this.events.emit("updated-line-width", { type: datum.type, strokeWidth });
this.lineStrokeWidthMenu.hide();
this.updateStrokeWidth(item);
}
refreshButtons(datum) {
const locked = datum.locked ?? false;
for (const [index, button] of this.visibleButtons.entries()) {
if (!button)
continue;
if (button.value === "lock" /* Lock */) {
this.toolbar.toggleSwitchCheckedByIndex(index, locked);
this.updateButtonByIndex(index, locked ? button.checkedOverrides.toJson() : button.toJson());
} else {
this.toolbar.toggleButtonEnabledByIndex(index, !locked);
}
}
if (hasFontSize(datum))
this.updateFontSize(datum.fontSize);
this.updateColors(datum);
this.updateLineStyles(datum);
}
updateLineStyles(datum) {
if (!hasLineStyle(datum))
return;
const strokeWidth = datum.strokeWidth ?? 1;
const lineStyleType = getLineStyle(datum.lineDash, datum.lineStyle);
this.updateStrokeWidth({
strokeWidth,
value: strokeWidth,
label: String(strokeWidth)
});
this.updateLineStyleType(
LINE_STYLE_TYPE_ITEMS.find((item) => item.value === lineStyleType) ?? LINE_STYLE_TYPE_ITEMS[0]
);
}
updateButtonByValue(value, change) {
const index = this.visibleButtons.findIndex((button) => button.value === value);
if (index === -1)
return;
this.updateButtonByIndex(index, change);
}
updateButtonByIndex(index, change) {
const button = this.visibleButtons.at(index);
if (!button)
return;
this.toolbar.updateButtonByIndex(index, { ...button.toJson(), ...change, value: change.value ?? button.value });
}
};
__decorateClass([
Property32
], AnnotationOptionsToolbar.prototype, "enabled", 2);
__decorateClass([
Property32
], AnnotationOptionsToolbar.prototype, "buttons", 2);
// packages/ag-charts-enterprise/src/features/annotations/states/dragState.ts
import { Debug, StateMachine, StateMachineProperty, Vec2 as Vec22 } from "ag-charts-core";
var DragStateMachine = class extends StateMachine {
constructor(ctx) {
const actionKeyChange = ({ context }) => {
this.node?.drag(this.datum, this.offset, context, this.snapping);
ctx.update();
};
super("idle", {
idle: {
dragStart: {
target: "dragging",
action: ({ offset, context }) => {
this.hasMoved = false;
this.dragStart = offset;
this.offset = offset;
this.node?.dragStart(this.datum, offset, context);
}
}
},
dragging: {
keyDown: actionKeyChange,
keyUp: actionKeyChange,
drag: ({ offset, context }) => {
this.hasMoved = Vec22.lengthSquared(Vec22.sub(offset, this.dragStart)) > 0;
this.offset = offset;
this.node?.drag(this.datum, offset, context, this.snapping);
ctx.update();
},
dragEnd: {
target: StateMachine.parent,
action: () => {
this.node?.stopDragging();
if (this.hasMoved)
ctx.recordAction("Move annotation");
ctx.update();
}
}
}
});
this.debug = Debug.create(true, "annotations");
this.hasMoved = false;
this.snapping = false;
}
};
__decorateClass([
StateMachineProperty()
], DragStateMachine.prototype, "snapping", 2);
__decorateClass([
StateMachineProperty()
], DragStateMachine.prototype, "datum", 2);
__decorateClass([
StateMachineProperty()
], DragStateMachine.prototype, "node", 2);
// packages/ag-charts-enterprise/src/features/annotations/arrow-down/arrowDownProperties.ts
import { Property as Property33, isObject as isObject13 } from "ag-charts-core";
var ArrowDownProperties = class extends ShapePointProperties {
constructor() {
super(...arguments);
this.type = "arrow-down" /* ArrowDown */;
}
static is(value) {
return isObject13(value) && value.type === "arrow-down" /* ArrowDown */;
}
};
__decorateClass([
Property33
], ArrowDownProperties.prototype, "type", 2);
// packages/ag-charts-enterprise/src/features/annotations/arrow-down/arrowDownScene.ts
import { _ModuleSupport as _ModuleSupport39 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/features/annotations/arrow-up/arrowUpScene.ts
import { _ModuleSupport as _ModuleSupport38 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/features/annotations/scenes/annotationScene.ts
import { _ModuleSupport as _ModuleSupport36 } from "ag-charts-community";
import { ZIndexMap as ZIndexMap3, isObject as isObject14 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/scenes/handle.ts
import { _ModuleSupport as _ModuleSupport35 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/features/annotations/scenes/annotationShape.ts
import { _ModuleSupport as _ModuleSupport34 } from "ag-charts-community";
var AnnotationShape = class extends _ModuleSupport34.Marker {
// Use exact method for this, rather than the Marker's high performance approximation.
isPointInPath(x, y) {
this.updatePathIfDirty();
return this.path.closedPath && this.path.isPointInPath(x, y);
}
};
// packages/ag-charts-enterprise/src/features/annotations/scenes/handle.ts
var _Handle = class _Handle extends _ModuleSupport35.Group {
constructor() {
super(...arguments);
this.active = false;
this.locked = false;
this.visible = false;
this.zIndex = 1;
}
drag(target) {
const { handle: handle3, locked } = this;
if (locked) {
return { point: { x: handle3.x, y: handle3.y }, offset: { x: 0, y: 0 } };
}
return {
point: target,
offset: { x: target.x - handle3.x, y: target.y - handle3.y }
};
}
toggleActive(active) {
this.active = active;
if (!active) {
this.handle.strokeWidth = _Handle.INACTIVE_STROKE_WIDTH;
}
}
toggleHovered(hovered) {
this.glow.visible = !this.locked && hovered;
this.glow.dirtyPath = true;
}
toggleDragging(dragging) {
if (this.locked)
return;
this.handle.visible = !dragging;
this.glow.visible = this.glow.visible && !dragging;
this.handle.dirtyPath = true;
this.glow.dirtyPath = true;
}
toggleLocked(locked) {
this.locked = locked;
}
getCursor() {
return void 0;
}
containsPoint(x, y) {
return this.handle.containsPoint(x, y);
}
};
_Handle.INACTIVE_STROKE_WIDTH = 2;
var Handle2 = _Handle;
var _InvariantHandle = class _InvariantHandle extends Handle2 {
constructor() {
super();
this.handle = new AnnotationShape({ shape: "circle" });
this.glow = new AnnotationShape({ shape: "circle" });
this.append([this.handle]);
this.handle.size = _InvariantHandle.HANDLE_SIZE;
this.handle.strokeWidth = Handle2.INACTIVE_STROKE_WIDTH;
this.handle.zIndex = 2;
}
update(styles) {
this.handle.setProperties({ ...styles, strokeWidth: Handle2.INACTIVE_STROKE_WIDTH });
}
drag(target) {
return { point: target, offset: { x: 0, y: 0 } };
}
};
_InvariantHandle.HANDLE_SIZE = 7;
_InvariantHandle.GLOW_SIZE = 9;
var InvariantHandle = _InvariantHandle;
var _UnivariantHandle = class _UnivariantHandle extends Handle2 {
constructor() {
super();
this.handle = new _ModuleSupport35.Rect();
this.glow = new _ModuleSupport35.Rect();
this.gradient = "horizontal";
this.append([this.glow, this.handle]);
this.handle.cornerRadius = _UnivariantHandle.CORNER_RADIUS;
this.handle.width = _UnivariantHandle.HANDLE_SIZE;
this.handle.height = _UnivariantHandle.HANDLE_SIZE;
this.handle.strokeWidth = Handle2.INACTIVE_STROKE_WIDTH;
this.handle.zIndex = 2;
this.glow.cornerRadius = _UnivariantHandle.CORNER_RADIUS;
this.glow.width = _UnivariantHandle.GLOW_SIZE;
this.glow.height = _UnivariantHandle.GLOW_SIZE;
this.glow.strokeWidth = 0;
this.glow.fillOpacity = 0.2;
this.glow.zIndex = 1;
this.glow.visible = false;
}
toggleLocked(locked) {
super.toggleLocked(locked);
if (locked) {
const offset = (_UnivariantHandle.HANDLE_SIZE - InvariantHandle.HANDLE_SIZE) / 2;
this.handle.cornerRadius = 1;
this.handle.fill = this.handle.stroke;
this.handle.strokeWidth = 0;
this.handle.x += offset;
this.handle.y += offset;
this.handle.width = InvariantHandle.HANDLE_SIZE;
this.handle.height = InvariantHandle.HANDLE_SIZE;
this.glow.width = InvariantHandle.GLOW_SIZE;
this.glow.height = InvariantHandle.GLOW_SIZE;
} else {
this.handle.cornerRadius = _UnivariantHandle.CORNER_RADIUS;
this.handle.width = _UnivariantHandle.HANDLE_SIZE;
this.handle.height = _UnivariantHandle.HANDLE_SIZE;
this.glow.width = _UnivariantHandle.GLOW_SIZE;
this.glow.height = _UnivariantHandle.GLOW_SIZE;
if (this.cachedStyles) {
this.handle.setProperties(this.cachedStyles);
}
}
}
update(styles) {
this.cachedStyles = { ...styles };
if (!this.active) {
delete styles.strokeWidth;
}
if (this.locked) {
delete styles.fill;
delete styles.strokeWidth;
const offset = (_UnivariantHandle.HANDLE_SIZE - InvariantHandle.HANDLE_SIZE) / 2;
styles.x -= offset;
styles.y -= offset;
this.cachedStyles.x -= offset;
this.cachedStyles.y -= offset;
}
this.handle.setProperties(styles);
this.glow.setProperties({
...styles,
x: (styles.x ?? this.glow.x) - 2,
y: (styles.y ?? this.glow.y) - 2,
strokeWidth: 0,
fill: styles.stroke
});
}
drag(target) {
if (this.locked) {
return { point: target, offset: { x: 0, y: 0 } };
}
if (this.gradient === "vertical") {
return {
point: { x: target.x, y: this.handle.y },
offset: { x: target.x - this.handle.x, y: 0 }
};
}
return {
point: { x: this.handle.x, y: target.y },
offset: { x: 0, y: target.y - this.handle.y }
};
}
getCursor() {
if (this.locked)
return;
return this.gradient === "vertical" ? "col-resize" : "row-resize";
}
};
_UnivariantHandle.HANDLE_SIZE = 12;
_UnivariantHandle.GLOW_SIZE = 16;
_UnivariantHandle.CORNER_RADIUS = 4;
var UnivariantHandle = _UnivariantHandle;
var _DivariantHandle = class _DivariantHandle extends Handle2 {
constructor() {
super();
this.handle = new AnnotationShape({ shape: "circle" });
this.glow = new AnnotationShape({ shape: "circle" });
this.append([this.glow, this.handle]);
this.handle.size = _DivariantHandle.HANDLE_SIZE;
this.handle.strokeWidth = Handle2.INACTIVE_STROKE_WIDTH;
this.handle.zIndex = 2;
this.glow.size = _DivariantHandle.GLOW_SIZE;
this.glow.strokeWidth = 0;
this.glow.fillOpacity = 0.2;
this.glow.zIndex = 1;
this.glow.visible = false;
}
toggleLocked(locked) {
super.toggleLocked(locked);
if (locked) {
this.handle.fill = this.handle.stroke;
this.handle.strokeWidth = 0;
this.handle.size = InvariantHandle.HANDLE_SIZE;
this.glow.size = InvariantHandle.GLOW_SIZE;
} else {
this.handle.size = _DivariantHandle.HANDLE_SIZE;
this.glow.size = _DivariantHandle.GLOW_SIZE;
if (this.cachedStyles) {
this.handle.setProperties(this.cachedStyles);
}
}
}
update(styles) {
this.cachedStyles = { ...styles };
if (!this.active) {
delete styles.strokeWidth;
}
if (this.locked) {
delete styles.fill;
delete styles.strokeWidth;
}
this.handle.setProperties(styles);
this.glow.setProperties({ ...styles, strokeWidth: 0, fill: styles.stroke });
}
getCursor() {
return "pointer";
}
};
_DivariantHandle.HANDLE_SIZE = 11;
_DivariantHandle.GLOW_SIZE = 17;
var DivariantHandle = _DivariantHandle;
// packages/ag-charts-enterprise/src/features/annotations/scenes/annotationScene.ts
var AnnotationScene = class extends _ModuleSupport36.Group {
constructor() {
super(...arguments);
this.name = "AnnotationScene";
this.zIndex = ZIndexMap3.CHART_ANNOTATION;
}
static isCheck(value, type) {
return isObject14(value) && Object.hasOwn(value, "type") && value.type === type;
}
toggleHovered(hovered, active, readOnly) {
if (readOnly === true)
return;
this.toggleHandles(hovered || active);
}
computeBBoxWithoutHandles() {
return _ModuleSupport36.Transformable.toCanvas(
this,
_ModuleSupport36.Group.computeChildrenBBox(this.excludeChildren({ instance: Handle2 }))
);
}
updateNode(constructor, node, isConfigured) {
if (!isConfigured && node) {
node.remove();
return;
}
if (isConfigured && node == null) {
node = new constructor();
this.appendChild(node);
}
return node;
}
};
// packages/ag-charts-enterprise/src/features/annotations/scenes/pointScene.ts
import { Vec2 as Vec24 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/utils/coords.ts
import { _ModuleSupport as _ModuleSupport37 } from "ag-charts-community";
import { Vec2 as Vec23, entries, toRadians as toRadians3 } from "ag-charts-core";
var { ContinuousScale: ContinuousScale2 } = _ModuleSupport37;
function snapPoint(offset, context, snapping = false, origin, angleStep = 1) {
if (!snapping)
return invertCoords(offset, context);
const center = origin ? convertPoint(origin, context) : Vec23.origin();
return invertCoords(snapToAngle(offset, center, angleStep), context);
}
function snapToAngle(vector, center, step) {
const radial = Vec23.sub(vector, center);
const stepRadians = toRadians3(step);
const theta = Math.round(Vec23.angle(radial) / stepRadians) * stepRadians;
return Vec23.rotate(radial, theta, center);
}
function getDragStartState(points, context) {
const dragState = {};
for (const [name, point] of entries(points)) {
dragState[name] = convertPoint(point, context);
}
return dragState;
}
function translate(vectors, translation, context, options = {
overflowContinuous: 0,
translateVectors: void 0,
invertYVectors: void 0,
snap: void 0
}) {
const { xAxis, yAxis } = context;
const vectorNames = Object.keys(vectors);
const overflowsX = [];
const overflowsY = [];
const translateVectors = new Set(options.translateVectors ?? vectorNames);
const invertYVectors = new Set(options.invertYVectors ?? []);
const movingVectors = /* @__PURE__ */ new Set([...translateVectors, ...invertYVectors]);
const invertYTranslation = Vec23.multiply(translation, Vec23.from(1, -1));
for (const name of vectorNames) {
if (movingVectors.has(name)) {
vectors[name] = Vec23.add(vectors[name], invertYVectors.has(name) ? invertYTranslation : translation);
if (options.snap) {
vectors[name] = snapToAngle(vectors[name], options.snap.vectors[name], options.snap.angle);
}
}
overflowsX.push(xAxis.getRangeOverflow(vectors[name].x));
overflowsY.push(yAxis.getRangeOverflow(vectors[name].y));
}
const sortNumbersAbs = (a, b) => Math.abs(a) - Math.abs(b);
const overflowDirection = (scale, directionTranslation, overflows) => {
if (options.overflowContinuous === 0 || !ContinuousScale2.is(scale)) {
return overflows.toSorted(sortNumbersAbs).at(-1) ?? 0;
}
if (vectorNames.length === movingVectors.size) {
return overflows.toSorted(sortNumbersAbs).at(-options.overflowContinuous - 1) ?? 0;
}
if (overflows.filter((value) => value !== 0).length <= options.overflowContinuous) {
return 0;
}
const newTranslatedOverflows = overflows.filter(
(value, index) => value !== 0 && Math.abs(value) <= Math.abs(directionTranslation) && movingVectors.has(vectorNames[index])
);
return newTranslatedOverflows.toSorted(sortNumbersAbs).at(-1) ?? 0;
};
const overflow = Vec23.from(
overflowDirection(xAxis.scale, translation.x, overflowsX),
overflowDirection(yAxis.scale, translation.y, overflowsY)
);
if (!Vec23.equal(overflow, Vec23.origin())) {
for (const name of vectorNames) {
if (!movingVectors.has(name))
continue;
vectors[name] = Vec23.round(Vec23.sub(vectors[name], overflow), 4);
}
}
const result = {};
for (const name of vectorNames) {
result[name] = invertCoords(vectors[name], context);
}
return result;
}
// packages/ag-charts-enterprise/src/features/annotations/scenes/pointScene.ts
var PointScene = class extends AnnotationScene {
constructor() {
super(...arguments);
this.handle = new DivariantHandle();
this.anchor = {
x: 0,
y: 0,
position: "above"
};
}
update(datum, context) {
const coords = convertPoint(datum, context);
this.updateHandle(datum, coords);
this.anchor = this.updateAnchor(datum, coords, context);
}
dragStart(datum, target, context) {
this.dragState = {
offset: target,
...getDragStartState({ handle: datum }, context)
};
}
drag(datum, target, context) {
const { dragState } = this;
if (!datum.isWriteable() || !dragState)
return;
const { point } = translate({ point: dragState.handle }, Vec24.sub(target, dragState.offset), context);
datum.x = point.x;
datum.y = point.y;
}
translate(datum, translation, context) {
if (!datum.isWriteable())
return;
const { point } = translate({ point: convertPoint(datum, context) }, translation, context);
datum.x = point.x;
datum.y = point.y;
}
toggleHandles(show) {
this.handle.visible = Boolean(show);
this.handle.toggleHovered(this.activeHandle === "handle");
}
toggleActive(active) {
this.toggleHandles(active);
this.handle.toggleActive(active);
}
stopDragging() {
this.handle.toggleDragging(false);
}
copy(datum, copiedDatum, context) {
const coords = convertPoint(datum, context);
const point = invertCoords({ x: coords.x - 30, y: coords.y - 30 }, context);
copiedDatum.x = point.x;
copiedDatum.y = point.y;
return copiedDatum;
}
getAnchor() {
return this.anchor;
}
getCursor() {
return "pointer";
}
containsPoint(x, y) {
const { handle: handle3 } = this;
this.activeHandle = void 0;
if (handle3.containsPoint(x, y)) {
this.activeHandle = "handle";
return true;
}
return false;
}
getNodeAtCoords(x, y) {
if (this.handle.containsPoint(x, y))
return "handle";
}
updateHandle(datum, point, bbox) {
const { x, y } = this.getHandleCoords(datum, point, bbox);
const styles = this.getHandleStyles(datum);
this.handle.update({ ...styles, x, y });
this.handle.toggleLocked(datum.locked ?? false);
}
updateAnchor(datum, point, context) {
const coords = this.getHandleCoords(datum, point);
return {
x: coords.x + context.seriesRect.x,
y: coords.y + context.seriesRect.y,
position: this.anchor.position
};
}
getHandleCoords(_datum, point, _bbox) {
return {
x: point.x,
y: point.y
};
}
getHandleStyles(datum) {
return {
fill: datum.handle.fill,
stroke: datum.handle.stroke,
strokeOpacity: datum.handle.strokeOpacity,
strokeWidth: datum.handle.strokeWidth
};
}
};
// packages/ag-charts-enterprise/src/features/annotations/scenes/shapePointScene.ts
var ShapePointScene = class extends PointScene {
constructor() {
super();
this.append([this.handle]);
}
update(datum, context) {
super.update(datum, context);
const coords = convertPoint(datum, context);
this.updateShape(datum, coords);
}
updateShape(datum, point) {
this.updateShapeStyles(datum);
this.updateShapePath(datum, point);
}
updateShapeStyles(datum) {
const { shape } = this;
shape.fill = datum.fill;
shape.fillOpacity = datum.fillOpacity ?? 1;
}
updateShapePath(datum, point) {
const { shape } = this;
shape.x = point.x;
shape.y = point.y;
shape.size = datum.size;
}
containsPoint(x, y) {
return super.containsPoint(x, y) || this.shape.containsPoint(x, y);
}
getNodeAtCoords(x, y) {
if (this.shape.containsPoint(x, y))
return "shape";
return super.getNodeAtCoords(x, y);
}
};
// packages/ag-charts-enterprise/src/features/annotations/arrow-up/arrowUpScene.ts
var arrowUpPoints = [
[0.5, 0],
[1, 0.5],
[0.75, 0.5],
[0.75, 1],
[0.25, 1],
[0.25, 0.5],
[0, 0.5]
];
function arrowUp(params) {
_ModuleSupport38.drawMarkerUnitPolygon(params, arrowUpPoints);
}
arrowUp.anchor = { x: 0.5, y: 0 };
var ArrowUpScene = class extends ShapePointScene {
constructor() {
super();
this.type = "arrow-up" /* ArrowUp */;
this.shape = new AnnotationShape({ shape: arrowUp });
this.append([this.shape]);
}
static is(value) {
return AnnotationScene.isCheck(value, "arrow-up" /* ArrowUp */);
}
getHandleCoords(datum, point) {
const halfSize = DivariantHandle.HANDLE_SIZE / 2;
const handleCoords = super.getHandleCoords(datum, point);
handleCoords.y -= halfSize;
return handleCoords;
}
};
// packages/ag-charts-enterprise/src/features/annotations/arrow-down/arrowDownScene.ts
var arrowDownPoints = arrowUpPoints.map(([x, y]) => [x, 1 - y]);
function arrowDown(params) {
_ModuleSupport39.drawMarkerUnitPolygon(params, arrowDownPoints);
}
arrowDown.anchor = { x: 0.5, y: 1 };
var ArrowDownScene = class extends ShapePointScene {
constructor() {
super();
this.type = "arrow-down" /* ArrowDown */;
this.shape = new AnnotationShape({ shape: arrowDown });
this.append([this.shape]);
}
static is(value) {
return AnnotationScene.isCheck(value, "arrow-down" /* ArrowDown */);
}
updateAnchor(datum, point, context) {
const anchor = super.updateAnchor(datum, point, context);
anchor.y -= datum.size;
return anchor;
}
getHandleCoords(datum, point) {
const halfSize = DivariantHandle.HANDLE_SIZE / 2;
const handleCoords = super.getHandleCoords(datum, point);
handleCoords.y += halfSize;
return handleCoords;
}
};
// packages/ag-charts-enterprise/src/features/annotations/states/pointState.ts
import { Debug as Debug2, StateMachine as StateMachine2, StateMachineProperty as StateMachineProperty2 } from "ag-charts-core";
var PointStateMachine = class extends StateMachine2 {
constructor(ctx) {
const actionCreate = ({ point }) => {
const datum = this.createDatum();
datum.set({ x: point.x, y: point.y });
ctx.create(datum);
};
const actionFirstRender = () => {
this.node?.toggleActive(true);
ctx.showAnnotationOptions();
ctx.update();
};
super("start", {
start: {
click: {
target: "waiting-first-render",
action: actionCreate
},
drag: {
target: "waiting-first-render",
action: actionCreate
},
cancel: StateMachine2.parent,
reset: StateMachine2.parent
},
"waiting-first-render": {
render: {
target: StateMachine2.parent,
action: actionFirstRender
}
}
});
this.debug = Debug2.create(true, "annotations");
}
};
__decorateClass([
StateMachineProperty2()
], PointStateMachine.prototype, "node", 2);
// packages/ag-charts-enterprise/src/features/annotations/arrow-down/arrowDownState.ts
var ArrowDownStateMachine = class extends PointStateMachine {
createDatum() {
return new ArrowDownProperties();
}
};
// packages/ag-charts-enterprise/src/features/annotations/arrow-down/arrowDownConfig.ts
var arrowDownConfig = {
type: "arrow-down" /* ArrowDown */,
datum: ArrowDownProperties,
scene: ArrowDownScene,
isDatum: ArrowDownProperties.is,
translate: (node, datum, translation, context) => {
if (ArrowDownProperties.is(datum) && ArrowDownScene.is(node))
node.translate(datum, translation, context);
},
copy: (node, datum, copiedDatum, context) => {
if (ArrowDownProperties.is(datum) && ArrowDownProperties.is(copiedDatum) && ArrowDownScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (ArrowDownProperties.is(datum) && ArrowDownScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new ArrowDownStateMachine({
...ctx,
create: createDatum("arrow-down" /* ArrowDown */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/arrow-up/arrowUpProperties.ts
import { Property as Property34, isObject as isObject15 } from "ag-charts-core";
var ArrowUpProperties = class extends ShapePointProperties {
constructor() {
super(...arguments);
this.type = "arrow-up" /* ArrowUp */;
}
static is(value) {
return isObject15(value) && value.type === "arrow-up" /* ArrowUp */;
}
};
__decorateClass([
Property34
], ArrowUpProperties.prototype, "type", 2);
// packages/ag-charts-enterprise/src/features/annotations/arrow-up/arrowUpState.ts
var ArrowUpStateMachine = class extends PointStateMachine {
createDatum() {
return new ArrowUpProperties();
}
};
// packages/ag-charts-enterprise/src/features/annotations/arrow-up/arrowUpConfig.ts
var arrowUpConfig = {
type: "arrow-up" /* ArrowUp */,
datum: ArrowUpProperties,
scene: ArrowUpScene,
isDatum: ArrowUpProperties.is,
translate: (node, datum, translation, context) => {
if (ArrowUpProperties.is(datum) && ArrowUpScene.is(node))
node.translate(datum, translation, context);
},
copy: (node, datum, copiedDatum, context) => {
if (ArrowUpProperties.is(datum) && ArrowUpProperties.is(copiedDatum) && ArrowUpScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (ArrowUpProperties.is(datum) && ArrowUpScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new ArrowUpStateMachine({
...ctx,
create: createDatum("arrow-up" /* ArrowUp */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/callout/calloutScene.ts
import { _ModuleSupport as _ModuleSupport41 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/features/annotations/scenes/textualStartEndScene.ts
import { _ModuleSupport as _ModuleSupport40 } from "ag-charts-community";
import { Vec4 as Vec43 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/scenes/startEndScene.ts
import { Vec2 as Vec26, Vec4 as Vec42, entries as entries2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/scenes/linearScene.ts
import { Vec2 as Vec25, Vec4 } from "ag-charts-core";
var LinearScene = class extends AnnotationScene {
constructor() {
super(...arguments);
this.overflowContinuous = 0;
}
extendLine({ x1, y1, x2, y2 }, datum, context) {
const linePoints = { x1, y1, x2, y2 };
if (!datum.extendStart && !datum.extendEnd) {
return linePoints;
}
const [left, right] = boundsIntersections(linePoints, context.yAxis.bounds);
const isFlippedX = linePoints.x2 < linePoints.x1;
const isFlippedY = linePoints.y1 >= linePoints.y2;
const isVertical = linePoints.x2 === linePoints.x1;
if (datum.extendEnd) {
if (isVertical) {
linePoints.y2 = isFlippedY ? right.y : left.y;
} else {
linePoints.x2 = isFlippedX ? left.x : right.x;
linePoints.y2 = isFlippedX ? left.y : right.y;
}
}
if (datum.extendStart) {
if (isVertical) {
linePoints.y1 = isFlippedY ? left.y : right.y;
} else {
linePoints.x1 = isFlippedX ? right.x : left.x;
linePoints.y1 = isFlippedX ? right.y : left.y;
}
}
return linePoints;
}
dragStart(datum, target, context) {
this.dragState = {
offset: target,
...getDragStartState({ start: datum.start, end: datum.end }, context)
};
}
drag(datum, target, context, snapping) {
if (!datum.isWriteable())
return;
if (this.activeHandle) {
this.dragHandle(datum, target, context, snapping);
} else {
this.dragAll(datum, target, context);
}
}
dragAll(datum, target, context) {
const { dragState } = this;
if (!dragState)
return;
this.translatePoints(datum, dragState.start, dragState.end, Vec25.sub(target, dragState.offset), context);
}
translate(datum, translation, context) {
if (!datum.isWriteable())
return;
this.translatePoints(
datum,
convertPoint(datum.start, context),
convertPoint(datum.end, context),
translation,
context
);
}
copy(datum, copiedDatum, context) {
const coords = convertLine(datum, context);
if (!coords) {
return;
}
const bbox = this.computeBBoxWithoutHandles();
const translation = { x: -bbox.width / 2, y: -bbox.height / 2 };
this.translatePoints(copiedDatum, Vec4.start(coords), Vec4.end(coords), translation, context);
return copiedDatum;
}
translatePoints(datum, start, end, translation, context) {
const vectors = this.getTranslatePointsVectors(start, end);
const points = translate(vectors, translation, context, {
overflowContinuous: this.overflowContinuous
});
datum.start.x = points.start.x;
datum.end.x = points.end.x;
datum.start.y = points.start.y;
datum.end.y = points.end.y;
}
getTranslatePointsVectors(start, end) {
return { start, end };
}
};
// packages/ag-charts-enterprise/src/features/annotations/scenes/startEndScene.ts
var StartEndScene = class extends LinearScene {
constructor() {
super(...arguments);
this.start = new DivariantHandle();
this.end = new DivariantHandle();
this.anchor = {
x: 0,
y: 0,
position: "above"
};
}
update(datum, context) {
const coords = convertLine(datum, context);
if (coords == null) {
return;
}
this.updateHandles(datum, coords);
this.updateAnchor(datum, coords, context);
}
toggleHandles(show) {
if (typeof show === "boolean") {
this.start.visible = show;
this.end.visible = show;
} else {
for (const [handle3, visible] of entries2(show)) {
this[handle3].visible = visible;
}
}
this.start.toggleHovered(this.activeHandle === "start");
this.end.toggleHovered(this.activeHandle === "end");
}
toggleActive(active) {
this.toggleHandles(active);
this.start.toggleActive(active);
this.end.toggleActive(active);
}
dragHandle(datum, target, context, snapping) {
const { activeHandle, dragState } = this;
if (!activeHandle || !dragState)
return;
this[activeHandle].toggleDragging(true);
const snapHandle = activeHandle === "start" ? "end" : "start";
const snap = snapping ? { vectors: { [activeHandle]: convertPoint(datum[snapHandle], context) }, angle: datum.snapToAngle } : void 0;
const { [activeHandle]: point } = translate(
{ [activeHandle]: dragState[activeHandle] },
Vec26.sub(target, dragState.offset),
context,
{ overflowContinuous: 0, snap }
);
datum[activeHandle].x = point.x;
datum[activeHandle].y = point.y;
}
stopDragging() {
this.start.toggleDragging(false);
this.end.toggleDragging(false);
}
getAnchor() {
return this.anchor;
}
getCursor() {
return "pointer";
}
containsPoint(x, y) {
const { start, end } = this;
this.activeHandle = void 0;
if (start.containsPoint(x, y)) {
this.activeHandle = "start";
return true;
}
if (end.containsPoint(x, y)) {
this.activeHandle = "end";
return true;
}
return false;
}
getNodeAtCoords(x, y) {
if (this.start.containsPoint(x, y) || this.end.containsPoint(x, y))
return "handle";
}
updateHandles(datum, coords, bbox) {
this.start.update({
...this.getHandleStyles(datum, "start"),
...this.getHandleCoords(datum, coords, "start")
});
this.end.update({
...this.getHandleStyles(datum, "end"),
...this.getHandleCoords(datum, coords, "end", bbox)
});
this.start.toggleLocked(datum.locked ?? false);
this.end.toggleLocked(datum.locked ?? false);
}
updateAnchor(_datum, coords, context, _bbox) {
this.anchor = {
x: coords.x1 + context.seriesRect.x,
y: coords.y1 + context.seriesRect.y,
position: this.anchor.position
};
}
getHandleCoords(_datum, coords, handle3, _bbox) {
return handle3 === "start" ? Vec42.start(coords) : Vec42.end(coords);
}
getHandleStyles(datum, _handle) {
return {
fill: datum.handle.fill,
stroke: datum.handle.stroke,
strokeOpacity: datum.handle.strokeOpacity,
strokeWidth: datum.handle.strokeWidth
};
}
};
// packages/ag-charts-enterprise/src/features/annotations/scenes/textualStartEndScene.ts
var TextualStartEndScene = class extends StartEndScene {
constructor() {
super(...arguments);
this.label = new _ModuleSupport40.Text({ zIndex: 1 });
this.anchor = {
x: 0,
y: 0,
position: "above-left"
};
}
setTextInputBBox(bbox) {
this.textInputBBox = bbox;
this.markDirty("TextualStartEndScene");
}
update(datum, context) {
const coords = convertLine(datum, context);
if (coords == null) {
return;
}
const bbox = this.getTextBBox(datum, coords);
this.updateLabel(datum, bbox, coords);
this.updateHandles(datum, coords, bbox);
this.updateShape(datum, bbox, coords);
this.updateAnchor(datum, coords, context, bbox);
}
containsPoint(x, y) {
return super.containsPoint(x, y) || this.label.containsPoint(x, y);
}
getNodeAtCoords(x, y) {
if (this.label.containsPoint(x, y))
return "text";
return super.getNodeAtCoords(x, y);
}
getTextBBox(datum, coords) {
const { text: text2 } = datum.getText();
return getBBox(datum, text2, Vec43.end(coords), this.textInputBBox);
}
updateLabel(datum, bbox, coords) {
const { text: text2, isPlaceholder } = datum.getText();
updateTextNode(this.label, text2, isPlaceholder, datum, this.getLabelCoords(datum, bbox, coords));
}
updateShape(_datum, _textBBox, _coords) {
}
getLabelCoords(_datum, _bbox, coords) {
return Vec43.end(coords);
}
getHandleStyles(datum, handle3) {
return {
...super.getHandleStyles(datum, handle3),
stroke: datum.handle.stroke ?? datum.color
};
}
};
// packages/ag-charts-enterprise/src/features/annotations/callout/calloutScene.ts
var { drawCorner, Path: Path5 } = _ModuleSupport41;
var CalloutScene = class extends TextualStartEndScene {
constructor() {
super();
this.type = "callout" /* Callout */;
this.shape = new Path5();
this.append([this.shape, this.label, this.start, this.end]);
}
static is(value) {
return AnnotationScene.isCheck(value, "callout" /* Callout */);
}
drag(datum, target, context, snapping) {
if (!datum.isWriteable())
return;
if (this.activeHandle === "end") {
this.dragHandle(datum, target, context, snapping);
} else {
this.dragAll(datum, target, context);
}
}
getLabelCoords(datum, bbox, coords) {
const padding2 = datum.getPadding();
const {
bodyBounds = {
x: 0,
y: 0,
width: 0,
height: 0
}
} = this.getDimensions(datum, bbox, coords) ?? {};
return {
x: bodyBounds.x + padding2.left,
y: bodyBounds.y - padding2.bottom
};
}
getHandleStyles(datum, handle3) {
return handle3 === "start" ? {
fill: datum.handle.fill,
stroke: datum.handle.stroke ?? datum.stroke,
strokeOpacity: datum.handle.strokeOpacity,
strokeWidth: datum.handle.strokeWidth
} : { fill: void 0, strokeWidth: 0 };
}
updateAnchor(datum, coords, context, bbox) {
const { bodyBounds } = this.getDimensions(datum, bbox, coords) ?? {};
const bounds = bodyBounds ?? bbox;
this.anchor = {
x: bounds.x + context.seriesRect.x,
y: bounds.y + context.seriesRect.y - bounds.height,
position: this.anchor.position
};
}
updateShape(datum, textBox, coords) {
const { shape } = this;
shape.fill = datum.fill;
shape.fillOpacity = datum.fillOpacity ?? 1;
shape.stroke = datum.stroke;
shape.strokeWidth = datum.strokeWidth ?? 1;
shape.strokeOpacity = datum.strokeOpacity ?? 1;
const { tailPoint, bodyBounds } = this.getDimensions(datum, textBox, coords) ?? {};
if (!tailPoint || !bodyBounds) {
return;
}
this.updatePath(tailPoint, bodyBounds);
}
updatePath(tailPoint, bodyBounds) {
const { x: tailX, y: tailY } = tailPoint;
const { x, y, width, height } = bodyBounds;
const top = y - height;
const right = x + width;
const placement = this.calculateCalloutPlacement({ x: tailX, y: tailY }, bodyBounds);
const cornerRadius = 8;
const pathParams = [
{
coordinates: {
x0: x,
x1: x + cornerRadius,
y0: top + cornerRadius,
y1: top,
cx: placement === `topLeft` ? tailX : x + cornerRadius,
cy: placement === `topLeft` ? tailY : top + cornerRadius
},
type: placement === `topLeft` ? "calloutCorner" : "corner"
},
{
coordinates: {
x0: x + cornerRadius,
x1: right - cornerRadius,
y0: top,
y1: top,
cx: tailX,
cy: tailY
},
type: placement === `top` ? "calloutSide" : "side"
},
{
coordinates: {
x0: right - cornerRadius,
x1: right,
y0: top,
y1: top + cornerRadius,
cx: placement === `topRight` ? tailX : right - cornerRadius,
cy: placement === `topRight` ? tailY : top + cornerRadius
},
type: placement === `topRight` ? "calloutCorner" : "corner"
},
{
coordinates: {
x0: right,
x1: right,
y0: top + cornerRadius,
y1: y - cornerRadius,
cx: tailX,
cy: tailY
},
type: placement === `right` ? "calloutSide" : "side"
},
{
coordinates: {
x0: right,
x1: right - cornerRadius,
y0: y - cornerRadius,
y1: y,
cx: placement === `bottomRight` ? tailX : right - cornerRadius,
cy: placement === `bottomRight` ? tailY : y - cornerRadius
},
type: placement === `bottomRight` ? "calloutCorner" : "corner"
},
{
coordinates: {
x0: right - cornerRadius,
x1: x + cornerRadius,
y0: y,
y1: y,
cx: tailX,
cy: tailY
},
type: placement === `bottom` ? "calloutSide" : "side"
},
{
coordinates: {
x0: x + cornerRadius,
x1: x,
y0: y,
y1: y - cornerRadius,
cx: placement === `bottomLeft` ? tailX : x + cornerRadius,
cy: placement === `bottomLeft` ? tailY : y - cornerRadius
},
type: placement === `bottomLeft` ? "calloutCorner" : "corner"
},
{
coordinates: {
x0: x,
x1: x,
y0: y - cornerRadius,
y1: top + cornerRadius,
cx: tailX,
cy: tailY
},
type: placement === `left` ? "calloutSide" : "side"
}
];
const { path } = this.shape;
path.clear();
path.moveTo(x, top + cornerRadius);
for (const { coordinates, type } of pathParams) {
this.drawPath(path, coordinates, cornerRadius, type);
}
path.closePath();
}
drawPath(path, { x0, y0, x1, y1, cx, cy }, cornerRadius, type) {
const sideTailRadius = 6;
switch (type) {
case "calloutCorner": {
path.lineTo(cx, cy);
path.lineTo(x1, y1);
break;
}
case "corner": {
drawCorner(
path,
{
x0,
x1,
y0,
y1,
cx,
cy
},
cornerRadius,
false
);
break;
}
case "calloutSide": {
if (x0 === x1) {
const direction = y0 > y1 ? -1 : 1;
const midY = Math.min(y0, y1) + Math.abs(y0 - y1) / 2;
path.lineTo(x0, midY - sideTailRadius * direction);
path.lineTo(cx, cy);
path.lineTo(x0, midY + sideTailRadius * direction);
path.lineTo(x1, y1);
} else {
const direction = x0 > x1 ? -1 : 1;
const midX = Math.min(x0, x1) + Math.abs(x1 - x0) / 2;
path.lineTo(midX - sideTailRadius * direction, y0);
path.lineTo(cx, cy);
path.lineTo(midX + sideTailRadius * direction, y0);
path.lineTo(x1, y1);
}
break;
}
case "side":
default: {
path.lineTo(x1, y1);
break;
}
}
}
calculateCalloutPlacement(placement, bounds) {
const right = bounds.x + bounds.width;
const top = bounds.y - bounds.height;
let xPlacement;
let yPlacement;
if (placement.x > right) {
xPlacement = "right";
} else if (placement.x < bounds.x) {
xPlacement = "left";
}
if (placement.y > bounds.y) {
yPlacement = "bottom";
} else if (placement.y < top) {
yPlacement = "top";
}
if (xPlacement && yPlacement) {
return `${yPlacement}${xPlacement[0].toUpperCase()}${xPlacement.substring(1)}`;
} else {
return yPlacement ?? xPlacement;
}
}
getDimensions(datum, textBox, coords) {
const { fontSize } = datum;
const padding2 = datum.getPadding();
const horizontalPadding = padding2.left + padding2.right;
const verticalPadding = padding2.top + padding2.bottom;
const width = textBox.width + horizontalPadding;
const height = Math.max(textBox.height + verticalPadding, fontSize + verticalPadding);
return {
tailPoint: {
x: coords.x1,
y: coords.y1
},
bodyBounds: {
x: textBox.x,
y: textBox.y,
width,
height
}
};
}
containsPoint(x, y) {
const { start, end, shape } = this;
this.activeHandle = void 0;
if (start.containsPoint(x, y)) {
this.activeHandle = "start";
return true;
}
const bodyContainsPoint = end.containsPoint(x, y) || shape.containsPoint(x, y);
if (bodyContainsPoint) {
this.activeHandle = "end";
}
return bodyContainsPoint;
}
};
// packages/ag-charts-enterprise/src/features/annotations/states/textualStartEndState.ts
import "ag-charts-community";
import { Debug as Debug3, StateMachine as StateMachine3, StateMachineProperty as StateMachineProperty3 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/states/textualStateUtils.ts
function guardCancelAndExit({ key }) {
return key === "Escape";
}
function guardSaveAndExit({ key, shiftKey }) {
return !shiftKey && key === "Enter";
}
// packages/ag-charts-enterprise/src/features/annotations/states/textualStartEndState.ts
var TextualStartEndStateMachine = class extends StateMachine3 {
constructor(ctx) {
const actionCreate = ({ point }) => {
const datum = this.createDatum();
datum.set({ start: point, end: point, visible: true });
ctx.create(datum);
};
const actionFirstRender = () => {
const { node } = this;
node?.toggleActive(true);
node?.toggleHandles({ start: true });
};
const onStartEditing = () => {
ctx.showTextInput();
if (this.datum)
this.datum.visible = false;
};
const onStopEditing = () => {
ctx.hideTextInput();
if (this.datum)
this.datum.visible = true;
ctx.deselect();
};
const actionUpdateTextInputBBox = (bbox) => {
this.node?.setTextInputBBox(bbox);
ctx.update();
};
const onEndHover = ({ point }) => {
const { datum, node } = this;
datum?.set({ end: point });
node?.toggleActive(true);
node?.toggleHandles({ end: false });
ctx.update();
};
const onEndClick = () => {
ctx.showAnnotationOptions();
this.node?.toggleHandles({ end: true });
};
const actionColor = ({
colorPickerType,
colorOpacity,
color: color7,
opacity,
isMultiColor
}) => {
const { datum } = this;
if (!datum)
return;
if (colorPickerType === "text-color") {
ctx.updateTextInputColor(color7);
}
setColor(datum, colorPickerType, colorOpacity, color7, opacity, isMultiColor);
ctx.update();
};
const actionFontSize = (fontSize) => {
const { datum, node } = this;
if (!datum || !node || !isTextType(datum))
return;
datum.fontSize = fontSize;
ctx.updateTextInputFontSize(fontSize);
ctx.update();
};
const actionCancel = () => {
ctx.delete();
};
const actionSave = ({ textInputValue, bbox }) => {
const { datum } = this;
if (bbox != null && textInputValue != null && textInputValue.length > 0) {
if (!isTextType(datum)) {
return;
}
const wrappedText = maybeWrapText(datum, textInputValue, bbox.width);
datum?.set({ text: wrappedText });
ctx.update();
ctx.recordAction(`Create ${datum?.type} annotation`);
} else {
ctx.delete();
}
};
super("start", {
start: {
click: {
target: "waiting-first-render",
action: actionCreate
},
dragStart: {
target: "waiting-first-render",
action: actionCreate
},
cancel: StateMachine3.parent,
reset: StateMachine3.parent
},
"waiting-first-render": {
render: {
target: "end",
action: actionFirstRender
}
},
end: {
hover: onEndHover,
drag: onEndHover,
click: {
target: "edit",
action: onEndClick
},
dragEnd: {
target: "edit",
action: onEndClick
},
reset: {
target: StateMachine3.parent,
action: actionCancel
},
cancel: {
target: StateMachine3.parent,
action: actionCancel
}
},
edit: {
onEnter: onStartEditing,
updateTextInputBBox: actionUpdateTextInputBBox,
color: actionColor,
fontSize: actionFontSize,
textInput: [
{
guard: guardCancelAndExit,
target: StateMachine3.parent,
action: actionCancel
},
{
guard: guardSaveAndExit,
target: StateMachine3.parent,
action: actionSave
}
],
click: {
target: StateMachine3.parent,
action: actionSave
},
dragStart: {
target: StateMachine3.parent,
action: actionSave
},
resize: {
target: StateMachine3.parent,
action: actionSave
},
onExit: onStopEditing,
cancel: {
target: StateMachine3.parent,
action: actionCancel
}
}
});
this.debug = Debug3.create(true, "annotations");
}
};
__decorateClass([
StateMachineProperty3()
], TextualStartEndStateMachine.prototype, "datum", 2);
__decorateClass([
StateMachineProperty3()
], TextualStartEndStateMachine.prototype, "node", 2);
// packages/ag-charts-enterprise/src/features/annotations/callout/calloutState.ts
var CalloutStateMachine = class extends TextualStartEndStateMachine {
createDatum() {
return new CalloutProperties();
}
};
// packages/ag-charts-enterprise/src/features/annotations/callout/calloutConfig.ts
var calloutConfig = {
type: "callout" /* Callout */,
datum: CalloutProperties,
scene: CalloutScene,
isDatum: CalloutProperties.is,
translate: (node, datum, transition, context) => {
if (CalloutProperties.is(datum) && CalloutScene.is(node))
return node.translate(datum, transition, context);
},
copy: (node, datum, copiedDatum, context) => {
if (CalloutProperties.is(datum) && CalloutProperties.is(copiedDatum) && CalloutScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (CalloutProperties.is(datum) && CalloutScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new CalloutStateMachine({
...ctx,
create: createDatum("callout" /* Callout */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/comment/commentScene.ts
import { _ModuleSupport as _ModuleSupport44 } from "ag-charts-community";
import { calcLineHeight as calcLineHeight2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/scenes/textualPointScene.ts
import { _ModuleSupport as _ModuleSupport43 } from "ag-charts-community";
var TextualPointScene = class extends PointScene {
constructor() {
super(...arguments);
this.label = new _ModuleSupport43.Text({ zIndex: 1 });
this.anchor = {
x: 0,
y: 0,
position: "above-left"
};
}
setTextInputBBox(bbox) {
this.textInputBBox = bbox;
this.markDirty("TextualPointScene");
}
update(datum, context) {
const coords = convertPoint(datum, context);
const bbox = this.getTextBBox(datum, coords, context);
this.updateLabel(datum, bbox);
this.updateHandle(datum, coords, bbox);
this.updateShape(datum, bbox);
this.anchor = this.updateAnchor(datum, bbox, context);
}
copy(datum, copiedDatum, context) {
const coords = convertPoint(datum, context);
const bbox = this.getTextBBox(datum, coords, context);
const padding2 = datum.getPadding();
const horizontalPadding = padding2.left + padding2.right;
const verticalPadding = padding2.top + padding2.bottom;
const xOffset = (bbox.width + horizontalPadding) / 2;
const yOffset = bbox.height + verticalPadding;
const point = invertCoords({ x: coords.x - xOffset, y: coords.y - yOffset }, context);
copiedDatum.x = point.x;
copiedDatum.y = point.y;
return copiedDatum;
}
containsPoint(x, y) {
const { label } = this;
return super.containsPoint(x, y) || label.visible && label.containsPoint(x, y);
}
getNodeAtCoords(x, y) {
if (this.label.visible && this.label.containsPoint(x, y))
return "text";
return super.getNodeAtCoords(x, y);
}
getTextBBox(datum, coords, _context) {
const { text: text2 } = datum.getText();
return getBBox(datum, text2, { x: coords.x, y: coords.y }, this.textInputBBox);
}
updateLabel(datum, bbox) {
const { text: text2, isPlaceholder } = datum.getText();
updateTextNode(
this.label,
text2,
isPlaceholder,
datum,
this.getLabelCoords(datum, bbox),
this.getTextBaseline(datum)
);
}
updateShape(_datum, _bbox) {
}
updateAnchor(_datum, bbox, context) {
return {
x: bbox.x + context.seriesRect.x,
y: bbox.y + context.seriesRect.y - bbox.height,
position: this.anchor.position
};
}
getLabelCoords(_datum, bbox) {
return bbox;
}
getTextBaseline(datum) {
return datum.position == "center" ? "middle" : datum.position;
}
getHandleCoords(_datum, _coords, bbox) {
return bbox;
}
getHandleStyles(datum) {
const styles = super.getHandleStyles(datum);
styles.stroke = datum.handle.stroke ?? datum.color;
return styles;
}
};
// packages/ag-charts-enterprise/src/features/annotations/comment/commentScene.ts
var { drawCorner: drawCorner2 } = _ModuleSupport44;
var CommentScene = class extends TextualPointScene {
constructor() {
super();
this.type = "comment" /* Comment */;
this.shape = new _ModuleSupport44.Path();
this.append([this.shape, this.label, this.handle]);
}
static is(value) {
return AnnotationScene.isCheck(value, "comment" /* Comment */);
}
updateShape(datum, bbox) {
const { shape } = this;
shape.fill = datum.fill;
shape.fillOpacity = datum.fillOpacity ?? 1;
shape.stroke = datum.stroke ?? "transparent";
shape.strokeWidth = datum.strokeWidth ?? 1;
shape.strokeOpacity = datum.strokeOpacity ?? 1;
this.updatePath(datum, bbox);
}
getLabelCoords(datum, point) {
const padding2 = datum.getPadding();
return {
x: point.x + padding2.left,
y: point.y - padding2.bottom
};
}
getHandleStyles(datum) {
return {
fill: datum.handle.fill,
stroke: datum.handle.stroke ?? datum.stroke ?? datum.fill,
strokeOpacity: datum.handle.strokeOpacity,
strokeWidth: datum.handle.strokeWidth
};
}
updateAnchor(datum, bbox, context) {
const anchor = super.updateAnchor(datum, bbox, context);
const padding2 = datum.getPadding();
anchor.y -= padding2.bottom + padding2.top;
return anchor;
}
updatePath(datum, bbox) {
const padding2 = datum.getPadding();
const { x, y } = bbox;
let { width, height } = bbox;
const { fontSize } = datum;
const horizontalPadding = padding2.left + padding2.right;
const verticalPadding = padding2.top + padding2.bottom;
width = width + horizontalPadding;
height = Math.max(height + verticalPadding, fontSize + verticalPadding);
const top = y - height;
const right = x + width;
const cornerRadius = (calcLineHeight2(fontSize, ANNOTATION_TEXT_LINE_HEIGHT) + verticalPadding) / 2;
const { path } = this.shape;
path.clear();
path.moveTo(x, y);
path.lineTo(x, top + cornerRadius);
drawCorner2(
path,
{
x0: x,
x1: x + cornerRadius,
y0: top + cornerRadius,
y1: top,
cx: x + cornerRadius,
cy: top + cornerRadius
},
cornerRadius,
false
);
path.lineTo(right - cornerRadius, top);
drawCorner2(
path,
{
x0: right - cornerRadius,
x1: right,
y0: top,
y1: top + cornerRadius,
cx: right - cornerRadius,
cy: top + cornerRadius
},
cornerRadius,
false
);
path.lineTo(right, y - cornerRadius);
drawCorner2(
path,
{
x0: right,
x1: right - cornerRadius,
y0: y - cornerRadius,
y1: y,
cx: right - cornerRadius,
cy: y - cornerRadius
},
cornerRadius,
false
);
path.closePath();
}
containsPoint(x, y) {
return super.containsPoint(x, y) || this.shape.containsPoint(x, y);
}
};
// packages/ag-charts-enterprise/src/features/annotations/states/textualPointState.ts
import "ag-charts-community";
import { Debug as Debug4, StateMachine as StateMachine4, StateMachineProperty as StateMachineProperty4 } from "ag-charts-core";
var TextualPointStateMachine = class extends StateMachine4 {
constructor(ctx) {
const actionCreate = ({ point }) => {
const datum = this.createDatum();
datum.set({ x: point.x, y: point.y });
ctx.create(datum);
};
const actionFirstRender = () => {
this.node?.toggleActive(true);
ctx.showAnnotationOptions();
ctx.update();
};
const onStartEditing = () => {
ctx.showTextInput();
if (this.datum) {
this.datum.visible = false;
}
};
const onStopEditing = () => {
ctx.hideTextInput();
if (this.datum)
this.datum.visible = true;
ctx.deselect();
};
const actionUpdateTextInputBBox = (bbox) => {
this.node?.setTextInputBBox(bbox);
ctx.update();
};
const actionColor = ({
colorPickerType,
colorOpacity,
color: color7,
opacity,
isMultiColor
}) => {
if (!this.datum)
return;
if (colorPickerType === "text-color") {
ctx.updateTextInputColor(color7);
}
setColor(this.datum, colorPickerType, colorOpacity, color7, opacity, isMultiColor);
ctx.update();
};
const actionFontSize = (fontSize) => {
const { datum, node } = this;
if (!datum || !node || !isTextType(datum))
return;
datum.fontSize = fontSize;
ctx.updateTextInputFontSize(fontSize);
ctx.update();
};
const actionCancel = () => {
ctx.delete();
};
const actionSave = ({ textInputValue, bbox }) => {
if (bbox != null && textInputValue != null && textInputValue.length > 0) {
const { datum } = this;
if (!isTextType(datum)) {
return;
}
const wrappedText = maybeWrapText(datum, textInputValue, bbox.width);
datum?.set({ text: wrappedText });
ctx.update();
ctx.recordAction(`Create ${datum?.type} annotation`);
} else {
ctx.delete();
}
};
super("start", {
start: {
click: {
target: "waiting-first-render",
action: actionCreate
},
dragStart: {
target: "waiting-first-render",
action: actionCreate
},
cancel: StateMachine4.parent,
reset: StateMachine4.parent
},
"waiting-first-render": {
render: {
target: "edit",
action: actionFirstRender
}
},
edit: {
onEnter: onStartEditing,
updateTextInputBBox: actionUpdateTextInputBBox,
color: actionColor,
fontSize: actionFontSize,
textInput: [
{
guard: guardCancelAndExit,
target: StateMachine4.parent,
action: actionCancel
},
{
guard: guardSaveAndExit,
target: StateMachine4.parent,
action: actionSave
}
],
click: {
target: StateMachine4.parent,
action: actionSave
},
dragStart: {
target: StateMachine4.parent,
action: actionSave
},
resize: {
target: StateMachine4.parent,
action: actionSave
},
onExit: onStopEditing,
cancel: {
target: StateMachine4.parent,
action: actionCancel
}
}
});
this.debug = Debug4.create(true, "annotations");
}
};
__decorateClass([
StateMachineProperty4()
], TextualPointStateMachine.prototype, "datum", 2);
__decorateClass([
StateMachineProperty4()
], TextualPointStateMachine.prototype, "node", 2);
// packages/ag-charts-enterprise/src/features/annotations/comment/commentState.ts
var CommentStateMachine = class extends TextualPointStateMachine {
createDatum() {
return new CommentProperties();
}
};
// packages/ag-charts-enterprise/src/features/annotations/comment/commentConfig.ts
var commentConfig = {
type: "comment" /* Comment */,
datum: CommentProperties,
scene: CommentScene,
isDatum: CommentProperties.is,
translate: (node, datum, translation, context) => {
if (CommentProperties.is(datum) && CommentScene.is(node))
node.translate(datum, translation, context);
},
copy: (node, datum, copiedDatum, context) => {
if (CommentProperties.is(datum) && CommentProperties.is(copiedDatum) && CommentScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (CommentProperties.is(datum) && CommentScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new CommentStateMachine({
...ctx,
create: createDatum("comment" /* Comment */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/cross-line/crossLineScene.ts
import "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection6, Vec2 as Vec29, Vec4 as Vec44 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/scenes/axisLabelScene.ts
import { _ModuleSupport as _ModuleSupport46 } from "ag-charts-community";
var { calculateLabelTranslation } = _ModuleSupport46;
var AxisLabelScene = class extends _ModuleSupport46.Group {
constructor() {
super({ name: "AnnotationAxisLabelGroup" });
this.label = new _ModuleSupport46.Text({ zIndex: 1 });
this.rect = new _ModuleSupport46.Rect();
const { label } = this;
label.fontSize = 12;
label.fontFamily = "Verdana, sans-serif";
label.fill = "black";
label.textBaseline = "middle";
label.textAlign = "center";
this.append([this.rect, this.label]);
}
update(opts) {
this.updateLabel(opts);
this.updateRect(opts);
this.updatePosition(opts);
}
updateLabel({ value, styles, context }) {
const { fontWeight, fontSize, fontStyle, fontFamily, textAlign, color: color7 = "white", formatter } = styles;
const text2 = formatter ? formatter({ value }) : context.formatScaleValue(value, "annotation-label");
this.label.setProperties({
fontWeight,
fontSize,
fontStyle,
fontFamily,
textAlign,
fill: color7,
text: text2
});
}
updateRect({ styles }) {
const { rect } = this;
const { cornerRadius, fill, fillOpacity, stroke: stroke3, strokeOpacity } = styles;
rect.fill = fill;
rect.fillOpacity = fillOpacity ?? 1;
rect.stroke = stroke3;
rect.strokeOpacity = strokeOpacity ?? 1;
rect.cornerRadius = cornerRadius ?? 0;
}
updatePosition({ x, y, context, styles: { padding: padding2 } }) {
const { label, rect } = this;
const labelBBox = label.getBBox()?.clone();
const horizontalPadding = padding2 ?? 8;
const verticalPadding = padding2 ?? 4;
const { xTranslation, yTranslation } = calculateLabelTranslation({
yDirection: true,
padding: context.labelPadding,
position: context.position ?? "left",
bbox: labelBBox
});
labelBBox.grow(horizontalPadding, "horizontal");
labelBBox.grow(verticalPadding, "vertical");
const translationX = x + xTranslation;
const translationY = y + yTranslation;
label.x = translationX;
label.y = translationY;
rect.y = translationY - Math.round(labelBBox.height / 2);
rect.x = translationX - Math.round(labelBBox.width / 2);
rect.height = labelBBox.height;
rect.width = labelBBox.width;
}
};
AxisLabelScene.className = "AxisLabel";
// packages/ag-charts-enterprise/src/features/annotations/scenes/collidableLineScene.ts
import { _ModuleSupport as _ModuleSupport47 } from "ag-charts-community";
import { Vec2 as Vec27, jsonDiff } from "ag-charts-core";
var CollidableLine = class extends _ModuleSupport47.Line {
constructor() {
super(...arguments);
this.growCollisionBox = 9;
this.clipMask = /* @__PURE__ */ new Map();
}
setProperties(styles) {
super.setProperties(styles);
this.updateCollisionBBox();
return this;
}
updateCollisionBBox() {
const { growCollisionBox, strokeWidth, x1, y1, x2, y2 } = this;
let height = strokeWidth + growCollisionBox;
if (height % 2 === 0)
height += 1;
const topLeft = Vec27.from(x1, y1 - Math.floor(height / 2));
const bottomRight = Vec27.from(x2, y2);
const width = Vec27.distance(topLeft, bottomRight);
this.collisionBBox = new _ModuleSupport47.BBox(topLeft.x, topLeft.y, width, height);
}
isPointInPath(pointX, pointY) {
const { collisionBBox, x1, y1, x2, y2 } = this;
if (!collisionBBox)
return false;
const v1 = Vec27.from(x1, y1);
const v2 = Vec27.from(x2, y2);
const point = Vec27.sub(Vec27.from(pointX, pointY), v1);
const end = Vec27.sub(v2, v1);
const rotated = Vec27.rotate(point, Vec27.angle(point, end), v1);
return collisionBBox.containsPoint(rotated.x, rotated.y) ?? false;
}
render(renderCtx) {
const { clipMask } = this;
const { ctx } = renderCtx;
if (clipMask.size === 0) {
super.render(renderCtx);
return;
}
ctx.save();
try {
for (const mask of this.clipMask.values()) {
const { x, y, radius } = mask;
ctx.beginPath();
ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.ellipse(x, y, radius, radius, 0, Math.PI * 2, 0, true);
ctx.clip();
}
super.render(renderCtx);
} finally {
ctx.restore();
}
}
setClipMask(id, mask) {
const cm = this.clipMask.get(id);
if (jsonDiff(cm, mask) != null) {
this.markDirty("CollidableLine");
}
if (mask) {
this.clipMask.set(id, mask);
} else {
this.clipMask.delete(id);
}
}
};
// packages/ag-charts-enterprise/src/features/annotations/scenes/collidableTextScene.ts
import { _ModuleSupport as _ModuleSupport48 } from "ag-charts-community";
var CollidableText = class extends _ModuleSupport48.TransformableText {
constructor() {
super(...arguments);
this.growCollisionBox = {
top: 4,
right: 4,
bottom: 4,
left: 4
};
}
isPointInPath(pointX, pointY) {
const localPoint = this.fromParentPoint(pointX, pointY);
const uBBox = this.computeBBoxWithoutTransforms();
if (!uBBox)
return false;
return uBBox.grow(this.growCollisionBox).containsPoint(localPoint.x, localPoint.y);
}
};
// packages/ag-charts-enterprise/src/features/annotations/utils/lineWithText.ts
import { Vec2 as Vec28 } from "ag-charts-core";
function updateLineText(id, line, coords, textProperties, textNode, text2, lineWidth) {
if (!text2 || !textNode || !textProperties) {
line.setClipMask(id);
return;
}
const { alignment, position } = textProperties;
const numbers = getNumbers(coords, textProperties.fontSize, lineWidth);
const { point, textBaseline } = positionAndAlignment(numbers, position, alignment);
setProperties(textNode, text2, textProperties, point, numbers.angle, textBaseline);
const { x, y, width, height } = textNode.getBBox();
const diameter = Vec28.length(Vec28.from(width, height));
const clipMask = {
x: x + width / 2,
y: y + height / 2,
radius: diameter / 2 + Vec28.length(numbers.offset)
};
if (position === "center") {
line.setClipMask(id, clipMask);
} else {
line.setClipMask(id);
}
return { clipMask, numbers };
}
function updateChannelText(offsetInsideTextLabel, top, bottom, textProperties, lineWidth, textNode, text2) {
if (!text2 || !textNode)
return;
const { alignment, position } = textProperties;
const [actualTop, actualBottom] = top.y1 <= bottom.y1 ? [top, bottom] : [bottom, top];
let relativeLine = actualTop;
if (position === "bottom") {
relativeLine = actualBottom;
} else if (position === "inside") {
relativeLine = {
x1: (actualTop.x1 + actualBottom.x1) / 2,
y1: (actualTop.y1 + actualBottom.y1) / 2,
x2: (actualTop.x2 + actualBottom.x2) / 2,
y2: (actualTop.y2 + actualBottom.y2) / 2
};
}
const numbers = getNumbers(relativeLine, textProperties.fontSize, lineWidth);
const { point, textBaseline } = positionAndAlignment(
numbers,
position === "inside" ? "center" : position,
alignment,
offsetInsideTextLabel
);
setProperties(textNode, text2, textProperties, point, numbers.angle, textBaseline);
}
function getNumbers(coords, fontSize, strokeWidth) {
let [left, right] = Vec28.from(coords);
if (left.x > right.x)
[left, right] = [right, left];
const normal = Vec28.normalized(Vec28.sub(right, left));
const angle = Vec28.angle(normal);
const inset = Vec28.multiply(normal, DivariantHandle.HANDLE_SIZE / 2 + (fontSize ?? 14) / 2);
const offset = Vec28.multiply(normal, (strokeWidth ?? 2) / 2 + (fontSize ?? 14) / 3);
return { left, right, normal, angle, inset, offset };
}
function positionAndAlignment({ left, right, normal, angle, inset, offset }, position, alignment, offsetInsideTextLabel) {
let point;
if (alignment === "right") {
point = Vec28.sub(right, inset);
} else if (alignment === "center") {
point = Vec28.add(left, Vec28.multiply(normal, Vec28.distance(left, right) / 2));
} else {
point = Vec28.add(left, inset);
}
let textBaseline = "bottom";
if (position === "bottom") {
point = Vec28.rotate(offset, angle + Math.PI / 2, point);
textBaseline = "top";
} else if (position === "center" && !offsetInsideTextLabel) {
textBaseline = "middle";
} else {
point = Vec28.rotate(offset, angle - Math.PI / 2, point);
}
return { point, textBaseline };
}
function setProperties(scene, text2, textProperties, point, angle, textBaseline) {
scene.setProperties({
text: text2,
x: point.x,
y: point.y,
rotation: angle,
rotationCenterX: point.x,
rotationCenterY: point.y,
fill: textProperties.color,
fontFamily: textProperties.fontFamily,
fontSize: textProperties.fontSize,
fontStyle: textProperties.fontStyle,
fontWeight: textProperties.fontWeight,
textAlign: textProperties.alignment,
textBaseline
});
}
// packages/ag-charts-enterprise/src/features/annotations/cross-line/crossLineScene.ts
var CrossLineScene = class extends AnnotationScene {
constructor() {
super();
this.type = "cross-line";
this.line = new CollidableLine();
this.middle = new UnivariantHandle();
this.isHorizontal = false;
this.append([this.line, this.middle]);
}
static is(value) {
return AnnotationScene.isCheck(value, "cross-line");
}
update(datum, context) {
const { seriesRect } = context;
this.seriesRect = seriesRect;
this.isHorizontal = HorizontalLineProperties.is(datum);
const axisContext = this.isHorizontal ? context.yAxis : context.xAxis;
const coords = this.convertCrossLine(datum, axisContext);
if (coords == null) {
this.visible = false;
return;
}
this.visible = datum.visible ?? true;
if (!this.visible)
return;
this.updateLine(datum, coords);
this.updateHandle(datum, coords);
this.updateText(datum, coords);
this.updateAxisLabel(datum, axisContext, coords);
}
updateLine(datum, coords) {
const { line } = this;
const { lineDashOffset, stroke: stroke3, strokeWidth, strokeOpacity } = datum;
const { x1, y1, x2, y2 } = coords;
line.setProperties({
x1,
y1,
x2,
y2,
lineCap: datum.getLineCap(),
lineDash: datum.getLineDash(),
lineDashOffset,
stroke: stroke3,
strokeWidth,
strokeOpacity,
fillOpacity: 0
});
}
updateHandle(datum, coords) {
const { middle } = this;
const { locked, stroke: stroke3, strokeWidth, strokeOpacity } = datum;
const handleStyles = {
fill: datum.handle.fill,
stroke: datum.handle.stroke ?? stroke3,
strokeOpacity: datum.handle.strokeOpacity ?? strokeOpacity,
strokeWidth: datum.handle.strokeWidth ?? strokeWidth
};
const handlePosition = Vec29.sub(
Vec44.center(coords),
Vec29.from(middle.handle.width / 2, middle.handle.height / 2)
);
middle.gradient = this.isHorizontal ? "horizontal" : "vertical";
middle.update({ ...handleStyles, ...handlePosition });
middle.toggleLocked(locked ?? false);
}
updateText(datum, coords) {
this.text = this.updateNode(CollidableText, this.text, !!datum.text.label);
updateLineText(this.line.id, this.line, coords, datum.text, this.text, datum.text.label, datum.strokeWidth);
}
createAxisLabel(context) {
const axisLabel3 = new AxisLabelScene();
context.attachLabel(axisLabel3);
return axisLabel3;
}
updateAxisLabel(datum, axisContext, coords) {
this.axisLabel ?? (this.axisLabel = this.createAxisLabel(axisContext));
const { axisLabel: axisLabel3, seriesRect } = this;
const { direction, position } = axisContext;
if (datum.axisLabel.enabled) {
axisLabel3.visible = this.visible;
const labelCorner = position === "left" || position === "top" ? Vec44.start(coords) : Vec44.end(coords);
const labelPosition = direction === ChartAxisDirection6.X ? labelCorner.x : labelCorner.y;
if (!axisContext.inRange(labelPosition)) {
axisLabel3.visible = false;
return;
}
const value = getGroupingValue(datum.value);
axisLabel3.update({
...Vec29.add(labelCorner, Vec29.required(seriesRect)),
value,
styles: datum.axisLabel,
context: axisContext
});
} else {
axisLabel3.visible = false;
}
}
setAxisLabelOpacity(opacity) {
if (!this.axisLabel)
return;
this.axisLabel.opacity = opacity;
}
setAxisLabelVisible(visible) {
if (!this.axisLabel)
return;
this.axisLabel.visible = visible;
}
toggleHandles(show) {
this.middle.visible = show;
this.middle.toggleHovered(this.activeHandle === "middle");
}
destroy() {
super.destroy();
this.axisLabel?.destroy();
}
toggleActive(active) {
this.toggleHandles(active);
this.middle.toggleActive(active);
}
dragStart(datum, target, context) {
const middle = HorizontalLineProperties.is(datum) ? { x: target.x, y: convert(datum.value, context.yAxis) } : { x: convert(datum.value, context.xAxis), y: target.y };
this.dragState = {
offset: target,
middle
};
}
drag(datum, target, context) {
const { activeHandle, dragState } = this;
if (!datum.isWriteable() || !dragState)
return;
if (activeHandle) {
this[activeHandle].toggleDragging(true);
}
this.translatePoint(datum, dragState.middle, Vec29.sub(target, dragState.offset), context);
}
translate(datum, translation, context) {
if (!datum.isWriteable())
return;
const vector = HorizontalLineProperties.is(datum) ? Vec29.from(0, convert(datum.value, context.yAxis)) : Vec29.from(convert(datum.value, context.xAxis), 0);
this.translatePoint(datum, vector, translation, context);
}
translatePoint(datum, value, translation, context) {
const isHorizontal2 = HorizontalLineProperties.is(datum);
if (isHorizontal2) {
translation.x = 0;
} else {
translation.y = 0;
}
const { point } = translate({ point: value }, translation, context);
datum.value = isHorizontal2 ? point.y : point.x;
}
stopDragging() {
this.middle.toggleDragging(false);
}
copy(datum, copiedDatum, context) {
const isHorizontal2 = HorizontalLineProperties.is(datum);
const axisContext = this.isHorizontal ? context.yAxis : context.xAxis;
const coords = this.convertCrossLine(datum, axisContext);
if (!coords) {
return;
}
const yOffset = isHorizontal2 ? -30 : 0;
const xOffset = isHorizontal2 ? 0 : -30;
const point = invertCoords({ x: coords.x1 + xOffset, y: coords.y1 + yOffset }, context);
copiedDatum.set({ value: isHorizontal2 ? point.y : point.x });
return copiedDatum;
}
getCursor() {
if (this.activeHandle == null)
return "pointer";
return this[this.activeHandle].getCursor();
}
containsPoint(x, y) {
const { middle, line, text: text2 } = this;
this.activeHandle = void 0;
if (middle.containsPoint(x, y)) {
this.activeHandle = "middle";
return true;
}
return line.isPointInPath(x, y) || Boolean(text2?.containsPoint(x, y));
}
getNodeAtCoords(x, y) {
if (this.text?.containsPoint(x, y))
return "text";
if (this.line.isPointInPath(x, y))
return "line";
if (this.middle.containsPoint(x, y))
return "handle";
}
getAnchor() {
const bbox = this.computeBBoxWithoutHandles();
if (this.isHorizontal) {
return { x: bbox.x + bbox.width / 2, y: bbox.y };
}
return { x: bbox.x + bbox.width, y: bbox.y + bbox.height / 2, position: "right" };
}
convertCrossLine(datum, context) {
if (datum.value == null)
return;
let x1 = 0;
let y1 = 0;
let x2, y2;
const { bounds } = context;
const scaledValue = convert(datum.value, context);
if (HorizontalLineProperties.is(datum)) {
x2 = bounds.width;
y1 = scaledValue;
y2 = scaledValue;
} else {
x1 = scaledValue;
x2 = scaledValue;
y2 = bounds.height;
}
return { x1, y1, x2, y2 };
}
};
// packages/ag-charts-enterprise/src/features/annotations/cross-line/crossLineState.ts
import "ag-charts-community";
import { Debug as Debug5, StateMachine as StateMachine5, StateMachineProperty as StateMachineProperty5 } from "ag-charts-core";
var CrossLineStateMachine = class extends StateMachine5 {
constructor(direction, ctx) {
const onClick = ({ point }) => {
const isHorizontal2 = direction === "horizontal";
const datum = isHorizontal2 ? new HorizontalLineProperties() : new VerticalLineProperties();
datum.set({ value: isHorizontal2 ? point.y : point.x });
ctx.create(datum);
ctx.recordAction(
`Create ${isHorizontal2 ? "horizontal-line" /* HorizontalLine */ : "vertical-line" /* VerticalLine */} annotation`
);
};
const actionFirstRender = () => {
this.node?.toggleActive(true);
ctx.showAnnotationOptions();
ctx.update();
};
super("start", {
start: {
click: {
target: "waiting-first-render",
action: onClick
},
drag: {
target: "waiting-first-render",
action: onClick
},
reset: StateMachine5.parent,
cancel: StateMachine5.parent
},
"waiting-first-render": {
render: {
target: StateMachine5.parent,
action: actionFirstRender
}
}
});
this.debug = Debug5.create(true, "annotations");
}
};
__decorateClass([
StateMachineProperty5()
], CrossLineStateMachine.prototype, "node", 2);
// packages/ag-charts-enterprise/src/features/annotations/cross-line/crossLineConfig.ts
var horizontalLineConfig = {
type: "horizontal-line" /* HorizontalLine */,
datum: HorizontalLineProperties,
scene: CrossLineScene,
isDatum: HorizontalLineProperties.is,
translate: (node, datum, translation, context) => {
if (HorizontalLineProperties.is(datum) && CrossLineScene.is(node))
node.translate(datum, translation, context);
},
copy: (node, datum, copiedDatum, context) => {
if (HorizontalLineProperties.is(datum) && HorizontalLineProperties.is(copiedDatum) && CrossLineScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (HorizontalLineProperties.is(datum) && CrossLineScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new CrossLineStateMachine("horizontal", {
...ctx,
create: createDatum("horizontal-line" /* HorizontalLine */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
var verticalLineConfig = {
type: "vertical-line" /* VerticalLine */,
datum: VerticalLineProperties,
scene: CrossLineScene,
isDatum: VerticalLineProperties.is,
translate: (node, datum, translation, context) => {
if (VerticalLineProperties.is(datum) && CrossLineScene.is(node))
node.translate(datum, translation, context);
},
copy: (node, datum, copiedDatum, context) => {
if (VerticalLineProperties.is(datum) && VerticalLineProperties.is(copiedDatum) && CrossLineScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (VerticalLineProperties.is(datum) && CrossLineScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new CrossLineStateMachine("vertical", {
...ctx,
create: createDatum("vertical-line" /* VerticalLine */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/disjoint-channel/disjointChannelScene.ts
import { Vec2 as Vec210, Vec4 as Vec46 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/scenes/channelScene.ts
import { _ModuleSupport as _ModuleSupport50 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/features/annotations/scenes/withBackgroundScene.ts
import { Vec4 as Vec45 } from "ag-charts-core";
var WithBackgroundScene = class {
static updateBackground(datum, top, bottom, context) {
const { background } = this;
const { seriesRect } = context;
background.path.clear(true);
const bounds = Vec45.from(0, 0, seriesRect.width, seriesRect.height);
const points = this.getBackgroundPoints(datum, top, bottom, bounds);
for (let i = 0; i < points.length; i++) {
const point = points[i];
if (i === 0) {
background.path.moveTo(point.x, point.y);
} else {
background.path.lineTo(point.x, point.y);
}
}
background.path.closePath();
background.checkPathDirty();
const backgroundStyles = this.getBackgroundStyles?.(datum) ?? datum.background;
background.fill = backgroundStyles.fill;
background.fillOpacity = backgroundStyles.fillOpacity ?? 1;
}
};
// packages/ag-charts-enterprise/src/features/annotations/scenes/channelScene.ts
var ChannelScene = class extends LinearScene {
constructor() {
super(...arguments);
this.handles = {};
this.overflowContinuous = 2;
this.topLine = new CollidableLine();
this.bottomLine = new CollidableLine();
this.background = new _ModuleSupport50.Path({ zIndex: -1 });
this.anchor = { x: 0, y: 0 };
this.updateBackground = WithBackgroundScene.updateBackground.bind(this);
}
update(datum, context) {
const { locked, visible } = datum;
const top = convertLine(datum, context);
const bottom = convertLine(datum.bottom, context);
if (top == null || bottom == null) {
this.visible = false;
return;
} else {
this.visible = visible ?? true;
}
const topLine = this.extendLine(top, datum, context);
const bottomLine = this.extendLine(bottom, datum, context);
this.updateLines(datum, topLine, bottomLine, context, top, bottom);
this.updateHandles(datum, top, bottom);
this.updateText(datum, top, bottom);
this.updateBackground(datum, topLine, bottomLine, context);
this.updateAnchor(top, bottom);
for (const handle3 of Object.values(this.handles)) {
handle3.toggleLocked(locked ?? false);
}
}
toggleHandles(show) {
const { handles } = this;
if (typeof show === "boolean") {
for (const [handle3, node] of Object.entries(handles)) {
node.visible = show;
node.toggleHovered(this.activeHandle === handle3);
}
return;
}
for (const [handle3, visible] of Object.entries(show)) {
const node = handles[handle3];
node.visible = visible ?? true;
node.toggleHovered(this.activeHandle === handle3);
}
}
toggleActive(active) {
this.toggleHandles(active);
for (const node of Object.values(this.handles)) {
node.toggleActive(active);
}
}
stopDragging() {
const { activeHandle, handles } = this;
if (activeHandle == null)
return;
handles[activeHandle].toggleDragging(false);
}
getAnchor() {
return this.anchor;
}
getCursor() {
if (this.activeHandle == null)
return "pointer";
return this.handles[this.activeHandle].getCursor();
}
containsPoint(x, y) {
const { handles, topLine, bottomLine, text: text2 } = this;
this.activeHandle = void 0;
for (const [handle3, child] of Object.entries(handles)) {
if (child.containsPoint(x, y)) {
this.activeHandle = handle3;
return true;
}
}
return topLine.containsPoint(x, y) || bottomLine.containsPoint(x, y) || Boolean(text2?.containsPoint(x, y));
}
getNodeAtCoords(x, y) {
if (this.text?.containsPoint(x, y))
return "text";
if (this.topLine.containsPoint(x, y) || this.bottomLine.containsPoint(x, y))
return "line";
for (const [, child] of Object.entries(this.handles)) {
if (child.containsPoint(x, y))
return "handle";
}
}
updateAnchor(top, bottom) {
const { x, y } = _ModuleSupport50.Transformable.toCanvasPoint(
this.topLine,
(top.x1 + top.x2) / 2,
Math.min(top.y1, top.y2, bottom.y1, bottom.y2)
);
this.anchor.x = x;
this.anchor.y = y;
}
};
// packages/ag-charts-enterprise/src/features/annotations/disjoint-channel/disjointChannelScene.ts
var DisjointChannelScene = class extends ChannelScene {
constructor() {
super();
this.type = "disjoint-channel";
this.handles = {
topLeft: new DivariantHandle(),
topRight: new DivariantHandle(),
bottomLeft: new DivariantHandle(),
bottomRight: new UnivariantHandle()
};
this.append([this.background, this.topLine, this.bottomLine, ...Object.values(this.handles)]);
}
static is(value) {
return AnnotationScene.isCheck(value, "disjoint-channel");
}
dragHandle(datum, target, context, snapping) {
const { activeHandle, handles } = this;
if (activeHandle == null)
return;
const { offset } = handles[activeHandle].drag(target);
handles[activeHandle].toggleDragging(true);
if (activeHandle === "bottomRight") {
offset.x = 0;
}
let translateVectors = [];
let invertYVectors = [];
let allowSnapping = snapping;
switch (activeHandle) {
case "topLeft":
translateVectors = ["topLeft"];
invertYVectors = ["bottomLeft"];
break;
case "bottomLeft":
translateVectors = ["bottomLeft"];
invertYVectors = ["topLeft"];
break;
case "topRight":
translateVectors = ["topRight"];
invertYVectors = ["bottomRight"];
break;
case "bottomRight":
translateVectors = ["bottomLeft", "bottomRight"];
allowSnapping = false;
break;
}
const top = convertLine(datum, context);
const bottom = convertLine(datum.bottom, context);
if (!top || !bottom)
return;
const vectors = {
topLeft: Vec46.start(top),
topRight: Vec46.end(top),
bottomLeft: Vec46.start(bottom),
bottomRight: Vec46.end(bottom)
};
const snap = {
vectors: {
topLeft: vectors.topRight,
bottomLeft: vectors.bottomRight,
topRight: vectors.topLeft,
bottomRight: vectors.bottomLeft
},
angle: datum.snapToAngle
};
const points = translate(vectors, offset, context, {
overflowContinuous: this.overflowContinuous,
translateVectors,
invertYVectors,
snap: allowSnapping ? snap : void 0
});
datum.start.x = points.topLeft.x;
datum.start.y = points.topLeft.y;
datum.end.x = points.topRight.x;
datum.end.y = points.topRight.y;
datum.startHeight = points.topLeft.y - points.bottomLeft.y;
datum.endHeight = points.topRight.y - points.bottomRight.y;
}
getTranslatePointsVectors(start, end) {
const { bottomLeft, bottomRight, topLeft, topRight } = this.handles;
const startHeight = bottomLeft.getBBox().y - topLeft.getBBox().y;
const endHeight = bottomRight.getBBox().y - topRight.getBBox().y;
const bottomStart = Vec210.add(start, Vec210.from(0, startHeight));
const bottomEnd = Vec210.add(end, Vec210.from(0, endHeight));
return { start, end, bottomStart, bottomEnd };
}
updateLines(datum, top, bottom) {
const { topLine, bottomLine } = this;
const { lineDashOffset, stroke: stroke3, strokeOpacity, strokeWidth } = datum;
const lineStyles = {
lineCap: datum.getLineCap(),
lineDash: datum.getLineDash(),
lineDashOffset,
stroke: stroke3,
strokeOpacity,
strokeWidth
};
topLine.setProperties({ ...top, ...lineStyles });
bottomLine.setProperties({ ...bottom, ...lineStyles });
}
updateHandles(datum, top, bottom) {
const {
handles: { topLeft, topRight, bottomLeft, bottomRight }
} = this;
const handleStyles = {
fill: datum.handle.fill,
stroke: datum.handle.stroke ?? datum.stroke,
strokeOpacity: datum.handle.strokeOpacity ?? datum.strokeOpacity,
strokeWidth: datum.handle.strokeWidth ?? datum.strokeWidth
};
topLeft.update({ ...handleStyles, ...Vec46.start(top) });
topRight.update({ ...handleStyles, ...Vec46.end(top) });
bottomLeft.update({ ...handleStyles, ...Vec46.start(bottom) });
bottomRight.update({
...handleStyles,
...Vec210.sub(Vec46.end(bottom), Vec210.from(bottomRight.handle.width / 2, bottomRight.handle.height / 2))
});
}
updateText(datum, top, bottom) {
this.text = this.updateNode(CollidableText, this.text, !!datum.text.label);
updateChannelText(false, top, bottom, datum.text, datum.strokeWidth, this.text, datum.text.label);
}
getBackgroundPoints(datum, top, bottom, bounds) {
const isFlippedX = top.x1 > top.x2;
const isFlippedY = top.y1 > top.y2;
const topY = isFlippedY ? bounds.y2 : bounds.y1;
const bottomY = isFlippedY ? bounds.y1 : bounds.y2;
const points = Vec210.from(top);
if (datum.extendEnd && top.y2 === bottomY) {
points.push(Vec210.from(isFlippedX ? bounds.x1 : bounds.x2, isFlippedY ? bounds.y1 : bounds.y2));
}
if (datum.extendEnd && bottom.y2 === topY) {
points.push(Vec210.from(isFlippedX ? bounds.x1 : bounds.x2, isFlippedY ? bounds.y2 : bounds.y1));
}
points.push(...Vec210.from(bottom).reverse());
if (datum.extendStart && bottom.y1 === bottomY) {
points.push(Vec210.from(isFlippedX ? bounds.x2 : bounds.x1, isFlippedY ? bounds.y1 : bounds.y2));
}
if (datum.extendStart && top.y1 === topY) {
points.push(Vec210.from(isFlippedX ? bounds.x2 : bounds.x1, isFlippedY ? bounds.y2 : bounds.y1));
}
return points;
}
};
// packages/ag-charts-enterprise/src/features/annotations/disjoint-channel/disjointChannelState.ts
import { Debug as Debug6, StateMachine as StateMachine6, StateMachineProperty as StateMachineProperty6, isNumber as isNumber2 } from "ag-charts-core";
var DisjointChannelStateMachine = class extends StateMachine6 {
constructor(ctx) {
const actionCreate = ({ point }) => {
const datum = new DisjointChannelProperties();
datum.set({ start: point, end: point, startHeight: 0, endHeight: 0 });
ctx.create(datum);
};
const actionFirstRender = () => {
const { node } = this;
node?.toggleActive(true);
node?.toggleHandles({ topLeft: true, topRight: false, bottomLeft: false, bottomRight: false });
};
const actionEndUpdate = ({ offset, context }) => {
const { datum, snapping } = this;
if (!datum)
return;
datum.set({ end: snapPoint(offset, context, snapping, datum.start, datum.snapToAngle) });
ctx.update();
};
const actionEndFinish = () => {
this.node?.toggleHandles({ topRight: true });
ctx.update();
};
const actionHeightUpdate = ({ point }) => {
const { datum, node } = this;
const endY = getGroupingValue(datum?.end.y);
const startY = getGroupingValue(datum?.start.y);
const { y: pointY } = point;
if (datum == null || !isNumber2(startY) || !isNumber2(endY) || !isNumber2(pointY))
return;
const endHeight = endY - (pointY ?? 0);
const startHeight = (startY - endY) * 2 + endHeight;
const bottomStart = { x: datum?.start.x, y: startY - startHeight };
const bottomEnd = { x: datum?.end.x, y: point.y };
node?.toggleHandles({ bottomLeft: true, bottomRight: true });
if (!ctx.validatePoint(bottomStart, { overflowContinuous: true }) || !ctx.validatePoint(bottomEnd, { overflowContinuous: true })) {
return;
}
datum.set({ startHeight, endHeight });
ctx.update();
};
const actionHeightFinish = ({ point }) => {
const { datum, node } = this;
const endY = getGroupingValue(datum?.end.y);
const startY = getGroupingValue(datum?.start.y);
const { y: pointY } = point;
if (datum == null || !isNumber2(startY) || !isNumber2(endY) || !isNumber2(pointY))
return;
const endHeight = endY - (pointY ?? 0);
const startHeight = (startY - endY) * 2 + endHeight;
const bottomStart = { x: datum.start.x, y: startY - endHeight };
const bottomEnd = { x: datum.end.x, y: point.y };
node?.toggleHandles(true);
if (!ctx.validatePoint(bottomStart, { overflowContinuous: true }) || !ctx.validatePoint(bottomEnd, { overflowContinuous: true })) {
return;
}
datum.set({ startHeight, endHeight });
ctx.recordAction(`Create ${"disjoint-channel" /* DisjointChannel */} annotation`);
ctx.showAnnotationOptions();
ctx.update();
};
const actionCancel = () => ctx.delete();
super("start", {
start: {
click: {
target: "waiting-first-render",
action: actionCreate
},
drag: {
target: "waiting-first-render",
action: actionCreate
},
reset: StateMachine6.parent
},
"waiting-first-render": {
render: {
target: "end",
action: actionFirstRender
}
},
end: {
hover: actionEndUpdate,
drag: actionEndUpdate,
click: {
target: "height",
action: actionEndFinish
},
dragEnd: {
target: "height",
action: actionEndFinish
},
reset: {
target: StateMachine6.parent,
action: actionCancel
},
cancel: {
target: StateMachine6.parent,
action: actionCancel
}
},
height: {
hover: actionHeightUpdate,
click: {
target: StateMachine6.parent,
action: actionHeightFinish
},
drag: {
target: StateMachine6.parent,
action: actionHeightFinish
},
reset: {
target: StateMachine6.parent,
action: actionCancel
},
cancel: {
target: StateMachine6.parent,
action: actionCancel
}
}
});
this.debug = Debug6.create(true, "annotations");
this.snapping = false;
}
};
__decorateClass([
StateMachineProperty6()
], DisjointChannelStateMachine.prototype, "datum", 2);
__decorateClass([
StateMachineProperty6()
], DisjointChannelStateMachine.prototype, "node", 2);
__decorateClass([
StateMachineProperty6()
], DisjointChannelStateMachine.prototype, "snapping", 2);
// packages/ag-charts-enterprise/src/features/annotations/disjoint-channel/disjointChannelConfig.ts
var disjointChannelConfig = {
type: "disjoint-channel" /* DisjointChannel */,
datum: DisjointChannelProperties,
scene: DisjointChannelScene,
isDatum: DisjointChannelProperties.is,
translate: (node, datum, transition, context) => {
if (DisjointChannelProperties.is(datum) && DisjointChannelScene.is(node)) {
node.translate(datum, transition, context);
}
},
copy: (node, datum, copiedDatum, context) => {
if (DisjointChannelProperties.is(datum) && DisjointChannelProperties.is(copiedDatum) && DisjointChannelScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (DisjointChannelProperties.is(datum) && DisjointChannelScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new DisjointChannelStateMachine({
...ctx,
create: createDatum("disjoint-channel" /* DisjointChannel */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/fibonacci-retracement-trend-based/fibonacciRetracementTrendBasedScene.ts
import { Vec2 as Vec212, Vec4 as Vec48, entries as entries3 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/scenes/fibonacciScene.ts
import { _ModuleSupport as _ModuleSupport51 } from "ag-charts-community";
import { Vec2 as Vec211, Vec4 as Vec47 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/utils/fibonacci.ts
var FIBONACCI_RETRACEMENT_RATIOS = [0, 23.6, 38.2, 50, 61.8, 78.6, 100];
var FIBONACCI_EXTENSION_RATIOS = [161.8, 261.8, 361.8, 423.6];
var FIBONACCI_RATIOS = [...FIBONACCI_RETRACEMENT_RATIOS, ...FIBONACCI_EXTENSION_RATIOS];
var FIBONACCI_RATIOS_MAP = {
10: FIBONACCI_RATIOS,
6: FIBONACCI_RETRACEMENT_RATIOS,
4: FIBONACCI_RETRACEMENT_RATIOS.filter((r) => r !== 78.6 && r !== 23.6)
};
var FIBONACCI_RANGE_LABEL_PADDING = 10;
function getFibonacciCoords(coords1, coords2) {
const { x2, y1, y2 } = coords1;
const trendLineVerticalDistance = y1 - y2;
if (coords2 == null) {
return {
x1: x2,
x2,
y1: y2 - trendLineVerticalDistance,
y2
};
}
return {
x1: coords2.x1,
x2: coords2.x2,
y1: coords2.y2 - trendLineVerticalDistance,
y2: coords2.y2
};
}
function createFibonacciRangesData({ x1, y1, x2, y2 }, context, reverse, yZero, bands = 10) {
const verticalDistance = y1 - y2;
const direction = reverse ? -1 : 1;
let startY = yZero;
const data = [];
for (const [index, ratio8] of FIBONACCI_RATIOS_MAP[bands].entries()) {
const endY = yZero + verticalDistance * (ratio8 / 100) * direction;
const yDatumVal = context.yAxis.scaleInvert(endY);
data.push({
id: index,
x1,
x2,
y1: startY,
y2: endY,
tag: ratio8 == 100 ? 0 /* OneLine */ : 1 /* HorizontalLine */,
label: {
x1: Math.min(x1, x2) - FIBONACCI_RANGE_LABEL_PADDING,
x2,
y1: endY,
y2: endY,
text: `${(ratio8 / 100).toFixed(3)} (${yDatumVal.toFixed(2)})`
}
});
startY = endY;
}
return data;
}
// packages/ag-charts-enterprise/src/features/annotations/scenes/fibonacciScene.ts
var FibonacciScene = class extends AnnotationScene {
constructor() {
super();
this.trendLine = new CollidableLine();
this.rangeFillsGroup = new _ModuleSupport51.Group({
name: `${this.id}-range-fills`
});
this.rangeFillsGroupSelection = _ModuleSupport51.Selection.select(this.rangeFillsGroup, _ModuleSupport51.Range);
this.rangeStrokesGroup = new _ModuleSupport51.Group({
name: `${this.id}-range-strokes`
});
this.rangeStrokesGroupSelection = _ModuleSupport51.Selection.select(this.rangeStrokesGroup, CollidableLine);
this.labelsGroup = new _ModuleSupport51.Group({
name: `${this.id}-ranges-labels`
});
this.labelsGroupSelection = _ModuleSupport51.Selection.select(this.labelsGroup, CollidableText);
this.anchor = {
x: 0,
y: 0,
position: "above"
};
this.append([this.trendLine, this.rangeFillsGroup, this.rangeStrokesGroup, this.labelsGroup]);
}
update(datum, context) {
let coords = convertLine(datum, context);
if (coords == null) {
this.visible = false;
return;
}
coords = Vec47.round(coords);
this.visible = datum.visible ?? true;
if (!this.visible)
return;
this.updateLine(datum, coords, this.trendLine);
this.updateHandles(datum, coords);
this.updateAnchor(datum, coords, context);
const { reverse } = datum;
const extendedCoords = this.extendLine(coords, datum, context);
const yZero = reverse ? extendedCoords.y1 : extendedCoords.y2;
const yOne = reverse ? extendedCoords.y2 : extendedCoords.y1;
const data = createFibonacciRangesData(extendedCoords, context, datum.reverse, yZero, datum.bands);
this.updateRanges(datum, data, context);
const oneLinePoints = { ...extendedCoords, y1: yOne, y2: yOne };
this.updateText(datum, oneLinePoints);
}
extendLine({ x1, y1, x2, y2 }, datum, context) {
const linePoints = { x1, y1, x2, y2 };
if (!datum.extendStart && !datum.extendEnd) {
return linePoints;
}
const { x, width } = context.xAxis.bounds;
if (datum.extendEnd) {
linePoints[x1 > x2 ? "x1" : "x2"] = x + width;
}
if (datum.extendStart) {
linePoints[x1 > x2 ? "x2" : "x1"] = x;
}
return linePoints;
}
updateLine(datum, coords, line) {
if (!coords || !line) {
return;
}
const { lineDashOffset, strokeWidth, strokeOpacity, stroke: stroke3 } = datum;
line.setProperties({
...coords,
lineCap: datum.getLineCap(),
lineDash: [3, 4],
lineDashOffset,
strokeWidth,
strokeOpacity,
fillOpacity: 0,
stroke: stroke3
});
}
updateRangeStrokes(datum) {
const { lineDashOffset, strokeWidth, strokeOpacity, strokes, rangeStroke, isMultiColor } = datum;
this.rangeStrokesGroupSelection.each((line, { x1, x2, y2, tag }, index) => {
const y = y2;
const color7 = isMultiColor ? strokes[index % strokes.length] : rangeStroke;
line.setProperties({
x1,
x2,
y1: y,
y2: y,
stroke: color7,
strokeOpacity,
strokeWidth,
lineCap: datum.getLineCap(),
lineDash: datum.getLineDash(),
lineDashOffset,
tag
});
});
}
updateRanges(datum, data, context) {
const getDatumId = (d) => d.id;
this.rangeFillsGroupSelection.update(data, void 0, getDatumId);
this.rangeStrokesGroupSelection.update(data, void 0, getDatumId);
this.labelsGroupSelection.update(data, void 0, getDatumId);
this.updateRangeFills(datum);
this.updateRangeStrokes(datum);
this.updateRangeLabels(datum, context);
}
updateRangeFills(datum) {
const {
lineDashOffset,
strokeWidth,
strokeOpacity,
strokes: colors,
rangeStroke,
showFill,
isMultiColor
} = datum;
this.rangeFillsGroupSelection.each((range2, { x1, x2, y1, y2 }, index) => {
const color7 = isMultiColor ? colors[index % colors.length] : rangeStroke;
if (!showFill) {
range2.visible = false;
return;
}
range2.setProperties({
x1,
x2,
y1,
y2,
startLine: false,
endLine: false,
stroke: color7,
strokeOpacity,
fill: color7,
fillOpacity: (strokeOpacity ?? 1) * 0.15,
strokeWidth,
lineCap: datum.getLineCap(),
lineDash: datum.getLineDash(),
lineDashOffset,
visible: true
});
});
}
updateRangeLabels(trendLineProperties, { xAxis }) {
const { rangeStrokesGroupSelection } = this;
const {
strokes: colors,
strokeWidth,
rangeStroke,
isMultiColor,
label: { fontFamily, fontSize, fontStyle, fontWeight, color: color7 }
} = trendLineProperties;
const labelProperties = {
fontFamily,
fontSize,
fontStyle,
fontWeight
};
const withinBounds = this.checkWithinBounds(xAxis, labelProperties, this.labelsGroupSelection.at(0));
this.labelsGroupSelection.each((textNode, datum, index) => {
const textColor = color7 ?? (isMultiColor ? colors[index % colors.length] : rangeStroke);
const line = rangeStrokesGroupSelection.at(index);
if (!line) {
return;
}
const { text: text2, ...coords } = datum.label;
if (withinBounds) {
textNode.setProperties({
...labelProperties,
text: text2,
x: coords.x1,
y: coords.y1,
textBaseline: "middle",
textAlign: "end",
fill: textColor
});
updateLineText(textNode.id, line, coords);
} else {
const textProperties = {
...labelProperties,
label: text2,
position: "center",
alignment: "left",
color: textColor
};
updateLineText(textNode.id, line, coords, textProperties, textNode, text2, strokeWidth);
}
});
}
checkWithinBounds(xAxis, fontOptions, textNode) {
if (!textNode) {
return false;
}
const { text: text2, ...coords } = textNode.datum.label;
textNode.setProperties({
...fontOptions,
text: text2,
x: coords.x1,
y: coords.y1,
textBaseline: "middle",
textAlign: "end"
});
const { x } = textNode.getBBox();
return x >= xAxis.bounds.x && x <= xAxis.bounds.x + xAxis.bounds.width;
}
updateText(datum, coords) {
const oneLine = this.rangeStrokesGroupSelection.selectByTag(0 /* OneLine */)[0];
if (!oneLine) {
return;
}
const { text: textProperties, strokeWidth } = datum;
this.text = this.updateNode(CollidableText, this.text, !!textProperties.label);
updateLineText(oneLine.id, oneLine, coords, textProperties, this.text, textProperties.label, strokeWidth);
}
updateAnchor(_datum, coords, _context, _bbox) {
const point = Vec47.topCenter(coords);
Vec211.apply(this.anchor, _ModuleSupport51.Transformable.toCanvasPoint(this.trendLine, point.x, point.y));
}
containsPoint(x, y) {
const { trendLine, rangeStrokesGroupSelection, text: text2 } = this;
let isInStrokePath = false;
rangeStrokesGroupSelection.each((line) => isInStrokePath || (isInStrokePath = line.isPointInPath(x, y)));
return isInStrokePath || trendLine.isPointInPath(x, y) || Boolean(text2?.containsPoint(x, y));
}
getNodeAtCoords(x, y) {
if (this.text?.containsPoint(x, y))
return "text";
if (this.trendLine.isPointInPath(x, y))
return "line";
}
getHandleStyles(datum) {
return {
fill: datum.handle.fill,
stroke: datum.handle.stroke ?? datum.stroke,
strokeOpacity: datum.handle.strokeOpacity ?? datum.strokeOpacity,
strokeWidth: datum.handle.strokeWidth ?? datum.strokeWidth
};
}
drag(datum, target, context, snapping) {
if (!datum.isWriteable())
return;
if (this.activeHandle) {
this.dragHandle(datum, target, context, snapping);
} else {
this.dragAll(datum, target, context);
}
}
getAnchor() {
return this.anchor;
}
getCursor() {
return "pointer";
}
};
// packages/ag-charts-enterprise/src/features/annotations/utils/validation.ts
import { _ModuleSupport as _ModuleSupport52 } from "ag-charts-community";
import { Logger as Logger3 } from "ag-charts-core";
var { ContinuousScale: ContinuousScale3 } = _ModuleSupport52;
function validateDatumPoint(context, point, options = { overflowContinuous: false }, warningPrefix) {
if (point.x == null || point.y == null) {
if (warningPrefix) {
Logger3.warnOnce(`${warningPrefix}requires both an [x] and [y] property, ignoring.`);
}
return false;
}
const { xAxis, yAxis } = context;
const continuousX = options.overflowContinuous && ContinuousScale3.is(xAxis.scale);
const continuousY = options.overflowContinuous && ContinuousScale3.is(yAxis.scale);
const validX = continuousX || validateDatumPointDirection(point.x, xAxis);
const validY = continuousY || validateDatumPointDirection(point.y, yAxis);
if (validX && validY)
return true;
if (warningPrefix) {
let text2 = "x & y domains";
if (validX)
text2 = "y domain";
if (validY)
text2 = "x domain";
const xValue = getGroupingValue(point.x);
const yValue = getGroupingValue(point.y);
Logger3.warnOnce(`${warningPrefix}is outside the ${text2}, ignoring. - x: [${xValue}], y: ${yValue}]`);
}
return false;
}
function validateDatumPointDirection(d, context) {
const { domain } = context.scale;
const value = getGroupingValue(d);
if (domain && value != null && context.continuous) {
return value >= domain[0] && value <= domain.at(-1);
}
return true;
}
// packages/ag-charts-enterprise/src/features/annotations/fibonacci-retracement-trend-based/fibonacciRetracementTrendBasedScene.ts
var FibonacciRetracementTrendBasedScene = class extends FibonacciScene {
constructor() {
super();
this.type = "fibonacci-retracement-trend-based";
this.endRetracementLine = new CollidableLine();
this.start = new DivariantHandle();
this.end = new DivariantHandle();
this.endRetracement = new DivariantHandle();
this.append([this.endRetracementLine, this.start, this.end, this.endRetracement]);
}
static is(value) {
return AnnotationScene.isCheck(value, "fibonacci-retracement-trend-based");
}
update(datum, context) {
let { coords1, coords2 } = this.getCoords(datum, context);
if (coords1 == null || coords2 == null) {
this.visible = false;
return;
}
coords1 = Vec48.round(coords1);
coords2 = Vec48.round(coords2);
this.visible = datum.visible ?? true;
if (!this.visible)
return;
if (datum.endRetracement.x == void 0 || datum.endRetracement.y == void 0) {
coords2 = void 0;
}
this.updateLine(datum, coords1, this.trendLine);
this.updateLine(datum, coords2, this.endRetracementLine);
this.updateHandles(datum, coords1, coords2);
this.updateAnchor(datum, coords2 ?? coords1, context);
const { reverse, bands } = datum;
const coords = getFibonacciCoords(coords1, coords2);
const extendedCoords = this.extendLine(coords, datum, context);
const yZero = extendedCoords.y2;
const yOne = extendedCoords.y1;
const data = coords2 ? createFibonacciRangesData(extendedCoords, context, reverse, yZero, bands) : [];
this.updateRanges(datum, data, context);
const oneLinePoints = { ...extendedCoords, y1: yOne, y2: yOne };
this.updateText(datum, oneLinePoints);
}
containsPoint(x, y) {
const { start, end, endRetracement, endRetracementLine } = this;
this.activeHandle = void 0;
if (start.containsPoint(x, y)) {
this.activeHandle = "start";
return true;
}
if (end.containsPoint(x, y)) {
this.activeHandle = "end";
return true;
}
if (endRetracement.containsPoint(x, y)) {
this.activeHandle = "endRetracement";
return true;
}
return endRetracementLine.isPointInPath(x, y) || super.containsPoint(x, y);
}
getNodeAtCoords(x, y) {
if (this.start.containsPoint(x, y) || this.end.containsPoint(x, y) || this.endRetracement.containsPoint(x, y))
return "handle";
if (this.endRetracementLine.isPointInPath(x, y))
return "line";
return super.getNodeAtCoords(x, y);
}
dragStart(datum, target, context) {
this.dragState = {
offset: target,
...getDragStartState({ start: datum.start, end: datum.end, endRetracement: datum.endRetracement }, context)
};
}
stopDragging() {
this.start.toggleDragging(false);
this.end.toggleDragging(false);
this.endRetracement.toggleDragging(false);
}
dragAll(datum, target, context) {
const { dragState } = this;
if (!dragState)
return;
this.translatePoints({
datum,
start: dragState.start,
end: dragState.end,
endRetracement: dragState.endRetracement,
translation: Vec212.sub(target, dragState.offset),
context
});
}
dragHandle(datum, target, context, snapping) {
const { activeHandle, dragState } = this;
if (!activeHandle || !dragState)
return;
this[activeHandle].toggleDragging(true);
const point = snapping ? this.snapToAngle(datum, target, context) : invertCoords(this[activeHandle].drag(target).point, context);
if (!point || !validateDatumPoint(context, point))
return;
datum[activeHandle].x = point.x;
datum[activeHandle].y = point.y;
}
snapToAngle(datum, coords, context) {
const { activeHandle } = this;
const handles = ["start", "end", "endRetracement"];
if (!activeHandle)
return;
const index = (handles.indexOf(activeHandle) + 1) % handles.length;
const fixedHandle = handles[index];
this[activeHandle].toggleDragging(true);
const fixed = convertPoint(datum[fixedHandle], context);
return invertCoords(snapToAngle(coords, fixed, datum.snapToAngle), context);
}
translatePoints({
datum,
start,
end,
endRetracement,
translation,
context
}) {
const points = translate({ start, end, endRetracement }, translation, context, { overflowContinuous: 2 });
datum.start.x = points.start.x;
datum.end.x = points.end.x;
datum.endRetracement.x = points.endRetracement.x;
datum.start.y = points.start.y;
datum.end.y = points.end.y;
datum.endRetracement.y = points.endRetracement.y;
}
translate(datum, translation, context) {
this.translatePoints({
datum,
start: convertPoint(datum.start, context),
end: convertPoint(datum.end, context),
endRetracement: convertPoint(datum.endRetracement, context),
translation,
context
});
}
copy(datum, copiedDatum, context) {
const { coords1, coords2 } = this.getCoords(datum, context);
if (!coords1 || !coords2) {
return;
}
const bbox = this.computeBBoxWithoutHandles();
this.translatePoints({
datum: copiedDatum,
start: Vec48.start(coords1),
end: Vec48.end(coords1),
endRetracement: Vec48.end(coords2),
translation: { x: -bbox.width / 2, y: -bbox.height / 2 },
context
});
return copiedDatum;
}
getCoords(datum, context) {
return {
coords1: convertLine(datum, context),
coords2: convertLine({ start: datum.end, end: datum.endRetracement }, context)
};
}
toggleHandles(show) {
if (typeof show === "boolean") {
this.start.visible = show;
this.end.visible = show;
this.endRetracement.visible = show;
} else {
for (const [handle3, visible] of entries3(show)) {
this[handle3].visible = visible;
}
}
this.start.toggleHovered(this.activeHandle === "start");
this.end.toggleHovered(this.activeHandle === "end");
this.endRetracement.toggleHovered(this.activeHandle === "endRetracement");
}
toggleActive(active) {
this.toggleHandles(active);
this.start.toggleActive(active);
this.end.toggleActive(active);
this.endRetracement.toggleActive(active);
}
updateHandles(datum, coords1, coords2, bbox) {
this.start.update({
...this.getHandleStyles(datum),
...this.getHandleCoords(datum, coords1, "start")
});
this.end.update({
...this.getHandleStyles(datum),
...this.getHandleCoords(datum, coords1, "end", bbox)
});
if (coords2) {
this.endRetracement.update({
...this.getHandleStyles(datum),
...this.getHandleCoords(datum, coords2, "endRetracement", bbox)
});
}
this.start.toggleLocked(datum.locked ?? false);
this.end.toggleLocked(datum.locked ?? false);
this.endRetracement.toggleLocked(datum.locked ?? false);
}
getHandleCoords(_datum, coords, handle3, _bbox) {
return handle3 === "start" ? Vec48.start(coords) : Vec48.end(coords);
}
};
// packages/ag-charts-enterprise/src/features/annotations/fibonacci-retracement-trend-based/fibonacciRetracementTrendBasedState.ts
import { Debug as Debug7, StateMachine as StateMachine7, StateMachineProperty as StateMachineProperty7 } from "ag-charts-core";
var FibonacciRetracementTrendBasedStateMachine = class extends StateMachine7 {
constructor(ctx) {
const actionCreate = ({ point }) => {
const datum = this.createDatum();
datum.set({ start: point, end: point });
ctx.create(datum);
};
const actionFirstRender = () => {
const { node } = this;
node?.toggleActive(true);
node?.toggleHandles({ start: true, end: false, endRetracement: false });
};
const actionEndUpdate = ({ offset, context }) => {
const { datum, snapping } = this;
if (!datum)
return;
datum.set({ end: snapPoint(offset, context, snapping, datum.start, datum.snapToAngle) });
ctx.update();
};
const actionEndFinish = () => {
const { datum } = this;
if (!datum)
return;
datum.endRetracement.x = datum.end.x;
datum.endRetracement.y = datum.end.y;
this.node?.toggleHandles({ end: true });
ctx.update();
};
const actionEndRetracementUpdate = ({ offset, context }) => {
const { datum, snapping } = this;
if (!datum)
return;
datum.set({ endRetracement: snapPoint(offset, context, snapping, datum.end, datum.snapToAngle) });
ctx.update();
};
const actionEndRetracementFinish = () => {
this.node?.toggleHandles({ endRetracement: true });
ctx.update();
};
const actionCancel = () => ctx.delete();
const onExitEnd = () => {
ctx.showAnnotationOptions();
ctx.recordAction(`Create ${this.datum?.type} annotation`);
};
super("start", {
start: {
click: {
target: "waiting-first-render",
action: actionCreate
},
drag: {
target: "waiting-first-render",
action: actionCreate
},
reset: StateMachine7.parent
},
"waiting-first-render": {
render: {
target: "end",
action: actionFirstRender
}
},
end: {
hover: actionEndUpdate,
click: {
target: "endRetracement",
action: actionEndFinish
},
drag: actionEndUpdate,
dragEnd: {
target: "endRetracement",
action: actionEndFinish
},
reset: {
target: StateMachine7.parent,
action: actionCancel
},
cancel: {
target: StateMachine7.parent,
action: actionCancel
},
onExit: onExitEnd
},
endRetracement: {
hover: actionEndRetracementUpdate,
click: {
target: StateMachine7.parent,
action: actionEndRetracementFinish
},
drag: {
target: StateMachine7.parent,
action: actionEndRetracementFinish
},
reset: {
target: StateMachine7.parent,
action: actionCancel
},
cancel: {
target: StateMachine7.parent,
action: actionCancel
}
}
});
this.debug = Debug7.create(true, "annotations");
this.snapping = false;
}
createDatum() {
return new FibonacciRetracementTrendBasedProperties();
}
};
__decorateClass([
StateMachineProperty7()
], FibonacciRetracementTrendBasedStateMachine.prototype, "datum", 2);
__decorateClass([
StateMachineProperty7()
], FibonacciRetracementTrendBasedStateMachine.prototype, "node", 2);
__decorateClass([
StateMachineProperty7()
], FibonacciRetracementTrendBasedStateMachine.prototype, "snapping", 2);
// packages/ag-charts-enterprise/src/features/annotations/fibonacci-retracement-trend-based/fibonacciRetracementTrendBasedConfig.ts
var fibonacciRetracementTrendBasedConfig = {
type: "fibonacci-retracement-trend-based" /* FibonacciRetracementTrendBased */,
datum: FibonacciRetracementTrendBasedProperties,
scene: FibonacciRetracementTrendBasedScene,
isDatum: FibonacciRetracementTrendBasedProperties.is,
translate: (node, datum, transition, context) => {
if (FibonacciRetracementTrendBasedProperties.is(datum) && FibonacciRetracementTrendBasedScene.is(node))
node.translate(datum, transition, context);
},
copy: (node, datum, copiedDatum, context) => {
if (FibonacciRetracementTrendBasedProperties.is(datum) && FibonacciRetracementTrendBasedProperties.is(copiedDatum) && FibonacciRetracementTrendBasedScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (FibonacciRetracementTrendBasedProperties.is(datum) && FibonacciRetracementTrendBasedScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new FibonacciRetracementTrendBasedStateMachine({
...ctx,
create: createDatum("fibonacci-retracement-trend-based" /* FibonacciRetracementTrendBased */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/fibonacci-retracement/fibonacciRetracementScene.ts
import { Vec2 as Vec213, Vec4 as Vec49, entries as entries4 } from "ag-charts-core";
var FibonacciRetracementScene = class extends FibonacciScene {
constructor() {
super();
this.type = "fibonacci-retracement";
this.start = new DivariantHandle();
this.end = new DivariantHandle();
this.append([this.start, this.end]);
}
static is(value) {
return AnnotationScene.isCheck(value, "fibonacci-retracement");
}
containsPoint(x, y) {
const { start, end } = this;
this.activeHandle = void 0;
if (start.containsPoint(x, y)) {
this.activeHandle = "start";
return true;
}
if (end.containsPoint(x, y)) {
this.activeHandle = "end";
return true;
}
return super.containsPoint(x, y);
}
getNodeAtCoords(x, y) {
if (this.start.containsPoint(x, y) || this.end.containsPoint(x, y))
return "handle";
return super.getNodeAtCoords(x, y);
}
dragStart(datum, target, context) {
this.dragState = {
offset: target,
...getDragStartState({ start: datum.start, end: datum.end }, context)
};
}
stopDragging() {
this.start.toggleDragging(false);
this.end.toggleDragging(false);
}
dragAll(datum, target, context) {
const { dragState } = this;
if (!dragState)
return;
this.translatePoints({
datum,
start: dragState.start,
end: dragState.end,
translation: Vec213.sub(target, dragState.offset),
context
});
}
dragHandle(datum, target, context, snapping) {
const { activeHandle, dragState } = this;
if (!activeHandle || !dragState)
return;
this[activeHandle].toggleDragging(true);
const point = snapping ? this.snapToAngle(datum, target, context) : invertCoords(this[activeHandle].drag(target).point, context);
if (!point || !validateDatumPoint(context, point))
return;
datum[activeHandle].x = point.x;
datum[activeHandle].y = point.y;
}
snapToAngle(datum, coords, context) {
const { activeHandle } = this;
const handles = ["start", "end"];
const fixedHandle = handles.find((handle3) => handle3 !== activeHandle);
if (!activeHandle || !fixedHandle)
return;
this[activeHandle].toggleDragging(true);
const fixed = convertPoint(datum[fixedHandle], context);
return invertCoords(snapToAngle(coords, fixed, datum.snapToAngle), context);
}
translatePoints({
datum,
start,
end,
translation,
context
}) {
const points = translate({ start, end }, translation, context, { overflowContinuous: 1 });
datum.start.x = points.start.x;
datum.end.x = points.end.x;
datum.start.y = points.start.y;
datum.end.y = points.end.y;
}
translate(datum, translation, context) {
this.translatePoints({
datum,
start: convertPoint(datum.start, context),
end: convertPoint(datum.end, context),
translation,
context
});
}
copy(datum, copiedDatum, context) {
const coords = convertLine(datum, context);
if (!coords) {
return;
}
const bbox = this.computeBBoxWithoutHandles();
this.translatePoints({
datum: copiedDatum,
start: { x: coords.x1, y: coords.y1 },
end: { x: coords.x2, y: coords.y2 },
translation: { x: -bbox.width / 2, y: -bbox.height / 2 },
context
});
return copiedDatum;
}
toggleHandles(show) {
if (typeof show === "boolean") {
this.start.visible = show;
this.end.visible = show;
} else {
for (const [handle3, visible] of entries4(show)) {
this[handle3].visible = visible;
}
}
this.start.toggleHovered(this.activeHandle === "start");
this.end.toggleHovered(this.activeHandle === "end");
}
toggleActive(active) {
this.toggleHandles(active);
this.start.toggleActive(active);
this.end.toggleActive(active);
}
updateHandles(datum, coords, _coords2, bbox) {
this.start.update({
...this.getHandleStyles(datum),
...this.getHandleCoords(datum, coords, "start")
});
this.end.update({
...this.getHandleStyles(datum),
...this.getHandleCoords(datum, coords, "end", bbox)
});
this.start.toggleLocked(datum.locked ?? false);
this.end.toggleLocked(datum.locked ?? false);
}
getHandleCoords(_datum, coords, handle3, _bbox) {
return handle3 === "start" ? Vec49.start(coords) : Vec49.end(coords);
}
};
// packages/ag-charts-enterprise/src/features/annotations/line/lineState.ts
import { Debug as Debug8, StateMachine as StateMachine8, StateMachineProperty as StateMachineProperty8 } from "ag-charts-core";
var LineTypeStateMachine = class extends StateMachine8 {
constructor(ctx) {
const actionCreate = ({ point }) => {
const datum = this.createDatum();
datum.set({ start: point, end: point });
ctx.create(datum);
};
const actionFirstRender = () => {
const { node } = this;
node?.toggleActive(true);
node?.toggleHandles({ start: true, end: false });
};
const actionEndUpdate = ({ offset, context }) => {
const { datum, snapping } = this;
if (!datum)
return;
datum.set({ end: snapPoint(offset, context, snapping, datum.start, datum.snapToAngle) });
ctx.update();
};
const actionEndFinish = () => {
this.node?.toggleHandles({ end: true });
ctx.update();
};
const actionCancel = () => ctx.delete();
const onExitEnd = () => {
ctx.showAnnotationOptions();
ctx.recordAction(`Create ${this.datum?.type} annotation`);
};
super("start", {
start: {
click: {
target: "waiting-first-render",
action: actionCreate
},
drag: {
target: "waiting-first-render",
action: actionCreate
},
reset: StateMachine8.parent
},
"waiting-first-render": {
render: {
target: "end",
action: actionFirstRender
}
},
end: {
hover: actionEndUpdate,
click: {
target: StateMachine8.parent,
action: actionEndFinish
},
drag: actionEndUpdate,
dragEnd: {
target: StateMachine8.parent,
action: actionEndFinish
},
reset: {
target: StateMachine8.parent,
action: actionCancel
},
cancel: {
target: StateMachine8.parent,
action: actionCancel
},
onExit: onExitEnd
}
});
this.debug = Debug8.create(true, "annotations");
this.snapping = false;
}
};
__decorateClass([
StateMachineProperty8()
], LineTypeStateMachine.prototype, "datum", 2);
__decorateClass([
StateMachineProperty8()
], LineTypeStateMachine.prototype, "node", 2);
__decorateClass([
StateMachineProperty8()
], LineTypeStateMachine.prototype, "snapping", 2);
var ArrowStateMachine = class extends LineTypeStateMachine {
createDatum() {
return new ArrowProperties();
}
};
var LineStateMachine = class extends LineTypeStateMachine {
createDatum() {
return new LineProperties();
}
};
// packages/ag-charts-enterprise/src/features/annotations/fibonacci-retracement/fibonacciRetracementState.ts
var FibonacciRetracementStateMachine = class extends LineTypeStateMachine {
createDatum() {
return new FibonacciRetracementProperties();
}
};
// packages/ag-charts-enterprise/src/features/annotations/fibonacci-retracement/fibonacciRetracementConfig.ts
var fibonacciRetracementConfig = {
type: "fibonacci-retracement" /* FibonacciRetracement */,
datum: FibonacciRetracementProperties,
scene: FibonacciRetracementScene,
isDatum: FibonacciRetracementProperties.is,
translate: (node, datum, transition, context) => {
if (FibonacciRetracementProperties.is(datum) && FibonacciRetracementScene.is(node))
node.translate(datum, transition, context);
},
copy: (node, datum, copiedDatum, context) => {
if (FibonacciRetracementProperties.is(datum) && FibonacciRetracementProperties.is(copiedDatum) && FibonacciRetracementScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (FibonacciRetracementProperties.is(datum) && FibonacciRetracementScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new FibonacciRetracementStateMachine({
...ctx,
create: createDatum("fibonacci-retracement" /* FibonacciRetracement */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/line/lineScene.ts
import { _ModuleSupport as _ModuleSupport54 } from "ag-charts-community";
import { Vec2 as Vec215, Vec4 as Vec410 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/scenes/capScene.ts
import { _ModuleSupport as _ModuleSupport53 } from "ag-charts-community";
import { Vec2 as Vec214 } from "ag-charts-core";
var CapScene = class extends _ModuleSupport53.Group {
};
var ArrowCapScene = class extends CapScene {
constructor() {
super();
this.type = "arrow";
this.path = new _ModuleSupport53.Path();
this.armLength = 6;
this.append([this.path]);
}
update(options) {
const { path } = this;
const { x, y, angle, ...rest } = options;
const origin = Vec214.from(x, y);
const offsetAngle = 3 * Math.PI / 4;
const armLength = this.armLength + (options.strokeWidth ?? 0) * 2;
const leftEnd = Vec214.rotate(Vec214.from(0, armLength), angle + offsetAngle, origin);
const rightEnd = Vec214.rotate(Vec214.from(armLength, 0), angle - offsetAngle, origin);
path.setProperties(rest);
path.fillOpacity = 0;
path.path.clear();
path.path.moveTo(leftEnd.x, leftEnd.y);
path.path.lineTo(origin.x, origin.y);
path.path.lineTo(rightEnd.x, rightEnd.y);
}
};
// packages/ag-charts-enterprise/src/features/annotations/line/lineScene.ts
var { Transformable: Transformable2 } = _ModuleSupport54;
var LineScene = class extends StartEndScene {
constructor() {
super();
this.type = "line";
this.line = new CollidableLine();
this.append([this.line, this.start, this.end]);
}
static is(value) {
return AnnotationScene.isCheck(value, "line");
}
update(datum, context) {
let coords = convertLine(datum, context);
if (coords == null) {
this.visible = false;
return;
}
coords = Vec410.round(coords);
this.visible = datum.visible ?? true;
if (!this.visible)
return;
this.updateLine(datum, coords, context);
this.updateHandles(datum, coords);
this.updateText(datum, coords);
this.updateCaps(datum, coords);
this.updateAnchor(datum, coords, context);
}
updateLine(datum, coords, context) {
const { line } = this;
const { lineDashOffset, stroke: stroke3, strokeWidth, strokeOpacity } = datum;
const linePoints = this.extendLine(coords, datum, context);
line.setProperties({
...linePoints,
lineCap: datum.getLineCap(),
lineDash: datum.getLineDash(),
lineDashOffset,
stroke: stroke3,
strokeWidth,
strokeOpacity,
fillOpacity: 0
});
}
updateText(datum, coords) {
this.text = this.updateNode(CollidableText, this.text, !!datum.text.label);
updateLineText(this.line.id, this.line, coords, datum.text, this.text, datum.text.label, datum.strokeWidth);
}
updateCaps(datum, coords) {
if (!datum.startCap && this.startCap) {
this.startCap.remove();
this.startCap = void 0;
}
if (!datum.endCap && this.endCap) {
this.endCap.remove();
this.endCap = void 0;
}
if (!datum.startCap && !datum.endCap)
return;
const { stroke: stroke3, strokeWidth, strokeOpacity } = datum;
const [start, end] = Vec215.from(coords);
const angle = Vec215.angle(Vec215.sub(end, start));
if (datum.startCap) {
if (this.startCap && this.startCap.type !== datum.startCap) {
this.startCap.remove();
this.startCap = void 0;
}
if (this.startCap == null) {
this.startCap = new ArrowCapScene();
this.append([this.startCap]);
}
this.startCap.update({
x: start.x,
y: start.y,
angle: angle - Math.PI,
stroke: stroke3,
strokeWidth,
strokeOpacity
});
}
if (datum.endCap) {
if (this.endCap && this.endCap.type !== datum.endCap) {
this.endCap.remove();
this.endCap = void 0;
}
if (this.endCap == null) {
this.endCap = new ArrowCapScene();
this.append([this.endCap]);
}
this.endCap.update({
x: end.x,
y: end.y,
angle,
stroke: stroke3,
strokeWidth,
strokeOpacity
});
}
}
updateAnchor(_datum, coords, _context, _bbox) {
const point = Vec410.topCenter(coords);
Vec215.apply(this.anchor, Transformable2.toCanvasPoint(this.line, point.x, point.y));
}
containsPoint(x, y) {
const { line, text: text2 } = this;
return super.containsPoint(x, y) || line.isPointInPath(x, y) || Boolean(text2?.containsPoint(x, y));
}
getNodeAtCoords(x, y) {
if (this.text?.containsPoint(x, y))
return "text";
if (this.line.isPointInPath(x, y))
return "line";
return super.getNodeAtCoords(x, y);
}
getHandleCoords(_datum, coords, handle3, _bbox) {
const { startCap, endCap } = this;
let [startPoint, endPoint] = Vec215.from(coords);
const angle = Vec215.angle(Vec215.sub(endPoint, startPoint));
if (startCap) {
startPoint = Vec215.rotate(Vec215.from(0, -DivariantHandle.HANDLE_SIZE / 2), angle, startPoint);
}
if (endCap) {
endPoint = Vec215.rotate(Vec215.from(0, DivariantHandle.HANDLE_SIZE / 2), angle, endPoint);
}
return handle3 === "start" ? startPoint : endPoint;
}
getHandleStyles(datum) {
return {
fill: datum.handle.fill,
stroke: datum.handle.stroke ?? datum.stroke,
strokeOpacity: datum.handle.strokeOpacity ?? datum.strokeOpacity,
strokeWidth: datum.handle.strokeWidth ?? datum.strokeWidth
};
}
};
// packages/ag-charts-enterprise/src/features/annotations/line/lineConfig.ts
var lineConfig = {
type: "line" /* Line */,
datum: LineProperties,
scene: LineScene,
isDatum: LineProperties.is,
translate: (node, datum, transition, context) => {
if (LineProperties.is(datum) && LineScene.is(node))
node.translate(datum, transition, context);
},
copy: (node, datum, copiedDatum, context) => {
if (LineProperties.is(datum) && LineProperties.is(copiedDatum) && LineScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (LineProperties.is(datum) && LineScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new LineStateMachine({
...ctx,
create: createDatum("line" /* Line */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
var arrowConfig = {
type: "arrow" /* Arrow */,
datum: ArrowProperties,
scene: LineScene,
isDatum: ArrowProperties.is,
translate: (node, datum, transition, context) => {
if (ArrowProperties.is(datum) && LineScene.is(node))
node.translate(datum, transition, context);
},
copy: (node, datum, copiedDatum, context) => {
if (ArrowProperties.is(datum) && ArrowProperties.is(copiedDatum) && LineScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (ArrowProperties.is(datum) && LineScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new ArrowStateMachine({
...ctx,
create: createDatum("arrow" /* Arrow */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/measurer/measurerScene.ts
import { _ModuleSupport as _ModuleSupport57 } from "ag-charts-community";
import { Vec2 as Vec216, Vec4 as Vec412, isDate as isDate2, isNumber as isNumber3 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/measurer/measurerStatisticsScene.ts
import { _ModuleSupport as _ModuleSupport56 } from "ag-charts-community";
import { Vec4 as Vec411 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/annotations/utils/layout.ts
import { _ModuleSupport as _ModuleSupport55 } from "ag-charts-community";
function layoutScenesRow(scenes, startX = 0, gap = 0) {
let x = startX;
for (const scene of scenes) {
if (Array.isArray(scene)) {
for (const scene_ of scene) {
layoutSetX(scene_, x);
}
x += _ModuleSupport55.Group.computeChildrenBBox(scene).width + gap;
} else {
layoutSetX(scene, x);
x += scene.getBBox().width + gap;
}
}
}
function layoutScenesColumn(scenes, startY = 0, gap = 0) {
let y = startY;
for (const scene of scenes) {
if (Array.isArray(scene)) {
for (const scene_ of scene) {
layoutSetY(scene_, y);
}
y += _ModuleSupport55.Group.computeChildrenBBox(scene).height + gap;
} else {
layoutSetY(scene, y);
y += scene.getBBox().height + gap;
}
}
}
function layoutSetX(scene, x) {
if ("x1" in scene) {
scene.x2 = x + (scene.x2 - scene.x1);
scene.x1 = x;
} else {
scene.x = x;
}
}
function layoutSetY(scene, y) {
if ("y1" in scene) {
scene.y2 = y + (scene.y2 - scene.y1);
scene.y1 = y;
} else {
scene.y = y;
}
}
function layoutAddX(scene, x) {
if ("x1" in scene) {
scene.x1 += x;
scene.x2 += x;
} else {
scene.x += x;
}
}
function layoutAddY(scene, y) {
if ("y1" in scene) {
scene.y1 += y;
scene.y2 += y;
} else {
scene.y += y;
}
}
// packages/ag-charts-enterprise/src/features/annotations/measurer/measurerStatisticsScene.ts
var MeasurerStatisticsScene = class extends _ModuleSupport56.Group {
constructor() {
super();
this.name = "MeasurerStatisticsScene";
this.background = new _ModuleSupport56.Rect();
this.dateRangeBarsText = new _ModuleSupport56.Text();
this.dateRangeDivider = new _ModuleSupport56.Line();
this.dateRangeValueText = new _ModuleSupport56.Text();
this.priceRangeValueText = new _ModuleSupport56.Text();
this.priceRangeDivider = new _ModuleSupport56.Line();
this.priceRangePercentageText = new _ModuleSupport56.Text();
this.volumeText = new _ModuleSupport56.Text();
this.volumeFormatter = new Intl.NumberFormat("en-US", {
notation: "compact",
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
this.append([
this.background,
this.dateRangeBarsText,
this.dateRangeDivider,
this.dateRangeValueText,
this.priceRangeValueText,
this.priceRangeDivider,
this.priceRangePercentageText,
this.volumeText
]);
}
update(datum, stats, anchor, coords, context, verticalDirection, localeManager) {
this.verticalDirection = verticalDirection;
const scenes = this.updateStatistics(datum, stats, anchor, localeManager);
const bbox = _ModuleSupport56.Group.computeChildrenBBox(scenes.flat());
const padding2 = 10;
bbox.grow(padding2);
this.updateBackground(datum, bbox, padding2);
this.reposition(scenes, padding2, context);
this.checkVisibility(datum, context, coords);
}
checkVisibility(datum, context, coords) {
const bounds = Vec411.from(context.seriesRect);
this.visible = Vec411.collides(coords, bounds) && (datum.visible ?? true);
}
updateStatistics(datum, stats, anchor, localeManager) {
const {
dateRangeBarsText,
dateRangeDivider,
dateRangeValueText,
priceRangeValueText,
priceRangeDivider,
priceRangePercentageText,
volumeText
} = this;
const horizontalGap = 8;
const verticalGap = 6;
const dividerLineHeight = datum.statistics.fontSize + 3;
const dividerLineOffset = -2;
const textStyles = this.getTextStyles(datum);
const dividerLineStyles = {
...this.getDividerStyles(datum),
x1: 0,
y1: 0,
x2: 0,
y2: dividerLineHeight
};
const dateScenes = [dateRangeBarsText, dateRangeDivider, dateRangeValueText];
const priceScenes = [priceRangeValueText, priceRangeDivider, priceRangePercentageText];
const scenes = [];
if (stats.priceRange) {
priceRangeValueText.setProperties({
...textStyles,
text: this.formatPriceRangeValue(stats.priceRange.value, localeManager)
});
priceRangeDivider.setProperties(dividerLineStyles);
priceRangePercentageText.setProperties({
...textStyles,
text: this.formatPriceRangePercentage(stats.priceRange.percentage, localeManager)
});
layoutScenesRow(priceScenes, anchor.x, horizontalGap);
scenes.push(priceScenes);
}
if (stats.dateRange) {
dateRangeBarsText.setProperties({
...textStyles,
text: this.formatDateRangeBars(stats.dateRange.bars, localeManager)
});
dateRangeDivider.setProperties(dividerLineStyles);
dateRangeValueText.setProperties({
...textStyles,
text: this.formatDateRangeValue(stats.dateRange.value)
});
layoutScenesRow(dateScenes, anchor.x, horizontalGap);
scenes.push(dateScenes);
}
if (stats.volume == null) {
volumeText.visible = false;
} else {
volumeText.setProperties({
...textStyles,
x: anchor.x,
text: this.formatVolume(stats.volume, localeManager),
visible: true
});
scenes.push(volumeText);
}
layoutScenesColumn(scenes, anchor.y, verticalGap);
priceRangeDivider.y1 += dividerLineOffset;
priceRangeDivider.y2 += dividerLineOffset;
dateRangeDivider.y1 += dividerLineOffset;
dateRangeDivider.y2 += dividerLineOffset;
return scenes;
}
updateBackground(datum, bbox, padding2) {
const styles = this.getBackgroundStyles(datum);
this.background.setProperties({
...styles,
...bbox,
x: bbox.x - bbox.width / 2 + padding2,
y: bbox.y
});
}
reposition(scenes, padding2, context) {
const { width, height } = context.seriesRect;
const background = Vec411.from(this.background.getBBox());
let offsetX = 0;
if (background.x1 < 0)
offsetX = -background.x1;
if (background.x2 > width)
offsetX = width - background.x2;
const offsetY = Math.min(padding2, height - background.y2);
for (const scene of scenes) {
if (Array.isArray(scene)) {
const rowWidth = _ModuleSupport56.Group.computeChildrenBBox(scene).width;
for (const scene_ of scene) {
layoutAddX(scene_, offsetX - rowWidth / 2);
layoutAddY(scene_, offsetY);
}
} else {
layoutAddX(scene, offsetX - scene.getBBox().width / 2);
layoutAddY(scene, offsetY);
}
}
this.background.x += offsetX;
this.background.y += offsetY;
}
getTextStyles(datum) {
return {
fill: datum.statistics.color,
fontFamily: datum.statistics.fontFamily,
fontSize: datum.statistics.fontSize,
fontStyle: datum.statistics.fontStyle,
fontWeight: datum.statistics.fontWeight,
textBaseline: "top"
};
}
getDividerStyles(datum) {
return {
stroke: datum.statistics.divider.stroke,
strokeOpacity: datum.statistics.divider.strokeOpacity,
strokeWidth: datum.statistics.divider.strokeWidth
};
}
getBackgroundStyles(datum) {
return {
fill: datum.statistics.fill,
stroke: datum.statistics.stroke,
strokeOpacity: datum.statistics.strokeOpacity,
strokeWidth: datum.statistics.strokeWidth,
cornerRadius: 4
};
}
formatDateRangeBars(bars, localeManager) {
return localeManager?.t("measurerDateRangeBars", { value: bars }) ?? `${bars}`;
}
formatDateRangeValue(time) {
const range2 = [];
const sign = time >= 0 ? "" : "-";
time = Math.abs(time);
const MINUTE = 1e3 * 60;
const HOUR = MINUTE * 60;
const DAY2 = HOUR * 24;
const minutes = Math.floor(time / MINUTE);
const hours = Math.floor(time / HOUR);
const days = Math.floor(time / DAY2);
const remainderHours = hours % (DAY2 / HOUR);
const remainderMinutes = minutes % (HOUR / MINUTE);
if (days >= 1)
range2.push(`${days}d`);
if (hours >= 1 && (time < DAY2 || remainderHours !== 0))
range2.push(`${remainderHours}h`);
if (time < HOUR || remainderMinutes !== 0)
range2.push(`${remainderMinutes}m`);
range2[0] = `${sign}${range2[0]}`;
return range2.join(" ");
}
formatPriceRangeValue(value, localeManager) {
return localeManager?.t("measurerPriceRangeValue", { value: Number(value.toFixed(2)) }) ?? `${value}`;
}
formatPriceRangePercentage(percentage, localeManager) {
return localeManager?.t("measurerPriceRangePercent", { value: percentage }) ?? `${percentage}`;
}
formatVolume(volume, localeManager) {
const volumeString = Number.isNaN(volume) ? "" : this.volumeFormatter.format(volume);
return localeManager?.t("measurerVolume", { value: volumeString }) ?? volumeString;
}
};
var QuickMeasurerStatisticsScene = class extends MeasurerStatisticsScene {
getDirectionStyles(datum) {
return this.verticalDirection === "down" ? datum.down.statistics : datum.up.statistics;
}
getTextStyles(datum) {
const styles = this.getDirectionStyles(datum);
return {
...super.getTextStyles(datum),
fill: styles.color,
fontFamily: styles.fontFamily,
fontSize: styles.fontSize,
fontStyle: styles.fontStyle,
fontWeight: styles.fontWeight
};
}
getDividerStyles(datum) {
const styles = this.getDirectionStyles(datum);
return {
stroke: styles.divider.stroke,
strokeOpacity: styles.divider.strokeOpacity,
strokeWidth: styles.divider.strokeWidth
};
}
getBackgroundStyles(datum) {
const styles = this.getDirectionStyles(datum);
return {
...super.getBackgroundStyles(datum),
fill: styles.fill,
stroke: styles.stroke,
strokeOpacity: styles.strokeOpacity,
strokeWidth: styles.strokeWidth
};
}
};
// packages/ag-charts-enterprise/src/features/annotations/measurer/measurerScene.ts
var MeasurerScene = class extends StartEndScene {
constructor() {
super();
this.type = "measurer";
this.horizontalLine = new CollidableLine();
this.verticalLine = new CollidableLine();
// These four bounding lines are named after the way they are drawn, e.g. the horizontalStartLine is a horizontal
// line that is only shown when the measurer has the 'vertical' direction.
this.horizontalStartLine = new CollidableLine();
this.horizontalEndLine = new CollidableLine();
this.verticalStartLine = new CollidableLine();
this.verticalEndLine = new CollidableLine();
this.horizontalEndCap = new ArrowCapScene();
this.verticalEndCap = new ArrowCapScene();
this.background = new _ModuleSupport57.Path({ zIndex: -1 });
this.updateBackground = WithBackgroundScene.updateBackground.bind(this);
this.statistics = this.createStatisticsScene();
this.statistics.zIndex = 1;
this.append([
this.background,
this.verticalStartLine,
this.verticalEndLine,
this.horizontalStartLine,
this.horizontalEndLine,
this.horizontalLine,
this.verticalLine,
this.horizontalEndCap,
this.verticalEndCap,
this.start,
this.end,
this.statistics
]);
}
static is(value) {
return AnnotationScene.isCheck(value, "measurer");
}
createStatisticsScene() {
return new MeasurerStatisticsScene();
}
update(datum, context) {
const coords = convertLine(datum, context);
if (coords == null) {
this.visible = false;
return;
}
this.visible = datum.visible ?? true;
if (!this.visible)
return;
const extended = this.extendPerpendicular(coords, datum, context);
const verticalStart = { ...extended, y2: extended.y1 };
const verticalEnd = { ...extended, y1: extended.y2 };
this.verticalDirection = coords.y1 < coords.y2 ? "down" : "up";
this.updateVisibilities(datum);
this.updateLines(datum, coords);
this.updateHandles(datum, coords);
this.updateText(datum, coords);
this.updateCaps(datum, coords);
this.updateBoundingLines(datum, extended);
this.updateBackground(datum, verticalStart, verticalEnd, context);
this.updateStatistics(datum, coords, context);
this.updateAnchor(datum, coords, context);
}
extendPerpendicular(coords, datum, context) {
const extended = {
x1: Math.min(coords.x1, coords.x2),
x2: Math.max(coords.x1, coords.x2),
y1: Math.min(coords.y1, coords.y2),
y2: Math.max(coords.y1, coords.y2)
};
const [start, end] = Vec216.from(context.yAxis.bounds);
if (DateRangeProperties.is(datum)) {
if (datum.extendAbove)
extended.y1 = start.y;
if (datum.extendBelow)
extended.y2 = end.y;
} else if (PriceRangeProperties.is(datum)) {
if (datum.extendLeft)
extended.x1 = start.x;
if (datum.extendRight)
extended.x2 = end.x;
}
return extended;
}
updateVisibilities(datum) {
const {
horizontalStartLine,
horizontalEndLine,
horizontalEndCap,
verticalStartLine,
verticalEndLine,
verticalEndCap
} = this;
const { direction } = datum;
verticalStartLine.visible = direction !== "vertical";
verticalEndLine.visible = direction !== "vertical";
horizontalEndCap.visible = direction !== "vertical";
horizontalStartLine.visible = direction !== "horizontal";
horizontalEndLine.visible = direction !== "horizontal";
verticalEndCap.visible = direction !== "horizontal";
}
updateLines(datum, coords) {
const { horizontalLine, verticalLine } = this;
const { direction } = datum;
const { x1, y1, x2, y2 } = coords;
const center = Vec216.round(Vec412.center(coords), 0);
const lineStyles = this.getLineStyles(datum);
if (direction !== "vertical") {
horizontalLine.setProperties({
...lineStyles,
x1,
x2,
y1: center.y,
y2: center.y
});
}
if (direction !== "horizontal") {
verticalLine.setProperties({
...lineStyles,
x1: center.x,
x2: center.x,
y1,
y2
});
}
}
updateText(datum, coords) {
const { direction } = datum;
const center = Vec216.round(Vec412.center(coords), 0);
let line;
const textCoords = { ...coords };
if (direction === "vertical") {
line = this.verticalLine;
textCoords.x1 = center.x;
textCoords.x2 = center.x;
} else {
line = this.horizontalLine;
textCoords.y1 = center.y;
textCoords.y2 = center.y;
}
this.text = this.updateNode(CollidableText, this.text, !!datum.text.label);
const { id } = line;
const clip = updateLineText(id, line, textCoords, datum.text, this.text, datum.text.label, datum.strokeWidth);
let verticalClipMask;
if (direction === "both" && clip && this.text) {
const textBBox = Vec412.from(this.text.getBBox());
const { offset } = clip.numbers;
const crossesVerticalLine = textBBox.x1 <= center.x + offset.x && textBBox.x2 >= center.x - offset.x;
if (crossesVerticalLine) {
verticalClipMask = {
x: center.x,
y: clip.clipMask.y,
radius: this.text.getBBox().height / 2 + Vec216.length(offset)
};
}
}
this.verticalLine.setClipMask(id, verticalClipMask);
}
updateCaps(datum, coords) {
const { horizontalEndCap, verticalEndCap } = this;
const { direction } = datum;
const { x1, y1, x2, y2 } = coords;
const center = Vec216.round(Vec412.center(coords), 0);
const { stroke: stroke3, strokeWidth, strokeOpacity } = this.getLineStyles(datum);
const capStyles = { stroke: stroke3, strokeWidth, strokeOpacity };
if (direction !== "vertical") {
const angle = x1 <= x2 ? 0 : Math.PI;
let x = x2;
if (direction === "horizontal") {
x += x1 <= x2 ? -2 : 2;
}
horizontalEndCap.update({ ...capStyles, x, y: center.y, angle });
}
if (direction !== "horizontal") {
const angle = y1 <= y2 ? Math.PI / 2 : Math.PI / -2;
let y = y2;
if (direction === "vertical") {
y += y1 <= y2 ? -2 : 2;
}
verticalEndCap.update({ ...capStyles, x: center.x, y, angle });
}
}
updateBoundingLines(datum, extendedCoords) {
const { verticalStartLine, verticalEndLine, horizontalStartLine, horizontalEndLine } = this;
const { direction } = datum;
const { x1, y1, x2, y2 } = extendedCoords;
const lineStyles = this.getLineStyles(datum);
if (direction === "horizontal") {
verticalStartLine.setProperties({ ...lineStyles, x1, y1, x2: x1, y2 });
verticalEndLine.setProperties({ ...lineStyles, x1: x2, y1, x2, y2 });
}
if (direction === "vertical") {
horizontalStartLine.setProperties({ ...lineStyles, x1, y1, x2, y2: y1 });
horizontalEndLine.setProperties({ ...lineStyles, x1, y1: y2, x2, y2 });
}
}
updateStatistics(datum, coords, context) {
const point = Vec216.add(Vec412.bottomCenter(coords), Vec216.from(0, 10));
const statistics = { volume: this.getVolume(datum) };
if (datum.hasPriceRange) {
statistics.priceRange = {
percentage: this.getPriceRangePercentage(datum),
value: this.getPriceRangeValue(datum)
};
}
if (datum.hasDateRange) {
statistics.dateRange = {
bars: this.getDateRangeBars(coords, context),
value: this.getDateRangeValue(datum)
};
}
this.statistics.update(datum, statistics, point, coords, context, this.verticalDirection, datum.localeManager);
}
updateAnchor(_datum, coords, _context, _bbox) {
const point = Vec412.topCenter(coords);
Vec216.apply(this.anchor, _ModuleSupport57.Transformable.toCanvasPoint(this.horizontalLine, point.x, point.y));
}
getBackgroundPoints(_datum, verticalStart, verticalEnd, _bounds) {
const [startStart, startEnd] = Vec216.from(verticalStart);
const [endStart, endEnd] = Vec216.from(verticalEnd);
return [startStart, startEnd, endEnd, endStart];
}
getLineStyles(datum) {
const { lineDashOffset, stroke: stroke3, strokeWidth, strokeOpacity } = datum;
return {
lineCap: datum.getLineCap(),
lineDash: datum.getLineDash(),
lineDashOffset,
stroke: stroke3,
strokeWidth,
strokeOpacity,
fillOpacity: 0
};
}
getBackgroundStyles(datum) {
const { background } = datum;
return {
fill: background.fill,
fillOpacity: background.fillOpacity
};
}
getHandleStyles(datum) {
return {
fill: datum.handle.fill,
stroke: datum.handle.stroke ?? datum.stroke,
strokeOpacity: datum.handle.strokeOpacity ?? datum.strokeOpacity,
strokeWidth: datum.handle.strokeWidth ?? datum.strokeWidth
};
}
containsPoint(x, y) {
const {
horizontalLine,
text: text2,
verticalLine,
horizontalStartLine,
horizontalEndLine,
verticalStartLine,
verticalEndLine
} = this;
return super.containsPoint(x, y) || horizontalLine.isPointInPath(x, y) || verticalLine.isPointInPath(x, y) || horizontalStartLine.visible && horizontalStartLine.isPointInPath(x, y) || horizontalEndLine.visible && horizontalEndLine.isPointInPath(x, y) || verticalStartLine.visible && verticalStartLine.isPointInPath(x, y) || verticalEndLine.visible && verticalEndLine.isPointInPath(x, y) || Boolean(text2?.containsPoint(x, y));
}
getNodeAtCoords(x, y) {
if (this.text?.containsPoint(x, y))
return "text";
if (this.start.containsPoint(x, y) || this.end.containsPoint(x, y))
return "handle";
return "line";
}
getDateRangeBars(coords, context) {
const { step } = context.xAxis.scale;
const sign = coords.x1 <= coords.x2 ? 1 : -1;
return step ? Math.round(Vec412.width(coords) / step) * sign : 0;
}
getDateRangeValue(datum) {
const start = getGroupingValue(datum.start.x);
const end = getGroupingValue(datum.end.x);
if (!isDate2(start) || !isDate2(end)) {
throw new Error("Can not create a date range measurement of non-date x-axis.");
}
return end.getTime() - start.getTime();
}
getPriceRangePercentage(datum) {
if (datum.start.y == null || datum.end.y == null) {
throw new Error("Can not create a price range measurement of a non-numeric y-axis");
}
const endY = getGroupingValue(datum.end.y);
const startY = getGroupingValue(datum.start.y);
if (!isNumber3(endY) || !isNumber3(startY)) {
throw new Error("Can not create a price range measurement of a non-numeric y-axis");
}
return (endY - startY) / startY;
}
getPriceRangeValue(datum) {
if (datum.start.y == null || datum.end.y == null) {
throw new Error("Can not create a price range measurement of a non-numeric y-axis");
}
const endY = getGroupingValue(datum.end.y);
const startY = getGroupingValue(datum.start.y);
if (!isNumber3(endY) || !isNumber3(startY)) {
throw new Error("Can not create a price range measurement of a non-numeric y-axis");
}
return endY - startY;
}
getVolume(datum) {
return datum.getVolume(datum.start.x, datum.end.x);
}
};
var QuickMeasurerScene = class extends MeasurerScene {
constructor() {
super(...arguments);
this.type = "quick-measurer";
}
static is(value) {
return AnnotationScene.isCheck(value, "quick-measurer");
}
createStatisticsScene() {
return new QuickMeasurerStatisticsScene();
}
getDirectionStyles(datum) {
return this.verticalDirection === "down" ? datum.down : datum.up;
}
getLineStyles(datum) {
const styles = this.getDirectionStyles(datum);
return {
...super.getLineStyles(datum),
stroke: styles.stroke,
strokeWidth: styles.strokeWidth,
strokeOpacity: styles.strokeOpacity
};
}
getBackgroundStyles(datum) {
const styles = this.getDirectionStyles(datum);
return {
fill: styles.fill,
fillOpacity: styles.fillOpacity
};
}
getHandleStyles(datum) {
const styles = this.getDirectionStyles(datum);
return {
fill: styles.handle.fill,
stroke: styles.handle.stroke ?? styles.stroke,
strokeOpacity: styles.handle.strokeOpacity ?? styles.strokeOpacity,
strokeWidth: styles.handle.strokeWidth ?? styles.strokeWidth
};
}
};
// packages/ag-charts-enterprise/src/features/annotations/measurer/measurerState.ts
import { Debug as Debug9, StateMachine as StateMachine9, StateMachineProperty as StateMachineProperty9 } from "ag-charts-core";
var MeasurerTypeStateMachine = class extends StateMachine9 {
constructor(ctx) {
const actionCreate = ({ point }) => {
const datum = this.createDatum();
datum.set({ start: point, end: point });
ctx.create(datum);
};
const actionEndUpdate = ({ point }) => {
const { datum, node } = this;
datum?.set({ end: point });
node?.toggleActive(true);
node?.toggleHandles({ end: false });
ctx.update();
};
const actionEndFinish = () => {
this.node?.toggleHandles({ end: true });
};
const actionCancel = () => ctx.delete();
const onExitEnd = () => {
ctx.showAnnotationOptions();
ctx.recordAction(`Create ${this.node?.type} annotation`);
};
super("start", {
start: {
reset: StateMachine9.parent,
click: {
target: "end",
action: actionCreate
},
drag: {
target: "end",
action: actionCreate
}
},
end: {
hover: actionEndUpdate,
drag: actionEndUpdate,
click: {
target: StateMachine9.parent,
action: actionEndFinish
},
dragEnd: {
target: StateMachine9.parent,
action: actionEndFinish
},
reset: {
target: StateMachine9.parent,
action: actionCancel
},
cancel: {
target: StateMachine9.parent,
action: actionCancel
},
onExit: onExitEnd
}
});
this.debug = Debug9.create(true, "annotations");
}
};
__decorateClass([
StateMachineProperty9()
], MeasurerTypeStateMachine.prototype, "datum", 2);
__decorateClass([
StateMachineProperty9()
], MeasurerTypeStateMachine.prototype, "node", 2);
var DateRangeStateMachine = class extends MeasurerTypeStateMachine {
createDatum() {
return new DateRangeProperties();
}
};
var PriceRangeStateMachine = class extends MeasurerTypeStateMachine {
createDatum() {
return new PriceRangeProperties();
}
};
var DatePriceRangeStateMachine = class extends MeasurerTypeStateMachine {
createDatum() {
return new DatePriceRangeProperties();
}
};
var QuickDatePriceRangeStateMachine = class extends MeasurerTypeStateMachine {
createDatum() {
return new QuickDatePriceRangeProperties();
}
};
// packages/ag-charts-enterprise/src/features/annotations/measurer/measurerConfig.ts
var dateRangeConfig = {
type: "date-range" /* DateRange */,
datum: DateRangeProperties,
scene: MeasurerScene,
isDatum: DateRangeProperties.is,
translate: (node, datum, translation, context) => {
if (DateRangeProperties.is(datum) && MeasurerScene.is(node)) {
node.translate(datum, translation, context);
}
},
copy: (node, datum, copiedDatum, context) => {
if (DateRangeProperties.is(datum) && DateRangeProperties.is(copiedDatum) && MeasurerScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (DateRangeProperties.is(datum) && MeasurerScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new DateRangeStateMachine({
...ctx,
create: createDatum("date-range" /* DateRange */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
var priceRangeConfig = {
type: "price-range" /* PriceRange */,
datum: PriceRangeProperties,
scene: MeasurerScene,
isDatum: PriceRangeProperties.is,
translate: (node, datum, translation, context) => {
if (PriceRangeProperties.is(datum) && MeasurerScene.is(node)) {
node.translate(datum, translation, context);
}
},
copy: (node, datum, copiedDatum, context) => {
if (PriceRangeProperties.is(datum) && PriceRangeProperties.is(copiedDatum) && MeasurerScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (PriceRangeProperties.is(datum) && MeasurerScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new PriceRangeStateMachine({
...ctx,
create: createDatum("date-range" /* DateRange */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
var datePriceRangeConfig = {
type: "date-price-range" /* DatePriceRange */,
datum: DatePriceRangeProperties,
scene: MeasurerScene,
isDatum: DatePriceRangeProperties.is,
translate: (node, datum, translation, context) => {
if (DatePriceRangeProperties.is(datum) && MeasurerScene.is(node)) {
node.translate(datum, translation, context);
}
},
copy: (node, datum, copiedDatum, context) => {
if (DatePriceRangeProperties.is(datum) && DatePriceRangeProperties.is(copiedDatum) && MeasurerScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (DatePriceRangeProperties.is(datum) && MeasurerScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new DatePriceRangeStateMachine({
...ctx,
create: createDatum("date-range" /* DateRange */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
var quickDatePriceRangeConfig = {
type: "quick-date-price-range" /* QuickDatePriceRange */,
datum: QuickDatePriceRangeProperties,
scene: QuickMeasurerScene,
isDatum: QuickDatePriceRangeProperties.is,
translate: (node, datum, translation, context) => {
if (QuickDatePriceRangeProperties.is(datum) && QuickMeasurerScene.is(node)) {
node.translate(datum, translation, context);
}
},
copy: (node, datum, copiedDatum, context) => {
if (QuickDatePriceRangeProperties.is(datum) && QuickDatePriceRangeProperties.is(copiedDatum) && QuickMeasurerScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (QuickDatePriceRangeProperties.is(datum) && QuickMeasurerScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new QuickDatePriceRangeStateMachine({
...ctx,
create: createDatum("quick-date-price-range" /* QuickDatePriceRange */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/note/noteScene.ts
import { _ModuleSupport as _ModuleSupport58 } from "ag-charts-community";
import { ZIndexMap as ZIndexMap4, calcLineHeight as calcLineHeight3, clamp as clamp4, wrapText as wrapText2 } from "ag-charts-core";
var NoteScene = class extends TextualPointScene {
constructor() {
super();
this.type = "note" /* Note */;
this.shape = new _ModuleSupport58.Rect();
this.iconBackground = new _ModuleSupport58.TranslatableSvgPath(
"M22 1.83333C22 0.820811 21.1792 0 20.1667 0H1.83333C0.820811 0 0 0.82081 0 1.83333V13.9868C0 14.9994 0.820811 15.8202 1.83333 15.8202L5.88971 15.8202C6.44575 15.8202 6.97175 16.0725 7.31971 16.5062L9.57006 19.3112C10.304 20.2259 11.6962 20.2259 12.4301 19.3112L14.6804 16.5062C15.0284 16.0725 15.5544 15.8202 16.1104 15.8202L20.1667 15.8202C21.1792 15.8202 22 14.9994 22 13.9868V1.83333Z"
);
this.iconLines = new _ModuleSupport58.TranslatableSvgPath(
"M17.1114 5.75C17.1114 6.16421 16.7756 6.5 16.3614 6.5H5.63916C5.22495 6.5 4.88916 6.16421 4.88916 5.75V5.75C4.88916 5.33579 5.22495 5 5.63916 5H16.3614C16.7756 5 17.1114 5.33579 17.1114 5.75V5.75ZM17.1114 9.25C17.1114 9.66421 16.7756 10 16.3614 10H5.63916C5.22495 10 4.88916 9.66421 4.88916 9.25V9.25C4.88916 8.83579 5.22495 8.5 5.63916 8.5H16.3614C16.7756 8.5 17.1114 8.83579 17.1114 9.25V9.25Z"
);
this.active = false;
this.shape.visible = false;
this.label.visible = false;
this.iconBackground.fillShadow = new _ModuleSupport58.DropShadow();
this.append([this.shape, this.label, this.iconBackground, this.iconLines, this.handle]);
}
static is(value) {
return AnnotationScene.isCheck(value, "note" /* Note */);
}
update(datum, context) {
this.updateIcon(datum, context);
super.update(datum, context);
}
getTextBBox(datum, coords, context) {
const bbox = super.getTextBBox(datum, coords, context);
bbox.x -= datum.width / 2;
bbox.x = clamp4(0, bbox.x, context.seriesRect.width - datum.width);
const padding2 = datum.getPadding().top;
const topY = bbox.y - LABEL_OFFSET - padding2 * 2;
const bottomY = bbox.y + DivariantHandle.HANDLE_SIZE + padding2 * 2;
if (topY - bbox.height - TOOLBAR_OFFSET < 0) {
bbox.y = bottomY;
datum.position = "top";
} else {
bbox.y = topY + padding2;
datum.position = "bottom";
}
return bbox;
}
updateLabel(datum, bbox) {
const labelVisibility = datum.visible === false ? false : this.label.visible;
super.updateLabel(datum, bbox);
this.label.visible = labelVisibility;
this.label.text = wrapText2(datum.text, {
maxWidth: 200,
font: datum,
textWrap: "always",
avoidOrphans: false
});
}
updateShape(datum, bbox) {
const { shape } = this;
shape.fill = datum.background.fill;
shape.fillOpacity = datum.background.fillOpacity ?? 1;
shape.stroke = datum.background.stroke;
shape.strokeOpacity = datum.background.strokeOpacity ?? 1;
shape.strokeWidth = datum.background.strokeWidth ?? 1;
shape.cornerRadius = 4;
const padding2 = datum.getPadding().top;
const isPositionTop = datum.position === "top";
shape.x = bbox.x - padding2;
shape.width = datum.width + padding2 * 2;
shape.height = bbox.height + padding2 * 2;
shape.y = bbox.y + (isPositionTop ? 0 : -bbox.height) - padding2;
}
updateIcon(datum, context) {
const { active, iconBackground, iconLines } = this;
const { x, y } = convertPoint(datum, context);
iconBackground.translationX = x - ICON_WIDTH / 2;
iconBackground.translationY = y - ICON_HEIGHT;
iconLines.translationX = iconBackground.translationX;
iconLines.translationY = iconBackground.translationY;
iconBackground.fill = datum.fill;
iconBackground.fillOpacity = datum.fillOpacity ?? 1;
iconBackground.stroke = datum.stroke;
iconBackground.strokeOpacity = datum.strokeOpacity ?? 1;
iconBackground.strokeWidth = datum.strokeWidth ?? 1;
iconLines.fill = datum.stroke;
if (active) {
iconBackground.fillShadow.color = datum.fill ?? "rgba(0, 0, 0, 0.22)";
} else {
iconBackground.fillShadow.color = "rgba(0, 0, 0, 0.22)";
}
}
updateAnchor(datum, bbox, context) {
const padding2 = datum.getPadding().top;
const isPositionTop = datum.position === "top";
const direction = isPositionTop ? 1 : -1;
return {
x: bbox.x + context.seriesRect.x + datum.width / 2,
y: bbox.y + context.seriesRect.y + direction * (bbox.height + padding2),
position: isPositionTop ? "below" : "above"
};
}
getLabelCoords(datum, bbox) {
const isPositionTop = datum.position === "top";
const padding2 = datum.getPadding().top + calcLineHeight3(datum.fontSize, ANNOTATION_TEXT_LINE_HEIGHT) / 2;
return { x: bbox.x, y: bbox.y + (isPositionTop ? padding2 / 2 : 0) };
}
getTextBaseline(datum) {
return datum.position === "top" ? "middle" : datum.position;
}
getHandleCoords(_datum, coords, _bbox) {
return {
x: coords.x,
y: coords.y + DivariantHandle.HANDLE_SIZE / 2 + 4
};
}
getHandleStyles(datum) {
return {
fill: datum.handle.fill,
stroke: datum.handle.stroke ?? datum.fill,
strokeOpacity: datum.handle.strokeOpacity,
strokeWidth: datum.handle.strokeWidth
};
}
toggleHovered(hovered, active, readOnly) {
super.toggleHovered(hovered, active, readOnly);
const visible = hovered || active && !readOnly;
this.label.visible = visible;
this.shape.visible = visible;
this.zIndex = visible ? ZIndexMap4.CHART_ANNOTATION_FOCUSED : ZIndexMap4.CHART_ANNOTATION;
}
toggleActive(active) {
super.toggleActive(active);
this.label.visible = active;
this.shape.visible = active;
this.active = active;
}
containsPoint(x, y) {
if (this.shape.visible && this.shape.containsPoint(x, y))
return true;
if (this.iconBackground.containsPoint(x, y))
return true;
return super.containsPoint(x, y);
}
};
// packages/ag-charts-enterprise/src/features/annotations/note/noteState.ts
var NoteStateMachine = class extends TextualPointStateMachine {
createDatum() {
return new NoteProperties();
}
};
// packages/ag-charts-enterprise/src/features/annotations/note/noteConfig.ts
var noteConfig = {
type: "note" /* Note */,
datum: NoteProperties,
scene: NoteScene,
isDatum: NoteProperties.is,
translate: (node, datum, transition, context) => {
if (NoteProperties.is(datum) && NoteScene.is(node))
node.translate(datum, transition, context);
},
copy: (node, datum, copiedDatum, context) => {
if (NoteProperties.is(datum) && NoteProperties.is(copiedDatum) && NoteScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (NoteProperties.is(datum) && NoteScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new NoteStateMachine({
...ctx,
create: createDatum("note" /* Note */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/parallel-channel/parallelChannelScene.ts
import { Vec2 as Vec217, Vec4 as Vec413 } from "ag-charts-core";
var ParallelChannelScene = class extends ChannelScene {
constructor() {
super();
this.type = "parallel-channel";
this.handles = {
topLeft: new DivariantHandle(),
topMiddle: new UnivariantHandle(),
topRight: new DivariantHandle(),
bottomLeft: new DivariantHandle(),
bottomMiddle: new UnivariantHandle(),
bottomRight: new DivariantHandle()
};
this.middleLine = new CollidableLine();
this.append([this.background, this.topLine, this.middleLine, this.bottomLine, ...Object.values(this.handles)]);
}
static is(value) {
return AnnotationScene.isCheck(value, "parallel-channel");
}
dragHandle(datum, target, context, snapping) {
const { activeHandle, handles } = this;
if (activeHandle == null)
return;
const { offset } = handles[activeHandle].drag(target);
handles[activeHandle].toggleDragging(true);
if (activeHandle === "topMiddle" || activeHandle === "bottomMiddle") {
offset.x = 0;
}
let translateVectors = [];
let allowSnapping = snapping;
switch (activeHandle) {
case "topLeft":
case "bottomLeft":
translateVectors = ["topLeft", "bottomLeft"];
break;
case "topMiddle":
translateVectors = ["topLeft", "topRight"];
offset.y -= UnivariantHandle.HANDLE_SIZE / 2;
allowSnapping = false;
break;
case "topRight":
case "bottomRight":
translateVectors = ["topRight", "bottomRight"];
break;
case "bottomMiddle":
translateVectors = ["bottomLeft", "bottomRight"];
offset.y -= UnivariantHandle.HANDLE_SIZE / 2;
allowSnapping = false;
break;
}
const top = convertLine(datum, context);
const bottom = convertLine(datum.bottom, context);
if (!top || !bottom)
return;
const vectors = {
topLeft: Vec413.start(top),
topRight: Vec413.end(top),
bottomLeft: Vec413.start(bottom),
bottomRight: Vec413.end(bottom)
};
const snap = {
vectors: {
topLeft: vectors.topRight,
bottomLeft: vectors.bottomRight,
topRight: vectors.topLeft,
bottomRight: vectors.bottomLeft
},
angle: datum.snapToAngle
};
const points = translate(vectors, offset, context, {
overflowContinuous: this.overflowContinuous,
translateVectors,
snap: allowSnapping ? snap : void 0
});
datum.start.x = points.topLeft.x;
datum.start.y = points.topLeft.y;
datum.end.x = points.topRight.x;
datum.end.y = points.topRight.y;
datum.height = points.topLeft.y - points.bottomLeft.y;
}
getTranslatePointsVectors(start, end) {
const { bottomLeft, topLeft } = this.handles;
const height = bottomLeft.getBBox().y - topLeft.getBBox().y;
const bottomStart = Vec217.add(start, Vec217.from(0, height));
const bottomEnd = Vec217.add(end, Vec217.from(0, height));
return { start, end, bottomStart, bottomEnd };
}
containsPoint(x, y) {
return super.containsPoint(x, y) || this.middleLine.visible && this.middleLine.strokeWidth > 0 && this.middleLine.containsPoint(x, y);
}
getNodeAtCoords(x, y) {
if (this.middleLine.visible && this.middleLine.strokeWidth > 0 && this.middleLine.containsPoint(x, y))
return "line";
return super.getNodeAtCoords(x, y);
}
updateLines(datum, top, bottom, context, naturalTop, naturalBottom) {
const { topLine, middleLine, bottomLine } = this;
const { lineDashOffset, stroke: stroke3, strokeOpacity, strokeWidth } = datum;
const lineDash = datum.getLineDash();
const lineStyles = {
lineCap: datum.getLineCap(),
lineDash,
lineDashOffset,
stroke: stroke3,
strokeOpacity,
strokeWidth
};
topLine.setProperties({ ...top, ...lineStyles });
bottomLine.setProperties({ ...bottom, ...lineStyles });
const middlePoints = this.extendLine(
{
x1: naturalTop.x1,
y1: naturalBottom.y1 + (naturalTop.y1 - naturalBottom.y1) / 2,
x2: naturalTop.x2,
y2: naturalBottom.y2 + (naturalTop.y2 - naturalBottom.y2) / 2
},
datum,
context
);
middleLine.setProperties({
...middlePoints,
lineDash: datum.middle.lineDash ?? lineDash,
lineDashOffset: datum.middle.lineDashOffset ?? lineDashOffset,
stroke: datum.middle.stroke ?? stroke3,
strokeOpacity: datum.middle.strokeOpacity ?? strokeOpacity,
strokeWidth: datum.middle.strokeWidth ?? strokeWidth,
visible: datum.middle.visible ?? true
});
}
updateHandles(datum, top, bottom) {
const {
handles: { topLeft, topMiddle, topRight, bottomLeft, bottomMiddle, bottomRight }
} = this;
const handleStyles = {
fill: datum.handle.fill,
stroke: datum.handle.stroke ?? datum.stroke,
strokeOpacity: datum.handle.strokeOpacity ?? datum.strokeOpacity,
strokeWidth: datum.handle.strokeWidth ?? datum.strokeWidth
};
topLeft.update({ ...handleStyles, ...Vec413.start(top) });
topRight.update({ ...handleStyles, ...Vec413.end(top) });
bottomLeft.update({ ...handleStyles, ...Vec413.start(bottom) });
bottomRight.update({ ...handleStyles, ...Vec413.end(bottom) });
topMiddle.update({
...handleStyles,
...Vec217.sub(Vec413.center(top), Vec217.from(topMiddle.handle.width / 2, topMiddle.handle.height / 2))
});
bottomMiddle.update({
...handleStyles,
...Vec217.sub(Vec413.center(bottom), Vec217.from(bottomMiddle.handle.width / 2, bottomMiddle.handle.height / 2))
});
}
updateText(datum, top, bottom) {
this.text = this.updateNode(CollidableText, this.text, !!datum.text.label);
updateChannelText(true, top, bottom, datum.text, datum.strokeWidth, this.text, datum.text.label);
}
getBackgroundPoints(datum, top, bottom, bounds) {
const isFlippedX = top.x1 > top.x2;
const isFlippedY = top.y1 > top.y2;
const outOfBoundsStart = top.x1 !== bottom.x1 && top.y1 !== bottom.y1;
const outOfBoundsEnd = top.x2 !== bottom.x2 && top.y2 !== bottom.y2;
const points = Vec217.from(top);
if (datum.extendEnd && outOfBoundsEnd) {
points.push(Vec217.from(isFlippedX ? bounds.x1 : bounds.x2, isFlippedY ? bounds.y1 : bounds.y2));
}
points.push(...Vec217.from(bottom).reverse());
if (datum.extendStart && outOfBoundsStart) {
points.push(Vec217.from(isFlippedX ? bounds.x2 : bounds.x1, isFlippedY ? bounds.y2 : bounds.y1));
}
return points;
}
};
// packages/ag-charts-enterprise/src/features/annotations/parallel-channel/parallelChannelState.ts
import { Debug as Debug10, StateMachine as StateMachine10, StateMachineProperty as StateMachineProperty10, isNumber as isNumber4 } from "ag-charts-core";
var ParallelChannelStateMachine = class extends StateMachine10 {
constructor(ctx) {
const actionCreate = ({ point }) => {
const datum = new ParallelChannelProperties();
datum.set({ start: point, end: point, height: 0 });
ctx.create(datum);
};
const actionFirstRender = () => {
const { node } = this;
node?.toggleActive(true);
node?.toggleHandles({
topLeft: true,
topMiddle: false,
topRight: false,
bottomLeft: false,
bottomMiddle: false,
bottomRight: false
});
};
const actionEndUpdate = ({ offset, context }) => {
const { datum, snapping } = this;
if (!datum)
return;
datum.set({ end: snapPoint(offset, context, snapping, datum.start, datum.snapToAngle) });
ctx.update();
};
const actionEndFinish = () => {
this.node?.toggleHandles({
topRight: true
});
ctx.update();
};
const actionHeightUpdate = ({ point }) => {
const { datum, node } = this;
const endY = getGroupingValue(datum?.end.y);
const startY = getGroupingValue(datum?.start.y);
const { y: pointY } = point;
if (datum == null || !isNumber4(startY) || !isNumber4(endY) || !isNumber4(pointY))
return;
const height = endY - (pointY ?? 0);
const bottomStartY = startY - height;
node?.toggleHandles({ bottomLeft: true, bottomRight: true });
if (!ctx.validatePoint({ x: datum.start.x, y: bottomStartY }, { overflowContinuous: true }) || !ctx.validatePoint({ x: datum.end.x, y: point.y }, { overflowContinuous: true })) {
return;
}
datum.set({ height });
ctx.update();
};
const actionHeightFinish = ({ point }) => {
const { datum, node } = this;
const endY = getGroupingValue(datum?.end.y);
const startY = getGroupingValue(datum?.start.y);
const { y: pointY } = point;
if (datum == null || !isNumber4(startY) || !isNumber4(endY) || !isNumber4(pointY))
return;
const height = endY - (pointY ?? 0);
const bottomStartY = startY - height;
node?.toggleHandles(true);
if (!ctx.validatePoint({ x: datum.start.x, y: bottomStartY }, { overflowContinuous: true }) || !ctx.validatePoint({ x: datum.end.x, y: point.y }, { overflowContinuous: true })) {
return;
}
datum.set({ height });
ctx.recordAction(`Create ${"parallel-channel" /* ParallelChannel */} annotation`);
ctx.showAnnotationOptions();
ctx.update();
};
const actionCancel = () => ctx.delete();
super("start", {
start: {
click: {
target: "waiting-first-render",
action: actionCreate
},
drag: {
target: "waiting-first-render",
action: actionCreate
},
reset: StateMachine10.parent
},
"waiting-first-render": {
render: {
target: "end",
action: actionFirstRender
}
},
end: {
hover: actionEndUpdate,
drag: actionEndUpdate,
click: {
target: "height",
action: actionEndFinish
},
dragEnd: {
target: "height",
action: actionEndFinish
},
reset: {
target: StateMachine10.parent,
action: actionCancel
},
cancel: {
target: StateMachine10.parent,
action: actionCancel
}
},
height: {
hover: actionHeightUpdate,
click: {
target: StateMachine10.parent,
action: actionHeightFinish
},
drag: {
target: StateMachine10.parent,
action: actionHeightFinish
},
reset: {
target: StateMachine10.parent,
action: actionCancel
},
cancel: {
target: StateMachine10.parent,
action: actionCancel
}
}
});
this.debug = Debug10.create(true, "annotations");
this.snapping = false;
}
};
__decorateClass([
StateMachineProperty10()
], ParallelChannelStateMachine.prototype, "datum", 2);
__decorateClass([
StateMachineProperty10()
], ParallelChannelStateMachine.prototype, "node", 2);
__decorateClass([
StateMachineProperty10()
], ParallelChannelStateMachine.prototype, "snapping", 2);
// packages/ag-charts-enterprise/src/features/annotations/parallel-channel/parallelChannelConfig.ts
var parallelChannelConfig = {
type: "parallel-channel" /* ParallelChannel */,
datum: ParallelChannelProperties,
scene: ParallelChannelScene,
isDatum: ParallelChannelProperties.is,
translate: (node, datum, transition, context) => {
if (ParallelChannelProperties.is(datum) && ParallelChannelScene.is(node)) {
node.translate(datum, transition, context);
}
},
copy: (node, datum, copiedDatum, context) => {
if (ParallelChannelProperties.is(datum) && ParallelChannelProperties.is(copiedDatum) && ParallelChannelScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (ParallelChannelProperties.is(datum) && ParallelChannelScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new ParallelChannelStateMachine({
...ctx,
create: createDatum("parallel-channel" /* ParallelChannel */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/text/textScene.ts
var TextScene = class extends TextualPointScene {
constructor() {
super();
this.type = "text" /* Text */;
this.append([this.label, this.handle]);
}
static is(value) {
return AnnotationScene.isCheck(value, "text" /* Text */);
}
getHandleCoords(_datum, point) {
const halfSize = DivariantHandle.HANDLE_SIZE / 2;
return {
x: point.x + halfSize,
y: point.y + 2 + halfSize
};
}
};
// packages/ag-charts-enterprise/src/features/annotations/text/textState.ts
var TextStateMachine = class extends TextualPointStateMachine {
createDatum() {
return new TextProperties();
}
};
// packages/ag-charts-enterprise/src/features/annotations/text/textConfig.ts
var textConfig = {
type: "text" /* Text */,
datum: TextProperties,
scene: TextScene,
isDatum: TextProperties.is,
translate: (node, datum, transition, context) => {
if (TextProperties.is(datum) && TextScene.is(node))
node.translate(datum, transition, context);
},
copy: (node, datum, copiedDatum, context) => {
if (TextProperties.is(datum) && TextProperties.is(copiedDatum) && TextScene.is(node)) {
return node.copy(datum, copiedDatum, context);
}
},
update: (node, datum, context) => {
if (TextProperties.is(datum) && TextScene.is(node)) {
node.update(datum, context);
}
},
createState: (ctx, { createDatum }) => new TextStateMachine({
...ctx,
create: createDatum("text" /* Text */)
}),
dragState: (ctx) => new DragStateMachine(ctx)
};
// packages/ag-charts-enterprise/src/features/annotations/annotationsConfig.ts
var annotationConfigs = {
// Lines
[lineConfig.type]: lineConfig,
[horizontalLineConfig.type]: horizontalLineConfig,
[verticalLineConfig.type]: verticalLineConfig,
// Channels
[parallelChannelConfig.type]: parallelChannelConfig,
[disjointChannelConfig.type]: disjointChannelConfig,
// Fibonaccis
[fibonacciRetracementConfig.type]: fibonacciRetracementConfig,
[fibonacciRetracementTrendBasedConfig.type]: fibonacciRetracementTrendBasedConfig,
// Texts
[calloutConfig.type]: calloutConfig,
[commentConfig.type]: commentConfig,
[noteConfig.type]: noteConfig,
[textConfig.type]: textConfig,
// Shapes
[arrowConfig.type]: arrowConfig,
[arrowUpConfig.type]: arrowUpConfig,
[arrowDownConfig.type]: arrowDownConfig,
// Measurers
[dateRangeConfig.type]: dateRangeConfig,
[priceRangeConfig.type]: priceRangeConfig,
[datePriceRangeConfig.type]: datePriceRangeConfig,
[quickDatePriceRangeConfig.type]: quickDatePriceRangeConfig
};
function getTypedDatum(datum) {
for (const { isDatum } of Object.values(annotationConfigs)) {
if (isDatum(datum)) {
return datum;
}
}
}
// packages/ag-charts-enterprise/src/features/annotations/annotationsStateMachine.ts
import "ag-charts-community";
import {
ActionOnSet as ActionOnSet3,
Debug as Debug11,
ParallelStateMachine,
StateMachine as StateMachine11,
StateMachineProperty as StateMachineProperty11
} from "ag-charts-core";
var AnnotationsStateMachine = class extends ParallelStateMachine {
constructor(ctx) {
super(
new SnappingStateMachine((snapping) => {
this.snapping = snapping;
}),
new UpdateMachine(() => {
this.node = this.active == null ? void 0 : ctx.node(this.active);
}),
new AnnotationsMainStateMachine(ctx, (index) => {
this.active = index;
this.datum = this.active == null ? void 0 : ctx.datum(this.active);
this.node = this.active == null ? void 0 : ctx.node(this.active);
})
);
this.snapping = false;
}
// TODO: remove this leak
getActive() {
return this.active;
}
// TODO: remove this leak
isActive(index) {
return index === this.active;
}
};
__decorateClass([
StateMachineProperty11()
], AnnotationsStateMachine.prototype, "snapping", 2);
__decorateClass([
StateMachineProperty11()
], AnnotationsStateMachine.prototype, "datum", 2);
__decorateClass([
StateMachineProperty11()
], AnnotationsStateMachine.prototype, "node", 2);
var SnappingStateMachine = class extends StateMachine11 {
constructor(setSnapping) {
super("idle" /* Idle */, {
["idle" /* Idle */]: {
hover: ({ shiftKey }) => setSnapping(shiftKey),
keyDown: ({ shiftKey }) => setSnapping(shiftKey),
keyUp: ({ shiftKey }) => setSnapping(shiftKey),
click: ({ shiftKey }) => setSnapping(shiftKey),
drag: ({ shiftKey }) => setSnapping(shiftKey)
},
["dragging" /* Dragging */]: {},
["translating" /* Translating */]: {},
["text-input" /* TextInput */]: {}
});
}
};
var UpdateMachine = class extends StateMachine11 {
constructor(update) {
super("idle" /* Idle */, {
["idle" /* Idle */]: {
onEnter: update,
render: update
},
["dragging" /* Dragging */]: {
onEnter: update,
render: update
},
["translating" /* Translating */]: {
onEnter: update,
render: update
},
["text-input" /* TextInput */]: {
render: update
}
});
}
};
var AnnotationsMainStateMachine = class extends StateMachine11 {
constructor(ctx, setActive) {
const createDatum = (type) => (datum) => {
ctx.create(type, datum);
this.active = ctx.selectLast();
};
const deleteDatum = () => {
if (this.active != null)
ctx.delete(this.active);
this.active = void 0;
ctx.select();
};
const stateMachineHelpers = {
createDatum
};
const createStateMachineContext = {
...ctx,
delete: deleteDatum,
showTextInput: () => {
if (this.active != null)
ctx.showTextInput(this.active);
},
deselect: () => {
const prevActive = this.active;
this.active = void 0;
this.hovered = void 0;
ctx.select(this.active, prevActive);
},
showAnnotationOptions: () => {
if (this.active != null)
ctx.showAnnotationOptions(this.active);
}
};
const createStateMachines = Object.fromEntries(
Object.entries(annotationConfigs).map(([type, config]) => [
type,
config.createState(createStateMachineContext, stateMachineHelpers)
])
);
const dragStateMachines = Object.fromEntries(
Object.entries(annotationConfigs).map(([type, config]) => [
type,
config.dragState(ctx, stateMachineHelpers)
])
);
const actionColor = ({
colorPickerType,
colorOpacity,
color: color7,
opacity,
isMultiColor
}) => {
if (!this.datum)
return;
if (colorPickerType === "text-color") {
ctx.updateTextInputColor(color7);
}
setColor(this.datum, colorPickerType, colorOpacity, color7, opacity, isMultiColor);
ctx.update();
};
const actionFontSize = (fontSize) => {
const { datum, node } = this;
if (!datum || !node)
return;
if (isTextType(datum)) {
datum.fontSize = fontSize;
ctx.updateTextInputFontSize(fontSize);
} else if (hasLineText(datum)) {
datum.text.fontSize = fontSize;
}
ctx.update();
};
const actionLineStyle = (lineStyle) => {
const { datum, node } = this;
if (!datum || !node || !hasLineStyle(datum))
return;
setLineStyle(datum, lineStyle);
ctx.update();
};
const actionUpdateTextInputBBox = (bbox) => {
const { node } = this;
if (!node || !("setTextInputBBox" in node))
return;
node.setTextInputBBox(bbox);
ctx.update();
};
const actionSaveText = ({ textInputValue, bbox }) => {
const { datum } = this;
if (bbox != null && textInputValue != null && textInputValue.length > 0) {
if (!isTextType(datum)) {
return;
}
const wrappedText = maybeWrapText(datum, textInputValue, bbox.width);
datum.set({ text: wrappedText });
ctx.update();
ctx.recordAction(`Change ${datum.type} annotation text`);
} else {
ctx.delete(this.active);
ctx.recordAction(`Delete ${datum?.type} annotation`);
}
};
const actionCancel = () => {
ctx.updateTextInputBBox(void 0);
};
const guardActive = () => this.active != null;
const guardCopied = () => this.copied != null;
const guardActiveHasLineText = () => {
const { active, datum } = this;
if (active == null)
return false;
if (!datum)
return false;
return hasLineText(datum) && datum.isWriteable();
};
const guardActiveNotEphemeral = () => this.active != null && !isEphemeralType(this.datum);
const guardHovered = () => this.hovered != null;
super("idle" /* Idle */, {
["idle" /* Idle */]: {
onEnter: () => {
ctx.select(this.active, this.active);
if (this.hoverCoords) {
this.hovered = ctx.hoverAtCoords(this.hoverCoords, this.active, this.hovered);
}
},
hover: ({ offset }) => {
this.hovered = ctx.hoverAtCoords(offset, this.active, this.hovered);
this.hoverCoords = offset;
},
translate: {
guard: guardActive,
target: "translating" /* Translating */,
action: ({ translation }) => {
ctx.startInteracting();
ctx.translate(this.active, translation);
ctx.update();
}
},
copy: {
guard: guardActiveNotEphemeral,
action: () => {
this.copied = ctx.copy(this.active);
}
},
cut: {
guard: guardActiveNotEphemeral,
action: () => {
this.copied = ctx.copy(this.active);
deleteDatum();
}
},
paste: {
guard: guardCopied,
action: () => {
ctx.paste(this.copied);
}
},
selectLast: () => {
const previousActive = this.active;
this.active = ctx.selectLast();
ctx.select(this.active, previousActive);
},
click: [
{
guard: () => {
const { active, hovered, datum } = this;
if (active == null || hovered !== active)
return false;
if (!datum)
return false;
return isTextType(datum) && datum.isWriteable();
},
target: "text-input" /* TextInput */
},
{
action: () => {
const prevActive = this.active;
this.active = this.hovered;
ctx.select(this.active, prevActive);
}
}
],
dblclick: {
guard: guardActiveHasLineText,
action: ({ offset }) => {
const nodeAtCoords = ctx.getNodeAtCoords(offset, this.active) === "text" ? "text" : "line";
ctx.showAnnotationSettings(this.active, void 0, nodeAtCoords);
}
},
dragStart: [
{
guard: guardHovered,
target: "dragging" /* Dragging */,
action: () => {
const prevActive = this.active;
this.active = this.hovered;
ctx.select(this.active, prevActive);
ctx.startInteracting();
}
},
{
action: () => {
const prevActive = this.active;
this.active = this.hovered;
ctx.select(this.active, prevActive);
}
}
],
color: {
guard: guardActive,
action: actionColor
},
fontSize: {
guard: guardActive,
action: actionFontSize
},
lineProps: {
guard: guardActive,
action: (props) => {
const datum = getTypedDatum(this.datum);
datum?.set(props);
ctx.update();
ctx.recordAction(
`Change ${datum?.type} ${Object.entries(props).map(([key, value]) => `${key} to ${value}`).join(", ")}`
);
}
},
lineStyle: {
guard: guardActive,
action: actionLineStyle
},
lineText: {
guard: guardActive,
action: (props) => {
const datum = getTypedDatum(this.datum);
if (!hasLineText(datum))
return;
if (isChannelType(datum) && props.position === "center") {
props.position = "inside";
}
datum.text.set(props);
ctx.update();
}
},
updateTextInputBBox: {
guard: guardActive,
action: actionUpdateTextInputBBox
},
toolbarPressSettings: {
guard: guardActiveHasLineText,
action: (sourceEvent) => {
ctx.showAnnotationSettings(this.active, sourceEvent);
}
},
reset: () => {
if (this.active != null) {
this.node?.toggleActive(false);
}
this.hovered = void 0;
this.active = void 0;
ctx.select(this.active, this.active);
ctx.resetToIdle();
},
delete: () => {
if (this.active == null)
return;
ctx.delete(this.active);
if (isEphemeralType(this.datum))
return;
ctx.recordAction(`Delete ${this.datum?.type} annotation`);
},
deleteAll: () => {
ctx.deleteAll();
},
...createStateMachines
},
["dragging" /* Dragging */]: {
onEnter: (_, data) => {
if (this.active == null)
return;
const type = ctx.getAnnotationType(this.active);
if (!type)
return;
this.transitionRoot(type);
this.transitionRoot("dragStart", data);
},
...dragStateMachines
},
["translating" /* Translating */]: {
onEnter: () => {
},
translate: {
guard: guardActive,
target: "translating" /* Translating */,
action: ({ translation }) => {
ctx.startInteracting();
ctx.translate(this.active, translation);
ctx.update();
}
},
translateEnd: {
guard: guardActive,
target: "idle" /* Idle */
},
onExit: () => {
ctx.stopInteracting();
ctx.update();
ctx.recordAction("Translate annotation");
}
},
["text-input" /* TextInput */]: {
onEnter: () => {
if (this.active == null)
return;
const datum = getTypedDatum(this.datum);
if (!datum || !("getTextInputCoords" in datum))
return;
ctx.startInteracting();
ctx.showTextInput(this.active);
datum.visible = false;
ctx.update();
},
updateTextInputBBox: {
guard: guardActive,
action: actionUpdateTextInputBBox
},
resize: {
target: "idle" /* Idle */,
action: actionSaveText
},
click: {
target: "idle" /* Idle */,
action: actionSaveText
},
drag: {
target: "idle" /* Idle */,
action: actionSaveText
},
textInput: [
{
guard: guardCancelAndExit,
target: "idle" /* Idle */,
action: actionCancel
},
{
guard: guardSaveAndExit,
target: "idle" /* Idle */,
action: actionSaveText
}
],
color: {
guard: guardActive,
action: actionColor
},
fontSize: {
guard: guardActive,
action: actionFontSize
},
cancel: {
target: "idle" /* Idle */,
action: actionCancel
},
onExit: () => {
ctx.stopInteracting();
ctx.hideTextInput();
const wasActive = this.active;
this.active = this.hovered = void 0;
ctx.select(this.active, wasActive);
if (wasActive == null)
return;
const datum = ctx.datum(wasActive);
const node = ctx.node(wasActive);
if (!datum || !node)
return;
datum.visible = true;
}
}
});
this.setActive = setActive;
this.debug = Debug11.create(true, "annotations");
this.snapping = false;
}
};
__decorateClass([
ActionOnSet3({
changeValue(newValue) {
this.setActive(newValue);
}
}),
StateMachineProperty11()
], AnnotationsMainStateMachine.prototype, "active", 2);
__decorateClass([
StateMachineProperty11()
], AnnotationsMainStateMachine.prototype, "hovered", 2);
__decorateClass([
StateMachineProperty11()
], AnnotationsMainStateMachine.prototype, "hoverCoords", 2);
__decorateClass([
StateMachineProperty11()
], AnnotationsMainStateMachine.prototype, "copied", 2);
__decorateClass([
StateMachineProperty11()
], AnnotationsMainStateMachine.prototype, "snapping", 2);
__decorateClass([
StateMachineProperty11()
], AnnotationsMainStateMachine.prototype, "datum", 2);
__decorateClass([
StateMachineProperty11()
], AnnotationsMainStateMachine.prototype, "node", 2);
// packages/ag-charts-enterprise/src/features/annotations/annotationsToolbar.ts
import { _ModuleSupport as _ModuleSupport60 } from "ag-charts-community";
import {
ActionOnSet as ActionOnSet4,
BaseProperties as BaseProperties15,
ChartAxisDirection as ChartAxisDirection7,
CleanupRegistry as CleanupRegistry3,
EventEmitter as EventEmitter2,
PropertiesArray as PropertiesArray2,
Property as Property35
} from "ag-charts-core";
var { LayoutElement, Menu: Menu2 } = _ModuleSupport60;
var AnnotationsToolbarButtonProperties = class extends ToolbarButtonProperties {
};
__decorateClass([
Property35
], AnnotationsToolbarButtonProperties.prototype, "value", 2);
var AnnotationsToolbar = class extends BaseProperties15 {
constructor(ctx) {
super();
this.ctx = ctx;
this.enabled = true;
this.padding = 20;
this.buttons = new PropertiesArray2(AnnotationsToolbarButtonProperties);
this.events = new EventEmitter2();
this.annotationMenu = new Menu2(this.ctx, "annotations");
this.cleanup = new CleanupRegistry3();
this.toolbar = ctx.sharedToolbar.getSharedToolbar("annotations");
const onKeyDown = this.onKeyDown.bind(this);
this.toolbar.addListener("keydown", onKeyDown);
this.cleanup.register(
this.toolbar.addToolbarListener("button-pressed", this.onToolbarButtonPress.bind(this)),
ctx.layoutManager.registerElement(LayoutElement.ToolbarLeft, this.onLayoutStart.bind(this)),
() => {
this.toolbar.removeListener("keydown", onKeyDown);
this.toolbar.destroy();
}
);
}
destroy() {
this.cleanup.flush();
}
toggleClearButtonEnabled(enabled) {
const index = this.buttons.findIndex((button) => button.value === "clear");
this.toolbar.toggleButtonEnabledByIndex(index, enabled);
}
resetButtonIcons() {
for (const [index, button] of this.buttons.entries()) {
switch (button.value) {
case "line-menu":
this.updateButtonByIndex(index, { icon: "trend-line-drawing", value: "line-menu" });
break;
case "fibonacci-menu":
this.updateButtonByIndex(index, { icon: "fibonacci-retracement-drawing", value: "fibonacci-menu" });
break;
case "text-menu":
this.updateButtonByIndex(index, { icon: "text-annotation", value: "text-menu" });
break;
case "shape-menu":
this.updateButtonByIndex(index, { icon: "arrow-drawing", value: "shape-menu" });
break;
case "measurer-menu":
this.updateButtonByIndex(index, { icon: "measurer-drawing", value: "measurer-menu" });
break;
}
}
}
hideOverlays() {
this.annotationMenu.hide();
}
clearActiveButton() {
this.toolbar.clearActiveButton();
}
onLayoutStart(ctx) {
if (!this.enabled)
return;
this.toolbar.updateButtons(this.buttons);
this.toolbar.layout(ctx.layoutBox, this.padding);
}
refreshButtonsEnabled(enabled) {
for (const [index, button] of this.buttons.entries()) {
if (!button)
continue;
this.toolbar.toggleButtonEnabledByIndex(index, enabled);
}
}
onToolbarButtonPress({
event,
button,
buttonBounds,
buttonWidget
}) {
const axisScale = this.ctx.axisManager.getAxisContext(ChartAxisDirection7.Y)[0].scale;
switch (button.value) {
case "clear":
this.events.emit("pressed-clear", null);
break;
case "line-menu":
this.onToolbarButtonPressShowMenu(
event,
buttonBounds,
buttonWidget,
button.value,
"toolbarAnnotationsLineAnnotations",
LINE_ANNOTATION_ITEMS.filter((item) => item.visible ? item.visible(axisScale) : true)
);
break;
case "fibonacci-menu":
this.onToolbarButtonPressShowMenu(
event,
buttonBounds,
buttonWidget,
button.value,
"toolbarAnnotationsFibonacciAnnotations",
FIBONACCI_ANNOTATION_ITEMS
);
break;
case "text-menu":
this.onToolbarButtonPressShowMenu(
event,
buttonBounds,
buttonWidget,
button.value,
"toolbarAnnotationsTextAnnotations",
TEXT_ANNOTATION_ITEMS
);
break;
case "shape-menu":
this.onToolbarButtonPressShowMenu(
event,
buttonBounds,
buttonWidget,
button.value,
"toolbarAnnotationsShapeAnnotations",
SHAPE_ANNOTATION_ITEMS
);
break;
case "measurer-menu":
this.onToolbarButtonPressShowMenu(
event,
buttonBounds,
buttonWidget,
button.value,
"toolbarAnnotationsMeasurerAnnotations",
MEASURER_ANNOTATION_ITEMS
);
break;
}
}
onToolbarButtonPressShowMenu(event, buttonBounds, controller, menu, ariaLabel, items) {
this.events.emit("pressed-show-menu", null);
const index = this.buttons.findIndex((button) => button.value === menu);
this.toolbar.toggleActiveButtonByIndex(index);
this.annotationMenu.setAnchor({ x: buttonBounds.x + buttonBounds.width + 6, y: buttonBounds.y });
this.annotationMenu.show(controller, {
items,
ariaLabel: this.ctx.localeManager.t(ariaLabel),
class: "ag-charts-annotations__toolbar-menu",
sourceEvent: event.sourceEvent,
onPress: this.onButtonPressMenuCreateAnnotation.bind(this, menu)
});
}
onButtonPressMenuCreateAnnotation(menu, item) {
const index = this.buttons.findIndex((button) => button.value === menu);
this.updateButtonByIndex(index, { icon: item.icon });
this.events.emit("pressed-create-annotation", { annotation: item.value });
this.annotationMenu.hide();
}
onKeyDown({ sourceEvent }) {
if (sourceEvent.key === "Escape") {
this.events.emit("cancel-create-annotation", null);
}
}
updateButtonByIndex(index, change) {
const button = this.buttons.at(index);
if (!button)
return;
button.set({ ...button.toJson(), ...change, value: change.value ?? button.value });
this.toolbar.updateButtonByIndex(index, { ...button.toJson() });
}
};
__decorateClass([
Property35,
ActionOnSet4({
changeValue(enabled) {
this.toolbar?.setHidden(!enabled);
}
})
], AnnotationsToolbar.prototype, "enabled", 2);
__decorateClass([
Property35
], AnnotationsToolbar.prototype, "padding", 2);
__decorateClass([
Property35
], AnnotationsToolbar.prototype, "buttons", 2);
// packages/ag-charts-enterprise/src/features/annotations/axisButton.ts
import { _ModuleSupport as _ModuleSupport61, _Widget as _Widget2 } from "ag-charts-community";
import { AbstractModuleInstance as AbstractModuleInstance3, ChartAxisDirection as ChartAxisDirection8, Property as Property36, getIconClassNames } from "ag-charts-core";
var { InteractionState } = _ModuleSupport61;
var DEFAULT_ANNOTATION_AXIS_BUTTON_CLASS = `ag-charts-annotations__axis-button`;
var AxisButton = class extends AbstractModuleInstance3 {
constructor(ctx, axisCtx, onButtonClick, seriesRect) {
super();
this.ctx = ctx;
this.axisCtx = axisCtx;
this.onButtonClick = onButtonClick;
this.seriesRect = seriesRect;
this.enabled = true;
this.snap = false;
this.padding = 0;
this.button = this.setup();
this.toggleVisibility(false);
this.updateButtonElement();
this.snap = Boolean(axisCtx.scale.bandwidth);
ctx.domManager.addEventListener("focusin", ({ target }) => {
const htmlTarget = target instanceof HTMLElement ? target : void 0;
const isSeriesAreaChild = htmlTarget && ctx.domManager.contains(htmlTarget, "series-area");
if (!isSeriesAreaChild && htmlTarget !== this.button.getElement())
this.hide();
});
this.cleanup.register(
ctx.widgets.seriesWidget.addListener("drag-move", (e) => this.onMouseDrag(e)),
ctx.widgets.seriesWidget.addListener("mousemove", (e) => this.onMouseMove(e)),
ctx.widgets.seriesWidget.addListener("mouseleave", () => this.onMouseLeave()),
ctx.widgets.seriesDragInterpreter?.events.on("click", (e) => this.onClick(e)),
ctx.eventsHub.on("series:focus-change", () => this.onKeyPress()),
ctx.eventsHub.on("zoom:pan-start", () => this.hide()),
ctx.eventsHub.on("zoom:change-complete", () => this.hide()),
() => this.destroyElements(),
() => this.button.destroy()
);
}
update(seriesRect, padding2) {
this.seriesRect = seriesRect;
this.padding = padding2;
}
setup() {
const button = new _Widget2.ButtonWidget();
button.addClass(DEFAULT_ANNOTATION_AXIS_BUTTON_CLASS);
button.setTabIndex(-1);
button.setAriaLabel(this.ctx.localeManager.t("ariaLabelAddHorizontalLine"));
this.ctx.widgets.seriesWidget.getElement().appendChild(button.getElement());
return button;
}
destroyElements() {
this.ctx.domManager.removeChild("canvas-overlay", DEFAULT_ANNOTATION_AXIS_BUTTON_CLASS);
}
onMouseMove(e) {
if (this.ctx.interactionManager.isState(InteractionState.Clickable))
this.show(e);
}
onMouseDrag(e) {
if (this.ctx.interactionManager.isState(InteractionState.AnnotationsMoveable))
this.show(e);
}
onMouseLeave() {
if (this.ctx.interactionManager.isState(InteractionState.Clickable))
this.hide();
}
onClick(e) {
if (this.ctx.interactionManager.isState(InteractionState.Clickable) && e.device === "touch")
this.show(e);
}
show(event) {
const { sourceEvent, currentX: x, currentY: y } = event;
if (!(this.enabled && this.ctx.widgets.seriesWidget.getElement().contains(sourceEvent.target))) {
this.hide();
return;
}
this.toggleVisibility(true);
const buttonCoords = this.getButtonCoordinates({ x, y });
this.coords = {
x: buttonCoords.x + this.button.clientWidth / 2,
y: buttonCoords.y + this.button.clientHeight / 2
};
this.updatePosition(buttonCoords);
}
hide() {
this.toggleVisibility(false);
}
onKeyPress() {
if (this.snap && this.ctx.interactionManager.isState(InteractionState.Default))
return;
this.hide();
}
getButtonCoordinates({ x, y }) {
const {
axisCtx: { direction, position },
seriesRect,
snap,
axisCtx,
padding: padding2
} = this;
const { clientWidth: buttonWidth, clientHeight: buttonHeight } = this.button;
const [minY, maxY] = [0, seriesRect.height];
const [minX, maxX] = [0, seriesRect.width];
if (snap) {
x = convert(invert(x - seriesRect.x, axisCtx), axisCtx) + seriesRect.x;
y = convert(invert(y - seriesRect.y, axisCtx), axisCtx) + seriesRect.y;
}
if (direction === ChartAxisDirection8.X) {
const crosshairLabelPadding = 5;
const offset = buttonHeight - Math.max(0, padding2 - crosshairLabelPadding);
x = x - buttonWidth / 2;
y = position === "top" ? minY - buttonHeight + offset : maxY - offset;
} else {
const crosshairLabelPadding = 9;
const offset = buttonWidth - Math.max(0, padding2 - crosshairLabelPadding);
x = position === "left" ? minX - buttonWidth + offset : maxX - offset;
y = y - buttonHeight / 2;
}
return { x, y };
}
toggleVisibility(visible) {
const { button } = this;
if (button == null)
return;
const isVisible = this.enabled && visible;
this.toggleClass("-hidden", !isVisible);
}
toggleClass(name, include) {
this.button.toggleClass(`${DEFAULT_ANNOTATION_AXIS_BUTTON_CLASS}-${name}`, include);
}
updatePosition({ x, y }) {
this.button.getElement().style.transform = `translate(${Math.round(x)}px, ${Math.round(y)}px)`;
}
updateButtonElement() {
const { button } = this;
button.addListener("click", () => this.onButtonClick(this.coords));
button.addListener("touchend", () => this.onButtonClick(this.coords));
button.addListener("drag-start", () => {
});
button.setInnerHTML(
`<span class="${getIconClassNames("zoom-in")} ${DEFAULT_ANNOTATION_AXIS_BUTTON_CLASS}-icon"></span>`
);
}
};
__decorateClass([
Property36
], AxisButton.prototype, "enabled", 2);
// packages/ag-charts-enterprise/src/features/annotations/settings-dialog/settingsDialog.ts
import "ag-charts-community";
import { EventEmitter as EventEmitter3, focusCursorAtEnd as focusCursorAtEnd2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/components/dialog/dialog.ts
import { _ModuleSupport as _ModuleSupport62 } from "ag-charts-community";
import {
Color as Color5,
Vec2 as Vec218,
createButton,
createCheckbox,
createElement as createElement4,
createElementId,
createSelect,
createTextArea,
entries as entries5,
getIconClassNames as getIconClassNames2,
getWindow as getWindow2,
initRovingTabIndex,
mapValues,
setAttribute,
setAttributes as setAttributes2
} from "ag-charts-core";
var { DraggablePopover, NativeWidget } = _ModuleSupport62;
var _Dialog = class _Dialog extends DraggablePopover {
constructor(ctx, id) {
super(ctx, id);
this.dragHandleDraggingClass = "ag-charts-dialog__drag-handle--dragging";
this.colorPicker = new ColorPicker(this.ctx, { detached: true });
this.cleanup.register(ctx.eventsHub.on("layout:complete", this.onLayoutComplete.bind(this)));
}
showWithChildren(children, options) {
const popover = super.showWithChildren(children, options);
popover.classList.add("ag-charts-dialog");
popover.setAttribute("role", "dialog");
popover.addEventListener("mousedown", (event) => {
if (event.target.classList?.contains("ag-charts-dialog__color-picker-button"))
return;
this.colorPicker.hide();
});
popover.addEventListener("keydown", this.onKeyDown.bind(this));
getWindow2().requestAnimationFrame(() => this.reposition());
this.colorPicker.attachTo(this);
return popover;
}
updatePosition(position) {
super.updatePosition(position);
const { anchor, fallbackAnchor } = this.getColorPickerAnchors() ?? {};
if (!anchor)
return;
this.colorPicker.setAnchor(anchor, fallbackAnchor);
}
/**************
* Containers *
**************/
createTabs(tablistLabel, initial, tabs) {
const element = createElement4("div", "ag-charts-dialog__tabs");
const tabButtonIds = mapValues(tabs, () => createElementId());
const tabPanelIds = mapValues(tabs, () => createElementId());
for (const [key, tab] of entries5(tabs)) {
setAttributes2(tab.panel, {
id: tabPanelIds[key],
role: "tabpanel",
"aria-labelledby": tabButtonIds[key]
});
}
const onPressTab = (active) => {
for (const [key, tab] of entries5(tabs)) {
tab.panel.classList.toggle("ag-charts-dialog__tab-panel--active", key === active);
tabButtons[key].classList.toggle("ag-charts-dialog__tab-button--active", key === active);
setAttribute(tabButtons[key], "aria-selected", key === active);
if (key === active)
tab.onShow?.();
}
};
const header = new NativeWidget(createElement4("div", "ag-charts-dialog__header"));
header.addListener("drag-start", (event) => {
const { sourceEvent } = event;
if (sourceEvent.target instanceof Element && sourceEvent.target.classList.contains("ag-charts-dialog__header")) {
this.onDragStart(event);
}
});
header.addListener("drag-move", (event) => this.onDragMove(event));
header.addListener("drag-end", () => this.onDragEnd());
const dragHandle = new DragHandleWidget();
this.setDragHandle(dragHandle);
const tabButtons = mapValues(
tabs,
(tab, key) => createButton(
{
label: this.ctx.localeManager.t(tab.label),
onPress: () => onPressTab(key)
},
{
id: tabButtonIds[key],
class: "ag-charts-dialog__tab-button",
role: "tab",
"aria-controls": tabPanelIds[key]
}
)
);
const tabList = createElement4("div", "ag-charts-dialog__tab-list");
setAttributes2(tabList, { role: "tablist", "aria-label": this.ctx.localeManager.t(tablistLabel) });
tabList.append(...Object.values(tabButtons));
const closeButton = this.createHeaderCloseButton();
header.getElement().append(dragHandle.getElement(), tabList, closeButton);
element.append(header.getElement(), ...Object.values(tabs).map((t) => t.panel));
onPressTab(initial);
initRovingTabIndex({ orientation: "horizontal", buttons: Object.values(tabButtons) });
return { tabs: element, initialFocus: tabButtons[initial] };
}
createTabPanel() {
return createElement4("div", "ag-charts-dialog__tab-panel");
}
/**********
* Inputs *
**********/
createInputGroupLine() {
return createElement4("div", "ag-charts-dialog__input-group-line");
}
createRadioGroup({ label, options, value, onChange }) {
const group = this.createInputGroup(label);
setAttributes2(group, {
role: "radiogroup",
tabindex: -1,
"aria-label": this.ctx.localeManager.t(label)
});
const activeClass = "ag-charts-dialog__button--active";
const buttons = [];
for (const button of options) {
const { icon, altText: altTextKey } = button;
const altText = this.ctx.localeManager.t(altTextKey);
const buttonEl = createButton(
{
icon,
altText,
onPress: () => {
for (const b of Array.from(group.children)) {
b.classList.remove(activeClass);
b.ariaChecked = "false";
}
buttonEl.classList.add(activeClass);
buttonEl.ariaChecked = "true";
onChange(button.value);
}
},
{
"aria-checked": button.value === value,
class: "ag-charts-dialog__button",
role: "radio",
title: altText
}
);
if (button.value === value) {
buttonEl.classList.add(activeClass);
}
group.appendChild(buttonEl);
buttons.push(buttonEl);
}
initRovingTabIndex({ orientation: "horizontal", buttons });
return group;
}
createSelect({ altText, label, options, value, onChange }) {
const group = this.createInputGroup(label);
const altTextT = this.ctx.localeManager.t(altText);
const select = createSelect(
{ value, options, onChange },
{ class: "ag-charts-dialog__select", "aria-label": altTextT, title: altTextT }
);
group.append(select);
return group;
}
createTextArea({ placeholder, value, onChange }) {
const placeholderT = placeholder ? this.ctx.localeManager.t(placeholder) : void 0;
return createTextArea({ value, onChange }, { placeholder: placeholderT });
}
createCheckbox({ label, checked, onChange }) {
const id = createElementId();
const group = this.createInputGroup(label, { for: id });
const checkbox = createCheckbox(
{ checked, onChange },
{ class: "ag-charts-dialog__checkbox", role: "switch", id }
);
group.append(checkbox);
return group;
}
createColorPicker({
color: color7,
opacity,
label,
altText,
onChange,
onChangeHide,
isMultiColor,
hasMultiColorOption
}) {
const group = this.createInputGroup(label);
const altTextT = this.ctx.localeManager.t(altText);
const colorEl = createButton(
{
label: altTextT,
onPress: (event) => {
const { anchor, fallbackAnchor } = this.getColorPickerAnchors(colorEl) ?? {};
this.colorPicker.show({
anchor,
fallbackAnchor,
color: color7,
opacity,
isMultiColor,
hasMultiColorOption,
sourceEvent: event,
onChange: (newColorOpacity, newColor, newOpacity, newIsMultiColor) => {
colorEl.style.setProperty("--color", newColorOpacity);
colorEl.classList.toggle(
"ag-charts-dialog__color-picker-button--multi-color",
newIsMultiColor
);
onChange(newColorOpacity, newColor, newOpacity, newIsMultiColor);
},
onChangeHide
});
}
},
{
"aria-label": altTextT,
tabindex: 0,
class: "ag-charts-dialog__color-picker-button",
title: altTextT
}
);
if (isMultiColor) {
colorEl.classList.toggle("ag-charts-dialog__color-picker-button--multi-color");
} else if (color7) {
const hex = Color5.fromString(color7);
const hexWithOpacity = new Color5(hex.r, hex.g, hex.b, opacity);
colorEl.style.setProperty("--color", hexWithOpacity.toHexString());
}
group.append(colorEl);
this.hideFns.push(() => {
this.colorPicker.hide();
});
return group;
}
/***********
* Private *
***********/
createHeaderCloseButton() {
return createButton(
{ icon: "close", altText: this.ctx.localeManager.t("iconAltTextClose"), onPress: () => this.hide() },
{ class: "ag-charts-dialog__close-button" }
);
}
createInputGroup(label, options) {
const group = createElement4("div", "ag-charts-dialog__input-group");
const labelEl = createElement4("label", "ag-charts-dialog__input-group-label");
labelEl.innerText = this.ctx.localeManager.t(label);
setAttribute(labelEl, "for", options?.for);
group.appendChild(labelEl);
return group;
}
onLayoutComplete(event) {
this.seriesRect = event.series.paddedRect;
this.reposition();
}
onKeyDown(event) {
if (event.altKey || event.ctrlKey || event.metaKey || event.isComposing || event.key !== "Escape")
return;
this.hide();
}
reposition() {
const { seriesRect, ctx } = this;
const popover = this.getPopoverElement();
if (!seriesRect || !popover)
return;
const clientRect = ctx.domManager.getBoundingClientRect();
const outerOffset = Vec218.from(0, seriesRect.y);
const outerSize = Vec218.from(clientRect.width, seriesRect.height);
const popoverSize = Vec218.from(popover);
const halfWidth = Vec218.from(0.5, 1);
let position;
if (seriesRect.width > 1e3) {
const bottomCenter = Vec218.sub(
Vec218.add(outerOffset, Vec218.multiply(outerSize, halfWidth)),
Vec218.multiply(popoverSize, halfWidth)
);
position = Vec218.sub(bottomCenter, Vec218.from(0, _Dialog.offset));
} else {
const bottomRight = Vec218.sub(Vec218.add(outerOffset, outerSize), popoverSize);
position = Vec218.sub(bottomRight, _Dialog.offset);
}
this.updatePosition(position);
}
getColorPickerAnchors(element) {
if (element)
this.colorPickerAnchorElement = element;
if (!this.colorPickerAnchorElement)
return;
const rect = this.colorPickerAnchorElement.getBoundingClientRect();
const canvasRect = this.ctx.domManager.getBoundingClientRect();
const topLeft = Vec218.sub(Vec218.from(rect.x, rect.y), Vec218.from(canvasRect.left, canvasRect.top));
const anchor = Vec218.add(topLeft, Vec218.from(0, rect.height + 5));
const fallbackAnchor = Vec218.sub(topLeft, Vec218.from(0, 5));
return { anchor, fallbackAnchor };
}
};
_Dialog.offset = 60;
var Dialog = _Dialog;
var DragHandleWidget = class extends NativeWidget {
constructor() {
super(createElement4("div", "ag-charts-dialog__drag-handle"));
const icon = new NativeWidget(createElement4("span", getIconClassNames2("drag-handle")));
icon.setAriaHidden(true);
this.addChild(icon);
}
};
// packages/ag-charts-enterprise/src/features/annotations/settings-dialog/settingsDialog.ts
var AnnotationSettingsDialog = class extends Dialog {
constructor(ctx) {
super(ctx, "settings");
this.events = new EventEmitter3();
this.hideFns.push(() => this.events.emit("hidden", null));
}
show(datum, options) {
const lineTab = this.createLinearLineTab(datum, options);
const textTab = this.createLinearTextTab(datum, options);
let lineLabel = "dialogHeaderLine";
if (isChannelType(datum)) {
lineLabel = "dialogHeaderChannel";
} else if (isFibonacciType(datum)) {
lineLabel = "dialogHeaderFibonacciRange";
} else if (datum.type === "date-range" /* DateRange */) {
lineLabel = "dialogHeaderDateRange";
} else if (datum.type === "price-range" /* PriceRange */) {
lineLabel = "dialogHeaderPriceRange";
} else if (datum.type === "date-price-range" /* DatePriceRange */) {
lineLabel = "dialogHeaderDatePriceRange";
}
const { tabs, initialFocus } = this.createTabs("ariaLabelSettingsTabBar", options.initialSelectedTab, {
line: {
label: lineLabel,
panel: lineTab
},
text: {
label: "dialogHeaderText",
panel: textTab.panel,
onShow: textTab.onShow
}
});
options.initialFocus = initialFocus;
const popover = this.showWithChildren([tabs], options);
popover.classList.add("ag-charts-dialog--annotation-settings");
}
createLinearLineTab(datum, options) {
const panel = this.createTabPanel();
const groupOne = this.createInputGroupLine();
const groupTwo = this.createInputGroupLine();
const hasMultiColorOption = "isMultiColor" in datum;
const lineColorPicker = this.createColorPickerInput(
"line-color",
datum.getDefaultColor("line-color"),
datum.getDefaultOpacity("line-color"),
hasMultiColorOption ? datum.isMultiColor : false,
hasMultiColorOption,
options.onChangeLineColor,
options.onChangeHideLineColor
);
const strokeWidth = this.createStrokeWidthSelect(datum.strokeWidth ?? 2, options.onChangeLineStyleWidth);
const lineStyle = this.createLineStyleRadioGroup(datum.lineStyle ?? "solid", options.onChangeLineStyleType);
groupOne.append(lineColorPicker);
if ("background" in datum) {
const fillColorPicker = this.createColorPickerInput(
"fill-color",
datum.getDefaultColor("fill-color"),
datum.getDefaultOpacity("fill-color"),
false,
false,
options.onChangeFillColor,
options.onChangeHideFillColor
);
groupOne.append(fillColorPicker);
groupTwo.append(strokeWidth);
} else if ("showFill" in datum) {
groupOne.append(
this.createCheckbox({
label: "dialogInputShowFill",
checked: datum.showFill ?? true,
onChange: (showFill) => options.onChangeLine({ showFill })
})
);
groupTwo.append(strokeWidth);
} else {
groupOne.append(strokeWidth);
}
groupTwo.append(lineStyle);
panel.append(groupOne, groupTwo);
if ("bands" in datum) {
panel.append(
this.createFibonacciRatioSelect(datum.bands ?? 10, (bands) => options.onChangeLine({ bands }))
);
}
if ("extendStart" in datum && "extendEnd" in datum) {
panel.append(
this.createCheckbox({
label: isChannelType(datum) ? "dialogInputExtendChannelStart" : "dialogInputExtendLineStart",
checked: datum.extendStart ?? false,
onChange: (extendStart) => options.onChangeLine({ extendStart })
}),
this.createCheckbox({
label: isChannelType(datum) ? "dialogInputExtendChannelEnd" : "dialogInputExtendLineEnd",
checked: datum.extendEnd ?? false,
onChange: (extendEnd) => options.onChangeLine({ extendEnd })
})
);
}
if ("extendAbove" in datum && "extendBelow" in datum) {
panel.append(
this.createCheckbox({
label: "dialogInputExtendAbove",
checked: datum.extendAbove ?? false,
onChange: (extendAbove) => options.onChangeLine({ extendAbove })
}),
this.createCheckbox({
label: "dialogInputExtendBelow",
checked: datum.extendBelow ?? false,
onChange: (extendBelow) => options.onChangeLine({ extendBelow })
})
);
}
if ("extendLeft" in datum && "extendRight" in datum) {
panel.append(
this.createCheckbox({
label: "dialogInputExtendLeft",
checked: datum.extendLeft ?? false,
onChange: (extendLeft) => options.onChangeLine({ extendLeft })
}),
this.createCheckbox({
label: "dialogInputExtendRight",
checked: datum.extendRight ?? false,
onChange: (extendRight) => options.onChangeLine({ extendRight })
})
);
}
if ("reverse" in datum && "showFill" in datum) {
panel.append(
this.createCheckbox({
label: "dialogInputReverse",
checked: datum.reverse ?? false,
onChange: (reverse) => options.onChangeLine({ reverse })
})
);
}
return panel;
}
createLinearTextTab(datum, options) {
const panel = this.createTabPanel();
const textArea = this.createTextArea({
placeholder: "inputTextareaPlaceholder",
value: datum.text.label,
onChange: (value) => options.onChangeText({ label: value })
});
const fontSize = this.createFontSizeSelect(datum.text.fontSize, options.onChangeTextFontSize);
const colorPicker = this.createColorPickerInput(
"text-color",
datum.text.color,
1,
false,
false,
options.onChangeTextColor,
options.onChangeHideTextColor
);
const textPosition = datum.text.position === "inside" ? "center" : datum.text.position;
const position = this.createPositionRadioGroup(
textPosition ?? "top",
(value) => options.onChangeText({ position: value })
);
const alignment = this.createAlignmentRadioGroup(
datum.text.alignment ?? "center",
(value) => options.onChangeText({ alignment: value })
);
const inputGroupLine = this.createInputGroupLine();
inputGroupLine.append(fontSize, colorPicker, position, alignment);
panel.append(textArea, inputGroupLine);
return { panel, onShow: () => focusCursorAtEnd2(textArea) };
}
createColorPickerInput(colorType, color7, opacity, isMultiColor, hasMultiColorOption, onChange, onChangeHide) {
const label = colorType === "fill-color" ? "dialogInputFillColorPicker" : "dialogInputColorPicker";
const altText = colorType === "fill-color" ? "dialogInputFillColorPickerAltText" : "dialogInputColorPickerAltText";
return this.createColorPicker({
label,
altText,
color: color7,
opacity,
isMultiColor,
hasMultiColorOption,
onChange,
onChangeHide
});
}
createStrokeWidthSelect(strokeWidth, onChange) {
return this.createSelect({
label: "dialogInputStrokeWidth",
altText: "dialogInputStrokeWidthAltText",
options: LINE_STROKE_WIDTH_ITEMS.map(({ label, value }) => ({ label, value: `${value}` })),
value: String(strokeWidth),
onChange: (value) => onChange(Number(value))
});
}
createFibonacciRatioSelect(bands, onChange) {
return this.createSelect({
label: "dialogInputFibonacciBands",
altText: "dialogInputFibonacciBandsAltText",
options: FIBONACCI_RATIO_ITEMS.map(({ label, value }) => ({ label, value: `${value}` })),
value: String(bands),
onChange: (value) => onChange(Number(value))
});
}
createLineStyleRadioGroup(lineStyle, onChange) {
return this.createRadioGroup({
label: "dialogInputLineStyle",
options: [
{ icon: "line-style-solid", altText: "iconAltTextLineStyleSolid", value: "solid" },
{ icon: "line-style-dashed", altText: "iconAltTextLineStyleDashed", value: "dashed" },
{ icon: "line-style-dotted", altText: "iconAltTextLineStyleDotted", value: "dotted" }
],
value: lineStyle,
onChange
});
}
createFontSizeSelect(fontSize, onChange) {
return this.createSelect({
label: "dialogInputFontSize",
altText: "dialogInputFontSizeAltText",
options: TEXT_SIZE_ITEMS.map(({ label, value }) => ({ label, value: String(value) })),
value: String(fontSize),
onChange: (value) => onChange(Number(value))
});
}
createPositionRadioGroup(position, onChange) {
return this.createRadioGroup({
label: "dialogInputPosition",
options: [
{ icon: "position-top", altText: "iconAltTextPositionTop", value: "top" },
{ icon: "position-center", altText: "iconAltTextPositionCenter", value: "center" },
{ icon: "position-bottom", altText: "iconAltTextPositionBottom", value: "bottom" }
],
value: position,
onChange
});
}
createAlignmentRadioGroup(alignment, onChange) {
return this.createRadioGroup({
label: "dialogInputAlign",
options: [
{ icon: "align-left", altText: "iconAltTextAlignLeft", value: "left" },
{ icon: "align-center", altText: "iconAltTextAlignCenter", value: "center" },
{ icon: "align-right", altText: "iconAltTextAlignRight", value: "right" }
],
value: alignment,
onChange
});
}
};
// packages/ag-charts-enterprise/src/features/annotations/utils/axis.ts
function calculateAxisLabelPadding(axisLayout) {
return axisLayout.gridPadding + axisLayout.seriesAreaPadding + axisLayout.tickSize + axisLayout.label.spacing;
}
// packages/ag-charts-enterprise/src/features/annotations/utils/update.ts
function updateAnnotation(node, datum, context) {
for (const { update } of Object.values(annotationConfigs)) {
update(node, datum, context);
}
}
// packages/ag-charts-enterprise/src/features/annotations/annotations.ts
var { InteractionState: InteractionState2, keyProperty, valueProperty, Selection: Selection3, BBox: BBox3 } = _ModuleSupport64;
var _Annotations = class _Annotations extends AbstractModuleInstance4 {
constructor(ctx) {
super();
this.ctx = ctx;
this.toolbar = new AnnotationsToolbar(this.ctx);
this.optionsToolbar = new AnnotationOptionsToolbar(this.ctx, () => {
const active = this.state.getActive();
if (active == null)
return;
return getTypedDatum(this.annotationData.at(active));
});
this.axesButtons = new AxesButtons();
this.enabled = true;
this.snap = false;
// Hidden options for use with measurer statistics
this.data = void 0;
this.xKey = void 0;
this.volumeKey = void 0;
this.annotationData = new PropertiesArray3(
_Annotations.createAnnotationDatum
);
this.defaults = new AnnotationDefaults();
this.container = new _ModuleSupport64.Group({ name: "static-annotations" });
this.annotations = new Selection3(
this.container,
this.createAnnotationScene.bind(this)
);
this.settingsDialog = new AnnotationSettingsDialog(this.ctx);
this.textInput = new TextInput(this.ctx);
this.postUpdateFns = [];
this.state = this.setupStateMachine();
this.setupListeners();
this.setupDOM();
this.ctx.historyManager.addMementoOriginator(ctx.annotationManager);
this.ctx.historyManager.addMementoOriginator(this.defaults);
this.textInput.setKeyDownHandler(this.onTextInput.bind(this));
this.cleanup.register(() => {
this.clear();
this.xAxis?.button?.destroy();
this.yAxis?.button?.destroy();
this.textInput.destroy();
});
}
setupStateMachine() {
const { ctx } = this;
return new AnnotationsStateMachine({
resetToIdle: () => {
ctx.domManager.updateCursor("annotations");
this.popAnnotationState(InteractionState2.Annotations);
this.hideOverlays();
this.optionsToolbar.hide();
this.deleteEphemeralAnnotations();
this.update();
},
hoverAtCoords: (coords, active, previousHovered) => {
let hovered;
this.annotations.each((annotation, datum, index) => {
if (!datum.isHoverable())
return;
const contains = annotation.containsPoint(coords.x, coords.y);
if (contains)
hovered ?? (hovered = index);
annotation.toggleHovered(contains, active === index, datum.readOnly);
});
if (hovered != null) {
ctx.tooltipManager.suppressTooltip("annotations");
} else if (!this.isAnnotationState()) {
ctx.tooltipManager.unsuppressTooltip("annotations");
}
if (hovered == null || !this.annotationData.at(hovered)?.readOnly) {
this.ctx.domManager.updateCursor(
"annotations",
hovered == null ? void 0 : this.annotations.at(hovered)?.getCursor()
);
}
if (hovered !== previousHovered) {
this.update();
}
return hovered;
},
getNodeAtCoords: (coords, active) => {
const node = this.annotations.at(active);
if (!node) {
return;
}
return node.getNodeAtCoords(coords.x, coords.y);
},
translate: (index, translation) => {
const node = this.annotations.at(index);
const datum = getTypedDatum(this.annotationData.at(index));
if (!node || !datum) {
return;
}
return this.translateNode(node, datum, translation);
},
copy: (index) => {
const node = this.annotations.at(index);
const datum = getTypedDatum(this.annotationData.at(index));
if (!node || !datum) {
return;
}
return this.createAnnotationDatumCopy(node, datum);
},
paste: (datum) => {
this.createAnnotation(datum.type, datum, false);
this.postUpdateFns.push(() => {
this.state.transitionAsync("selectLast");
this.state.transitionAsync("copy");
});
},
select: (index, previous) => {
const { annotations, optionsToolbar: optionsToolbar2, toolbar: toolbar2 } = this;
this.hideOverlays();
toolbar2.clearActiveButton();
toolbar2.resetButtonIcons();
const selectedNode = index == null ? null : annotations.at(index);
const previousNode = previous == null ? null : annotations.at(previous);
const selectedDatum = index == null ? null : this.annotationData.at(index);
if (previousNode === selectedNode && selectedNode != null) {
return;
}
previousNode?.toggleActive(false);
optionsToolbar2.hide();
if (selectedNode && !selectedDatum?.readOnly) {
this.pushAnnotationState(InteractionState2.AnnotationsSelected);
selectedNode.toggleActive(true);
if (!isEphemeralType(selectedDatum)) {
optionsToolbar2.updateButtons(this.annotationData.at(index));
this.postUpdateFns.push(() => {
optionsToolbar2.show();
optionsToolbar2.setAnchorScene(selectedNode);
});
}
} else {
this.popAnnotationState(InteractionState2.AnnotationsSelected);
this.popAnnotationState(InteractionState2.Annotations);
}
if (!isEphemeralType(selectedDatum)) {
this.deleteEphemeralAnnotations();
}
this.update();
},
selectLast: () => {
this.pushAnnotationState(InteractionState2.AnnotationsSelected);
return this.annotationData.length - 1;
},
startInteracting: () => {
this.pushAnnotationState(InteractionState2.Annotations);
},
stopInteracting: () => {
this.popAnnotationState(InteractionState2.Annotations);
},
create: (type, datum) => {
this.createAnnotation(type, datum);
},
delete: (index) => {
this.annotationData.splice(index, 1);
},
deleteAll: () => {
const readOnly = this.annotationData.filter((datum) => {
if (datum.readOnly === true)
return datum;
});
this.annotationData.splice(0, this.annotationData.length);
for (const datum of readOnly) {
this.annotationData.push(datum);
}
},
validatePoint: (point, options) => {
const context = this.getAnnotationContext();
return context ? validateDatumPoint(context, point, options) : true;
},
getAnnotationType: (index) => {
return stringToAnnotationType(this.annotationData[index].type);
},
datum: (index) => {
return this.annotationData.at(index);
},
node: (index) => {
return this.annotations.at(index);
},
recordAction: (label) => {
this.recordActionAfterNextUpdate(label);
},
update: () => {
this.postUpdateFns.push(() => {
const active = this.state.getActive();
const node = active == null ? null : this.annotations.at(active);
if (node == null)
return;
this.optionsToolbar.setAnchorScene(node);
});
this.update();
},
showTextInput: (active) => {
const datum = getTypedDatum(this.annotationData.at(active));
const node = this.annotations.at(active);
if (!node || !datum || !("getTextInputCoords" in datum) || !("getTextPosition" in datum))
return;
const styles = {
color: datum.color,
fontFamily: datum.fontFamily,
fontSize: datum.fontSize,
fontStyle: datum.fontStyle,
fontWeight: datum.fontWeight,
placeholderColor: datum.getPlaceholderColor()
};
const context = this.getAnnotationContext();
const getTextInputCoords = (height) => Vec219.add(datum.getTextInputCoords(context, height), Vec219.required(this.seriesRect));
const getTextPosition = () => datum.getTextPosition();
this.textInput.show({
styles,
layout: {
getTextInputCoords,
getTextPosition,
alignment: datum.alignment,
textAlign: datum.textAlign,
width: datum.width
},
text: datum.text,
placeholderText: datum.placeholderText,
onChange: (_text, bbox) => {
this.state.transition("updateTextInputBBox", bbox);
}
});
this.ctx.domManager.updateCursor("annotations");
},
hideTextInput: () => {
this.textInput.hide();
},
updateTextInputColor: (color7) => {
this.textInput.updateColor(color7);
},
updateTextInputFontSize: (fontSize) => {
const bbox = this.textInput.updateFontSize(fontSize);
this.state.transition("updateTextInputBBox", bbox);
},
updateTextInputBBox: (bbox) => {
this.state.transition("updateTextInputBBox", bbox);
},
showAnnotationOptions: (active) => {
const node = this.annotations.at(active);
if (!node || isEphemeralType(this.annotationData.at(active)))
return;
this.optionsToolbar.updateButtons(this.annotationData.at(active));
this.optionsToolbar.show();
this.optionsToolbar.setAnchorScene(node);
},
showAnnotationSettings: (active, sourceEvent, initialTab = "line") => {
const datum = this.annotationData.at(active);
if (!isLineType(datum) && !isChannelType(datum) && !isMeasurerType(datum))
return;
if (isEphemeralType(datum))
return;
const onChangeColor = (colorType) => (colorOpacity, color7, opacity, isMultiColor) => {
this.setColorAndDefault(datum.type, colorType, colorOpacity, color7, opacity, isMultiColor);
this.optionsToolbar.updateColorPickerColor(colorType, color7, opacity, isMultiColor);
};
const onChangeHideColor = (colorType) => () => {
this.recordActionAfterNextUpdate(
`Change ${datum.type} ${colorType} to ${datum.getDefaultColor(colorType)}`,
["annotations", "defaults"]
);
this.update();
};
const options = {
initialSelectedTab: initialTab,
ariaLabel: this.ctx.localeManager.t("ariaLabelAnnotationSettingsDialog"),
sourceEvent,
onChangeLine: (props) => {
this.state.transition("lineProps", props);
if (props.bands != null)
this.defaults.setDefaultFibonacciOptions(datum.type, "bands", props.bands);
if (props.reverse != null)
this.defaults.setDefaultFibonacciOptions(datum.type, "reverse", props.reverse);
if (props.showFill != null)
this.defaults.setDefaultFibonacciOptions(datum.type, "showFill", props.showFill);
},
onChangeText: (props) => {
this.state.transition("lineText", props);
if (props.alignment)
this.defaults.setDefaultLineTextAlignment(datum.type, props.alignment);
if (props.position)
this.defaults.setDefaultLineTextPosition(datum.type, props.position);
this.recordActionAfterNextUpdate(
`Change ${datum.type} text ${Object.keys(props).map((key) => `${key} to ${props[key]}`).join(", ")}`
);
},
onChangeFillColor: onChangeColor("fill-color"),
onChangeHideFillColor: onChangeHideColor("fill-color"),
onChangeLineColor: onChangeColor("line-color"),
onChangeHideLineColor: onChangeHideColor("line-color"),
onChangeLineStyleType: (lineStyleType) => {
this.setLineStyleTypeAndDefault(datum.type, lineStyleType);
this.optionsToolbar.updateLineStyleType(
LINE_STYLE_TYPE_ITEMS.find((item) => item.value === lineStyleType) ?? LINE_STYLE_TYPE_ITEMS[0]
);
},
onChangeLineStyleWidth: (strokeWidth) => {
this.setLineStyleWidthAndDefault(datum.type, strokeWidth);
this.optionsToolbar.updateStrokeWidth({
strokeWidth,
value: strokeWidth,
label: String(strokeWidth)
});
},
onChangeTextColor: onChangeColor("text-color"),
onChangeHideTextColor: onChangeHideColor("text-color"),
onChangeTextFontSize: (fontSize) => {
this.setFontSizeAndDefault(datum.type, fontSize);
}
};
this.settingsDialog.show(datum, options);
}
});
}
setupListeners() {
const { ctx, optionsToolbar: optionsToolbar2, settingsDialog, toolbar: toolbar2 } = this;
const { seriesWidget, seriesDragInterpreter, chartWidget } = ctx.widgets;
if (seriesDragInterpreter) {
this.cleanup.register(
// Interactions
seriesDragInterpreter.events.on("click", this.hoverTouchPreHandler.bind(this)),
seriesDragInterpreter.events.on("drag-start", this.hoverTouchPreHandler.bind(this)),
seriesDragInterpreter.events.on("drag-move", this.dragMoveTouchPreHandler.bind(this)),
seriesDragInterpreter.events.on("mousemove", this.onHover.bind(this)),
seriesDragInterpreter.events.on("click", this.onClick.bind(this)),
seriesDragInterpreter.events.on("dblclick", this.onDoubleClick.bind(this)),
seriesDragInterpreter.events.on("drag-start", this.onDragStart.bind(this)),
seriesDragInterpreter.events.on("drag-move", this.onDrag.bind(this)),
seriesDragInterpreter.events.on("drag-end", this.onDragEnd.bind(this))
);
}
this.cleanup.register(
// Interactions
seriesWidget.addListener("keydown", this.onKeyDown.bind(this)),
seriesWidget.addListener("keyup", this.onKeyUp.bind(this)),
chartWidget.addListener("click", this.onCancel.bind(this)),
// Services
ctx.eventsHub.on("annotations:restore", this.onRestoreAnnotations.bind(this)),
ctx.eventsHub.on("layout:complete", this.onLayoutComplete.bind(this)),
ctx.updateService.addListener("pre-scene-render", this.onPreRender.bind(this)),
ctx.eventsHub.on("zoom:change-complete", () => this.onResize()),
ctx.eventsHub.on("dom:resize", () => this.onResize()),
// Toolbar
toolbar2.events.on("cancel-create-annotation", () => {
this.cancel();
this.reset();
this.update();
}),
toolbar2.events.on("pressed-create-annotation", ({ annotation }) => {
this.cancel();
this.pushAnnotationState(InteractionState2.Annotations);
this.state.transition(annotation);
this.update();
}),
toolbar2.events.on("pressed-clear", () => {
this.clear();
this.recordActionAfterNextUpdate("Clear all");
}),
toolbar2.events.on("pressed-show-menu", () => {
this.cancel();
this.reset();
}),
toolbar2.events.on("pressed-unrelated", () => {
this.reset();
}),
// Annotation Options Toolbar
optionsToolbar2.events.on("pressed-delete", () => {
this.cancel();
this.delete();
this.reset();
}),
optionsToolbar2.events.on("pressed-settings", ({ sourceEvent }) => {
this.state.transition("toolbarPressSettings", sourceEvent);
}),
optionsToolbar2.events.on("pressed-lock", ({ locked }) => {
this.recordActionAfterNextUpdate(locked ? "Locked" : "Unlocked");
this.update();
}),
optionsToolbar2.events.on("hid-overlays", () => {
this.settingsDialog.hide();
}),
optionsToolbar2.events.on("saved-color", ({ type, colorPickerType, color: color7 }) => {
this.recordActionAfterNextUpdate(`Change ${type} ${colorPickerType} to ${color7}`, [
"annotations",
"defaults"
]);
}),
optionsToolbar2.events.on(
"updated-color",
({ type, colorPickerType, colorOpacity, color: color7, opacity, isMultiColor }) => {
this.setColorAndDefault(type, colorPickerType, colorOpacity, color7, opacity, isMultiColor);
}
),
optionsToolbar2.events.on("updated-font-size", ({ type, fontSize }) => {
this.setFontSizeAndDefault(type, fontSize);
}),
optionsToolbar2.events.on("updated-line-style", ({ type, lineStyleType }) => {
this.setLineStyleTypeAndDefault(type, lineStyleType);
}),
optionsToolbar2.events.on("updated-line-width", ({ type, strokeWidth }) => {
this.setLineStyleWidthAndDefault(type, strokeWidth);
}),
// Settings Dialog
settingsDialog.events.on("hidden", () => {
this.optionsToolbar.clearActiveButton();
})
);
}
setupDOM() {
const { ctx, toolbar: toolbar2, optionsToolbar: optionsToolbar2 } = this;
this.cleanup.register(ctx.annotationManager.attachNode(this.container), () => {
ctx.domManager.removeStyles(DEFAULT_ANNOTATION_AXIS_BUTTON_CLASS);
toolbar2.destroy();
optionsToolbar2.destroy();
});
}
async processData(dataController) {
if (!this.enabled || this.data == null || this.xKey == null || this.volumeKey == null)
return;
const props = [
keyProperty(this.xKey, void 0, { id: "date" }),
valueProperty(this.volumeKey, "number", { id: "volume" })
];
const dataSet = _ModuleSupport64.DataSet.wrap(this.data) ?? _ModuleSupport64.DataSet.empty();
const { dataModel, processedData } = await dataController.request("annotations", dataSet, {
props
});
this.dataModel = dataModel;
this.processedData = processedData;
}
/**
* Create an annotation scene within the `this.annotations` scene selection. This method is automatically called by
* the selection when a new scene is required.
*/
createAnnotationScene(datum) {
if (datum.type in annotationConfigs) {
return new annotationConfigs[datum.type].scene();
}
throw new Error(
`AG Charts - Cannot create annotation scene of type [${datum.type}], expected one of [${Object.keys(annotationConfigs)}], ignoring.`
);
}
/**
* Create an annotation datum within the `this.annotationData` properties array. It is created as an instance
* of `AnnotationProperties` from the given config for its type. This method is only called when annotations
* are added from the initial state.
*/
static createAnnotationDatum(params) {
if (params.type in annotationConfigs) {
return new annotationConfigs[params.type].datum().set(params);
}
throw new Error(
`AG Charts - Cannot create annotation datum of unknown type [${params.type}], expected one of [${Object.keys(annotationConfigs)}], ignoring.`
);
}
/**
* Append an annotation datum to `this.annotationData`, applying default styles. This method is called when a user
* interacts with the chart to draw their own annotations.
*/
createAnnotation(type, datum, applyDefaults = true) {
this.annotationData.push(datum);
if (applyDefaults) {
const styles = this.ctx.annotationManager.getAnnotationTypeStyles(type);
if (styles)
datum.set(styles);
this.defaults.applyDefaults(datum);
}
this.injectDatumDependencies(datum);
this.update();
}
injectDatumDependencies(datum) {
if ("setLocaleManager" in datum) {
datum.setLocaleManager(this.ctx.localeManager);
}
if ("getVolume" in datum) {
datum.getVolume = this.getDatumRangeVolume.bind(this);
}
}
getDatumRangeVolume(fromPoint, toPoint) {
const { dataModel, processedData } = this;
let from = getGroupingValue(fromPoint);
let to = getGroupingValue(toPoint);
if (!isValidDate(from) || !isValidDate(to) || !dataModel || !processedData || this.volumeKey == null)
return;
if (from > to) {
[from, to] = [to, from];
}
const dateValues = dataModel.resolveKeysById({ id: "annotations" }, "date", processedData);
const volumeValues = dataModel.resolveColumnById({ id: "annotations" }, "volume", processedData);
let sum = 0;
for (let datumIndex = 0; datumIndex < processedData.input.count; datumIndex++) {
const key = dateValues[datumIndex];
if (isValidDate(key) && key >= from && key <= to) {
sum += volumeValues[datumIndex];
}
}
return sum;
}
translateNode(node, datum, translation) {
const config = this.getAnnotationConfig(datum);
const context = this.getAnnotationContext();
if (!context) {
return;
}
config.translate(node, datum, translation, context);
}
createAnnotationDatumCopy(node, datum) {
const config = this.getAnnotationConfig(datum);
const newDatum = new config.datum();
newDatum.set(datum.toJson());
const context = this.getAnnotationContext();
if (!context) {
return;
}
return config.copy(node, datum, newDatum, context);
}
getAnnotationConfig(datum) {
if (datum.type in annotationConfigs) {
return annotationConfigs[datum.type];
}
throw new Error(
`AG Charts - Cannot get annotation config of unknown type [${datum.type}], expected one of [${Object.keys(annotationConfigs)}], ignoring.`
);
}
onRestoreAnnotations(event) {
if (!this.enabled)
return;
this.clear();
this.annotationData.set(event.annotations);
this.postUpdateFns.push(() => {
this.ctx.annotationManager.fireChangedEvent();
});
this.update();
}
onLayoutComplete(event) {
if (!this.enabled)
return;
const seriesRect = event.series.paddedRect;
this.seriesRect = seriesRect;
this.container.setClipRect(seriesRect);
this.xAxis = this.getAxis(event.axes[ChartAxisDirection9.X], seriesRect, this.xAxis?.button);
this.yAxis = this.getAxis(event.axes[ChartAxisDirection9.Y], seriesRect, this.yAxis?.button);
if (this.showAnnotations()) {
this.animateAnnotations({ from: 0, to: 1, phase: "trailing" });
} else {
this.animateAnnotations({ from: 1, to: 0, phase: "remove" });
}
}
showAnnotations() {
if (!this.yAxis || !this.xAxis) {
return false;
}
const hasData = this.ctx.chartService.series.some((s) => s.hasData);
const seriesIds = this.yAxis.context.seriesIds();
const anyBoundSeriesVisible = seriesIds.some((id) => {
const series = this.ctx.chartService.series.find((s) => s.id === id);
return series?.visible;
});
return hasData && anyBoundSeriesVisible;
}
animateAnnotations({ from, to, phase }) {
const { annotations } = this;
this.ctx.animationManager?.animate({
from,
to,
id: "chart-annotations",
phase,
groupId: "opacity",
onUpdate(value) {
annotations.each((node) => {
node.opacity = value;
if ("setAxisLabelOpacity" in node) {
node.setAxisLabelOpacity(value);
}
});
},
onStop() {
annotations.each((node) => {
node.opacity = to;
if ("setAxisLabelOpacity" in node) {
node.setAxisLabelOpacity(to);
}
});
}
});
}
onPreRender() {
if (!this.enabled)
return;
this.updateAnnotations();
this.state.transition("render");
}
getAxis(axisLayout, seriesRect, button) {
const axisCtx = this.ctx.axisManager.getAxisContext(axisLayout.direction)[0];
const { position: axisPosition = "bottom", direction } = axisCtx;
const padding2 = axisLayout.gridPadding + axisLayout.seriesAreaPadding;
const bounds = new BBox3(0, 0, seriesRect.width, seriesRect.height).grow(padding2, axisPosition);
const lineDirection = direction === ChartAxisDirection9.X ? "vertical" : "horizontal";
const { axesButtons, snap } = this;
const buttonEnabled = this.enabled && axesButtons.enabled && (axesButtons.axes === "xy" || axesButtons.axes === direction);
if (buttonEnabled) {
button ?? (button = new AxisButton(
this.ctx,
{ ...axisCtx, snapToGroup: snap },
(coords) => this.onAxisButtonClick(coords, lineDirection),
seriesRect
));
const axisLabelPadding = calculateAxisLabelPadding(axisLayout);
button.update(seriesRect, axisLabelPadding);
} else {
button?.destroy();
button = void 0;
}
return { layout: axisLayout, context: axisCtx, bounds, button };
}
recordActionAfterNextUpdate(label, types = ["annotations"]) {
const {
defaults,
ctx: { annotationManager, historyManager }
} = this;
const originators = types.map((type) => type === "defaults" ? defaults : annotationManager);
this.postUpdateFns.push(() => {
historyManager.record(label, ...originators);
annotationManager.fireChangedEvent();
});
}
setColorAndDefault(datumType, colorPickerType, colorOpacity, color7, opacity, isMultiColor) {
this.state.transition("color", { colorPickerType, colorOpacity, color: color7, opacity, isMultiColor });
this.defaults.setDefaultColor(datumType, colorPickerType, colorOpacity, color7, opacity, isMultiColor);
}
setFontSizeAndDefault(datumType, fontSize) {
this.state.transition("fontSize", fontSize);
this.defaults.setDefaultFontSize(datumType, fontSize);
this.recordActionAfterNextUpdate(`Change ${datumType} font size to ${fontSize}`, ["annotations", "defaults"]);
}
setLineStyleTypeAndDefault(datumType, styleType) {
this.state.transition("lineStyle", { type: styleType });
this.defaults.setDefaultLineStyleType(datumType, styleType);
this.recordActionAfterNextUpdate(`Change ${datumType} line style to ${styleType}`, ["annotations", "defaults"]);
}
setLineStyleWidthAndDefault(datumType, strokeWidth) {
this.state.transition("lineStyle", { strokeWidth });
this.defaults.setDefaultLineStyleWidth(datumType, strokeWidth);
this.recordActionAfterNextUpdate(`Change ${datumType} stroke width to ${strokeWidth}`, [
"annotations",
"defaults"
]);
}
updateAnnotations() {
const {
annotationData,
annotations,
seriesRect,
ctx: { annotationManager }
} = this;
const context = this.getAnnotationContext();
if (!seriesRect || !context)
return;
annotationManager.updateData(annotationData.toJson());
const showAnnotations = this.showAnnotations();
this.toolbar.refreshButtonsEnabled(showAnnotations);
this.toolbar.toggleClearButtonEnabled(annotationData.length > 0 && showAnnotations);
annotations.update(annotationData ?? [], void 0, (datum) => datum.id).each((node, datum) => {
if (!showAnnotations) {
node.visible = false;
if ("setAxisLabelVisible" in node) {
node.setAxisLabelVisible(false);
}
return;
}
if ("setAxisLabelVisible" in node) {
node.setAxisLabelVisible(true);
}
this.injectDatumDependencies(datum);
updateAnnotation(node, datum, context);
});
for (const fn of this.postUpdateFns) {
fn();
}
this.postUpdateFns = [];
}
getAnnotationContext() {
const { seriesRect, xAxis, yAxis, snap } = this;
if (!(seriesRect && xAxis && yAxis)) {
return;
}
return {
seriesRect,
xAxis: {
...xAxis.context,
bounds: xAxis.bounds,
labelPadding: calculateAxisLabelPadding(xAxis.layout),
snapToGroup: snap
},
yAxis: {
...yAxis.context,
bounds: yAxis.bounds,
labelPadding: calculateAxisLabelPadding(xAxis.layout),
snapToGroup: snap
}
};
}
onHover(event) {
const { state } = this;
const context = this.getAnnotationContext();
if (!context)
return;
const shiftKey = event.sourceEvent.shiftKey;
const offset = Vec219.from(event);
const point = invertCoords(offset, context);
state.transition("hover", { offset, point, shiftKey, context });
}
onClick(event) {
const { state } = this;
const context = this.getAnnotationContext();
if (!context)
return;
const shiftKey = event.sourceEvent.shiftKey;
const point = invertCoords(Vec219.from(event), context);
const textInputValue = this.textInput.getValue();
const bbox = this.textInput.getBBox();
state.transition("click", { point, shiftKey, textInputValue, bbox });
}
onDoubleClick(event) {
const { state } = this;
const context = this.getAnnotationContext();
if (!context)
return;
const offset = Vec219.from(event);
state.transition("dblclick", { offset });
}
onAxisButtonClick(coords, direction) {
this.cancel();
this.reset();
const context = this.getAnnotationContext();
if (!this.annotationData || !context)
return;
const { state } = this;
this.pushAnnotationState(InteractionState2.Annotations);
const isHorizontal2 = direction === "horizontal";
state.transition(isHorizontal2 ? "horizontal-line" /* HorizontalLine */ : "vertical-line" /* VerticalLine */);
this.optionsToolbar.hide();
if (!coords) {
return;
}
const point = invertCoords(coords, context);
if (!validateDatumPoint(context, point)) {
return;
}
state.transition("click", { point, shiftKey: false });
this.update();
}
onResize() {
const textInputValue = this.textInput.getValue();
const bbox = this.textInput.getBBox();
this.state.transition("resize", { textInputValue, bbox });
}
hoverTouchPreHandler(event) {
if (event.device === "touch") {
this.onHover(event);
}
}
dragMoveTouchPreHandler(event) {
if (event.device === "touch" && this.ctx.interactionManager.isState(InteractionState2.AnnotationsSelected)) {
event.sourceEvent.preventDefault();
}
}
onDragStart(event) {
if (!this.ctx.interactionManager.isState(InteractionState2.AnnotationsDraggable))
return;
const context = this.getAnnotationContext();
if (!context)
return;
const offset = Vec219.from(event);
const point = invertCoords(offset, context);
const textInputValue = this.textInput.getValue();
const bbox = this.textInput.getBBox();
this.state.transition("dragStart", { context, offset, point, textInputValue, bbox });
}
onDrag(event) {
if (!this.ctx.interactionManager.isState(InteractionState2.AnnotationsDraggable))
return;
const context = this.getAnnotationContext();
if (!context)
return;
const offset = Vec219.from(event);
const point = invertCoords(offset, context);
const shiftKey = event.sourceEvent.shiftKey;
const textInputValue = this.textInput.getValue();
const bbox = this.textInput.getBBox();
this.state.transition("drag", { context, offset, point, shiftKey, textInputValue, bbox });
}
onDragEnd() {
this.state.transition("dragEnd");
}
onCancel(widgetEvent) {
const { sourceEvent } = widgetEvent ?? {};
if (sourceEvent?.currentTarget !== sourceEvent?.target)
return;
this.cancel();
this.reset();
}
onDelete() {
if (this.textInput.isVisible())
return;
this.cancel();
this.delete();
this.reset();
this.update();
}
onTextInput(event) {
const { state } = this;
const context = this.getAnnotationContext();
if (!context)
return;
const { key, shiftKey } = event;
const textInputValue = this.textInput.getValue();
const bbox = this.textInput.getBBox();
state.transition("textInput", { key, shiftKey, textInputValue, bbox, context });
}
onKeyDown(event) {
const { state } = this;
const context = this.getAnnotationContext();
if (!context) {
return;
}
const { sourceEvent } = event;
const { shiftKey, ctrlKey, metaKey } = sourceEvent;
const ctrlMeta = ctrlKey || metaKey;
const ctrlShift = ctrlKey || shiftKey;
state.transition("keyDown", { shiftKey, context });
const translation = { x: 0, y: 0 };
const xStep = Math.max(context?.xAxis.scale.bandwidth ?? 0, ctrlShift ? 10 : 1);
const yStep = Math.max(context?.yAxis.scale.bandwidth ?? 0, ctrlShift ? 10 : 1);
switch (sourceEvent.key) {
case "ArrowDown":
translation.y = yStep;
break;
case "ArrowUp":
translation.y = -yStep;
break;
case "ArrowLeft":
translation.x = -xStep;
break;
case "ArrowRight":
translation.x = xStep;
break;
case "Escape":
this.onCancel();
return;
case "Backspace":
case "Delete":
this.onDelete();
return;
}
if (translation.x || translation.y) {
state.transition("translate", { translation });
sourceEvent.stopPropagation();
sourceEvent.preventDefault();
}
if (!ctrlMeta) {
return;
}
switch (sourceEvent.key) {
case "c":
state.transition("copy");
return;
case "x":
state.transition("cut");
this.recordActionAfterNextUpdate("Cut annotation");
return;
case "v":
state.transition("paste");
this.recordActionAfterNextUpdate("Paste annotation");
return;
}
}
onKeyUp(event) {
const { shiftKey } = event.sourceEvent;
const context = this.getAnnotationContext();
if (!context) {
return;
}
this.state.transition("keyUp", { shiftKey, context });
this.state.transition("translateEnd");
}
clear() {
this.cancel();
this.deleteAll();
this.reset();
}
reset() {
this.state.transition("reset");
}
cancel() {
this.state.transition("cancel");
}
delete() {
this.state.transition("delete");
}
deleteAll() {
this.state.transition("deleteAll");
}
deleteEphemeralAnnotations() {
let deletedEphemeral = false;
for (const [index, datum] of this.annotationData.entries()) {
if (isEphemeralType(datum)) {
this.annotationData.splice(index, 1);
deletedEphemeral = true;
}
}
if (deletedEphemeral) {
this.recordActionAfterNextUpdate("Delete ephemeral annotations");
}
}
hideOverlays() {
this.settingsDialog.hide();
this.toolbar.hideOverlays();
this.optionsToolbar.hideOverlays();
}
pushAnnotationState(state) {
this.ctx.interactionManager.pushState(state);
this.ctx.tooltipManager.suppressTooltip("annotations");
}
popAnnotationState(state) {
this.ctx.interactionManager.popState(state);
this.ctx.tooltipManager.unsuppressTooltip("annotations");
}
isAnnotationState() {
return this.ctx.interactionManager.isState(InteractionState2.Annotations) || this.ctx.interactionManager.isState(InteractionState2.AnnotationsSelected);
}
update(status = ChartUpdateType3.PRE_SCENE_RENDER) {
this.ctx.updateService.update(status);
}
};
__decorateClass([
Property37
], _Annotations.prototype, "toolbar", 2);
__decorateClass([
Property37
], _Annotations.prototype, "optionsToolbar", 2);
__decorateClass([
Property37
], _Annotations.prototype, "axesButtons", 2);
__decorateClass([
Property37,
ObserveChanges3((target, value) => {
const enabled = value ?? true;
target.toolbar.enabled = enabled;
target.optionsToolbar.enabled = enabled;
target.axesButtons.enabled = enabled;
})
], _Annotations.prototype, "enabled", 2);
__decorateClass([
Property37
], _Annotations.prototype, "snap", 2);
var Annotations = _Annotations;
// packages/ag-charts-enterprise/src/features/annotations/annotationsTheme.ts
import "ag-charts-community";
import * as ThemeSymbols from "ag-charts-core";
import { FONT_SIZE_RATIO } from "ag-charts-core";
var stroke = {
stroke: { $ref: "foregroundColor" },
strokeOpacity: 1,
strokeWidth: 2
};
var handle = {
fill: ThemeSymbols.DEFAULT_ANNOTATION_HANDLE_FILL,
strokeOpacity: 1,
strokeWidth: 2
};
var font = {
color: { $ref: "chartBackgroundColor" },
fontSize: { $rem: FONT_SIZE_RATIO.LARGE },
fontFamily: { $ref: "fontFamily" }
};
var axisLabel = {
...font,
enabled: true,
fill: { $ref: "foregroundColor" },
fontSize: { $ref: "fontSize" }
};
var text = {
...font,
textAlign: "left"
};
var lineText = {
...font,
position: "top",
alignment: "center",
color: { $ref: "textColor" }
};
var channelText = {
...font,
position: "top",
alignment: "center",
color: { $ref: "textColor" }
};
var measurerStatistics = {
...font,
fontSize: { $ref: "fontSize" },
color: ThemeSymbols.DEFAULT_ANNOTATION_STATISTICS_COLOR,
fill: ThemeSymbols.DEFAULT_ANNOTATION_STATISTICS_FILL,
stroke: ThemeSymbols.DEFAULT_ANNOTATION_STATISTICS_STROKE,
strokeWidth: 1,
divider: {
stroke: ThemeSymbols.DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE,
strokeWidth: 1,
strokeOpacity: 0.5
}
};
var measurer = {
...stroke,
background: {
fill: { $ref: "foregroundColor" },
fillOpacity: 0.075
},
handle: { ...handle },
text: { ...lineText },
statistics: { ...measurerStatistics }
};
var toolbar = {
buttons: {
$shallowSimple: [
{
icon: "text-annotation",
tooltip: "toolbarAnnotationsTextAnnotations",
value: "text-menu"
},
{
icon: "trend-line-drawing",
tooltip: "toolbarAnnotationsLineAnnotations",
value: "line-menu"
},
{
icon: "arrow-drawing",
tooltip: "toolbarAnnotationsShapeAnnotations",
value: "shape-menu"
},
{
icon: "delete",
tooltip: "toolbarAnnotationsClearAll",
value: "clear"
}
]
},
padding: { $ref: "chartPadding" }
};
var optionsToolbar = {
buttons: {
$shallowSimple: [
{
icon: "text-annotation",
tooltip: "toolbarAnnotationsTextColor",
value: "text-color"
},
{
icon: "line-color",
tooltip: "toolbarAnnotationsLineColor",
value: "line-color"
},
{
icon: "fill-color",
tooltip: "toolbarAnnotationsFillColor",
value: "fill-color"
},
{
tooltip: "toolbarAnnotationsTextSize",
value: "text-size"
},
{
tooltip: "toolbarAnnotationsLineStrokeWidth",
value: "line-stroke-width"
},
{
icon: "line-style-solid",
tooltip: "toolbarAnnotationsLineStyle",
value: "line-style-type"
},
{
icon: "settings",
tooltip: "toolbarAnnotationsSettings",
value: "settings"
},
{
icon: "unlocked",
tooltip: "toolbarAnnotationsLock",
ariaLabel: "toolbarAnnotationsLock",
checkedOverrides: {
icon: "locked",
tooltip: "toolbarAnnotationsUnlock"
},
value: "lock"
},
{
icon: "delete",
tooltip: "toolbarAnnotationsDelete",
value: "delete"
}
]
}
};
var annotationsTheme = {
enabled: false,
// Lines
line: {
...stroke,
handle: { ...handle },
text: { ...lineText }
},
"horizontal-line": {
...stroke,
handle: { ...handle },
axisLabel: { ...axisLabel },
text: { ...lineText }
},
"vertical-line": {
...stroke,
handle: { ...handle },
axisLabel: { ...axisLabel },
text: { ...lineText }
},
// Channels
"disjoint-channel": {
...stroke,
background: {
fill: { $ref: "foregroundColor" },
fillOpacity: 0.075
},
handle: { ...handle },
text: { ...channelText }
},
"parallel-channel": {
...stroke,
middle: {
lineDash: [6, 5],
strokeWidth: 1
},
background: {
fill: { $ref: "foregroundColor" },
fillOpacity: 0.075
},
handle: { ...handle },
text: { ...channelText }
},
// Fibonnaccis
"fibonacci-retracement": {
...stroke,
strokes: ThemeSymbols.DEFAULT_FIBONACCI_STROKES,
rangeStroke: { $ref: "foregroundColor" },
handle: { ...handle },
text: { ...lineText, position: "center" },
label: {
...font,
color: void 0,
fontSize: { $rem: FONT_SIZE_RATIO.SMALLER }
}
},
"fibonacci-retracement-trend-based": {
...stroke,
strokes: ThemeSymbols.DEFAULT_FIBONACCI_STROKES,
rangeStroke: { $ref: "foregroundColor" },
handle: { ...handle },
text: { ...lineText, position: "center" },
label: {
...font,
color: void 0,
fontSize: { $rem: FONT_SIZE_RATIO.SMALLER }
}
},
// Texts
callout: {
...stroke,
...text,
color: { $ref: "textColor" },
handle: { ...handle },
fill: { $ref: "foregroundColor" },
fillOpacity: 0.075
},
comment: {
...text,
fontWeight: 700,
handle: { ...handle },
fill: { $ref: "foregroundColor" }
},
note: {
...text,
color: ThemeSymbols.DEFAULT_TEXTBOX_COLOR,
fill: ThemeSymbols.DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR,
stroke: { $ref: "chartBackgroundColor" },
strokeWidth: 1,
strokeOpacity: 1,
handle: { ...handle },
background: {
fill: ThemeSymbols.DEFAULT_TEXTBOX_FILL,
stroke: ThemeSymbols.DEFAULT_TEXTBOX_STROKE,
strokeWidth: 1
}
},
text: {
...text,
color: { $ref: "textColor" },
handle: { ...handle }
},
// Shapes
arrow: {
...stroke,
handle: { ...handle },
text: { ...lineText }
},
"arrow-up": {
fill: { $palette: "up.fill" },
handle: { ...handle, stroke: { $ref: "foregroundColor" } }
},
"arrow-down": {
fill: { $palette: "down.fill" },
handle: { ...handle, stroke: { $ref: "foregroundColor" } }
},
// Measurers
"date-range": {
...measurer
},
"price-range": {
...measurer
},
"date-price-range": {
...measurer
},
"quick-date-price-range": {
up: {
...stroke,
fill: ThemeSymbols.DEFAULT_FINANCIAL_CHARTS_ANNOTATION_BACKGROUND_FILL,
fillOpacity: 0.2,
handle: { ...handle },
statistics: {
...measurerStatistics,
color: "#fff",
fill: ThemeSymbols.DEFAULT_FINANCIAL_CHARTS_ANNOTATION_BACKGROUND_FILL,
strokeWidth: 0,
divider: {
stroke: "#fff",
strokeWidth: 1,
strokeOpacity: 0.5
}
}
},
down: {
...stroke,
stroke: ThemeSymbols.DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE,
fill: ThemeSymbols.DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL,
fillOpacity: 0.2,
handle: {
...handle,
stroke: ThemeSymbols.DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE
},
statistics: {
...measurerStatistics,
color: "#fff",
fill: ThemeSymbols.DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL,
strokeWidth: 0,
divider: {
stroke: "#fff",
strokeWidth: 1,
strokeOpacity: 0.5
}
}
}
},
axesButtons: {},
// Toolbars
toolbar,
optionsToolbar
};
// packages/ag-charts-enterprise/src/features/annotations/annotationsModule.ts
var AnnotationsModule = {
type: "plugin",
name: "annotations",
chartType: "cartesian",
enterprise: true,
version: VERSION7,
options: _ModuleSupport65.annotationOptionsDef,
themeTemplate: annotationsTheme,
create: (ctx) => new Annotations(ctx),
patchContext: (ctx) => {
if (ctx.sharedToolbar)
return;
ctx.sharedToolbar = new SharedToolbar(ctx);
ctx.cleanup.register(() => ctx.sharedToolbar.destroy());
}
};
// packages/ag-charts-enterprise/src/features/band-highlight/bandHighlightModule.ts
import { VERSION as VERSION8 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/features/band-highlight/bandHighlight.ts
import { _ModuleSupport as _ModuleSupport66 } from "ag-charts-community";
import {
AbstractModuleInstance as AbstractModuleInstance5,
ChartAxisDirection as ChartAxisDirection10,
ChartUpdateType as ChartUpdateType4,
Property as Property38,
ZIndexMap as ZIndexMap5,
createId as createId2
} from "ag-charts-core";
var {
Range,
TranslatableGroup,
BBox: BBox4,
FillGradientDefaults,
FillImageDefaults,
FillPatternDefaults,
getShapeFill,
InteractionState: InteractionState3
} = _ModuleSupport66;
var BandHighlight = class extends AbstractModuleInstance5 {
constructor(ctx) {
super();
this.ctx = ctx;
this.id = createId2(this);
this.enabled = false;
this.stroke = "rgb(195, 195, 195)";
this.lineDash = [6, 3];
this.lineDashOffset = 0;
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.fill = "#c16068";
this.fillOpacity = 1;
this.fillGradientDefaults = new FillGradientDefaults();
this.fillPatternDefaults = new FillPatternDefaults();
this.fillImageDefaults = new FillImageDefaults();
this.bounds = new BBox4(0, 0, 0, 0);
this.bandHighlightGroup = new TranslatableGroup({
name: "bandHighlight",
zIndex: ZIndexMap5.AXIS_BAND_HIGHLIGHT
});
this.rangeNode = this.bandHighlightGroup.appendChild(new Range());
this.activeAxisHighlight = void 0;
this.axisCtx = ctx.parent;
this.hideBand();
ctx.domManager.addEventListener("focusin", ({ target }) => {
const isSeriesAreaChild = target instanceof HTMLElement && ctx.domManager.contains(target, "series-area");
if (this.bandHighlightGroup.visible && !isSeriesAreaChild) {
this.hideBand();
this.ctx.updateService.update(ChartUpdateType4.SCENE_RENDER);
}
});
const {
widgets: { seriesWidget, seriesDragInterpreter },
animationManager,
eventsHub
} = ctx;
this.cleanup.register(
ctx.scene.attachNode(this.bandHighlightGroup),
seriesWidget.addListener("mousemove", (event) => this.onHoverLikeEvent(event)),
seriesWidget.addListener("mouseleave", () => this.clearAllHighlight()),
animationManager.addListener("animation-start", () => this.clearAllHighlight()),
eventsHub.on("layout:complete", (event) => this.layout(event)),
eventsHub.on("series:focus-change", () => this.onKeyPress()),
eventsHub.on("zoom:pan-start", () => this.clearAllHighlight()),
eventsHub.on("zoom:change-complete", () => this.clearAllHighlight()),
eventsHub.on("dom:resize", () => this.clearAllHighlight()),
eventsHub.on("axis:change", () => this.axisChange())
);
if (seriesDragInterpreter) {
this.cleanup.register(
seriesDragInterpreter.events.on("drag-move", (event) => this.onHoverLikeEvent(event)),
seriesDragInterpreter.events.on("click", (event) => this.onClick(event))
);
}
}
axisChange() {
this.onHighlightChange();
}
isHover(event) {
return event.type === "mousemove" || event.type === "click" || event.device === "touch" && this.ctx.chartService.touch.dragAction === "hover";
}
onClick(event) {
if (event.device === "touch") {
this.onHoverLikeEvent(event);
}
}
clearAllHighlight() {
if (!this.ctx.interactionManager.isState(InteractionState3.Clickable))
return;
this.onHighlightChange();
}
onKeyPress() {
if (this.ctx.interactionManager.isState(InteractionState3.Default)) {
this.onHighlightChange();
}
}
onHoverLikeEvent(event) {
const requiredState = this.isHover(event) ? InteractionState3.Clickable : InteractionState3.AnnotationsMoveable;
if (!this.ctx.interactionManager.isState(requiredState))
return;
this.handleHoverHighlight(event);
}
handleHoverHighlight(event) {
if (!event)
return;
const { currentX: x, currentY: y } = event;
this.onHighlightChange(this.axisCtx.pickBand({ x, y }));
}
layout({ series: { rect, visible }, axes }) {
if (!visible || !axes || !this.enabled)
return;
const { position: axisPosition = "left", axisId } = this.axisCtx;
const axisLayout = axes[axisId];
if (!axisLayout)
return;
this.axisLayout = axisLayout;
this.bounds = rect.clone().grow(axisLayout.gridPadding, axisPosition);
const { bandHighlightGroup, bounds } = this;
bandHighlightGroup.translationX = Math.round(bounds.x);
bandHighlightGroup.translationY = Math.round(bounds.y);
this.updateBand();
}
updateBand() {
const {
rangeNode: node,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
fill,
fillOpacity,
fillGradientDefaults: fillGradientDefaults3,
fillPatternDefaults: fillPatternDefaults3,
fillImageDefaults: fillImageDefaults3,
lineDashOffset,
axisLayout
} = this;
if (!axisLayout)
return;
node.stroke = stroke3;
node.strokeWidth = strokeWidth;
node.strokeOpacity = strokeOpacity;
node.lineDash = lineDash;
node.lineDashOffset = lineDashOffset;
node.fill = getShapeFill(fill, fillGradientDefaults3, fillPatternDefaults3, fillImageDefaults3);
node.fillOpacity = fillOpacity;
node.startLine = true;
node.endLine = true;
}
isVertical() {
return this.axisCtx.direction === ChartAxisDirection10.X;
}
onHighlightChange(axisBandDatum) {
if (!this.enabled)
return;
this.activeAxisHighlight = axisBandDatum;
if (this.activeAxisHighlight) {
this.showBand();
} else {
this.hideBand();
}
this.ctx.updateService.update(ChartUpdateType4.SCENE_RENDER);
}
updateBandPosition() {
const { rangeNode, bounds } = this;
const { band } = this.activeAxisHighlight ?? {};
if (band == void 0) {
this.hideBand();
return;
}
let r0 = Math.min(...band);
let r1 = Math.max(...band);
if (r1 - r0 < 1) {
const mid = (r0 + r1) / 2;
r0 = mid - 0.5;
r1 = mid + 0.5;
}
if (this.isVertical()) {
rangeNode.y1 = 0;
rangeNode.y2 = bounds.height;
rangeNode.x1 = r0;
rangeNode.x2 = r1;
rangeNode.horizontal = true;
} else {
rangeNode.y1 = r0;
rangeNode.y2 = r1;
rangeNode.x1 = 0;
rangeNode.x2 = bounds.width;
rangeNode.horizontal = false;
}
}
showBand() {
this.updateBandPosition();
this.bandHighlightGroup.visible = true;
}
hideBand() {
this.bandHighlightGroup.visible = false;
}
};
BandHighlight.className = "BandHighlight";
__decorateClass([
Property38
], BandHighlight.prototype, "enabled", 2);
__decorateClass([
Property38
], BandHighlight.prototype, "stroke", 2);
__decorateClass([
Property38
], BandHighlight.prototype, "lineDash", 2);
__decorateClass([
Property38
], BandHighlight.prototype, "lineDashOffset", 2);
__decorateClass([
Property38
], BandHighlight.prototype, "strokeWidth", 2);
__decorateClass([
Property38
], BandHighlight.prototype, "strokeOpacity", 2);
__decorateClass([
Property38
], BandHighlight.prototype, "fill", 2);
__decorateClass([
Property38
], BandHighlight.prototype, "fillOpacity", 2);
__decorateClass([
Property38
], BandHighlight.prototype, "fillGradientDefaults", 2);
__decorateClass([
Property38
], BandHighlight.prototype, "fillPatternDefaults", 2);
__decorateClass([
Property38
], BandHighlight.prototype, "fillImageDefaults", 2);
// packages/ag-charts-enterprise/src/features/band-highlight/bandHighlightModule.ts
var BandHighlightModule = {
type: "axis:plugin",
name: "bandHighlight",
chartType: "cartesian",
axisTypes: ["category", "ordinal-time", "unit-time", "grouped-category"],
enterprise: true,
version: VERSION8,
themeTemplate: {
enabled: false,
strokeWidth: 0,
lineDash: [],
fill: { $foregroundBackgroundMix: 0.05 }
},
create: (ctx) => new BandHighlight(ctx)
};
// packages/ag-charts-enterprise/src/features/chart-toolbar/chartToolbarModule.ts
import { VERSION as VERSION9 } from "ag-charts-community";
import { boolean as boolean2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/chart-toolbar/chartToolbar.ts
import { _ModuleSupport as _ModuleSupport67 } from "ag-charts-community";
import { AbstractModuleInstance as AbstractModuleInstance6, ActionOnSet as ActionOnSet5, Logger as Logger4, Property as Property39 } from "ag-charts-core";
var { LayoutElement: LayoutElement2, Menu: Menu3 } = _ModuleSupport67;
var menuItems = [
{ label: "toolbarSeriesTypeOHLC", icon: "ohlc-series", value: "ohlc" },
{ label: "toolbarSeriesTypeCandles", icon: "candlestick-series", value: "candlestick" },
{ label: "toolbarSeriesTypeHollowCandles", icon: "hollow-candlestick-series", value: "hollow-candlestick" },
{ label: "toolbarSeriesTypeLine", icon: "line-series", value: "line" },
{ label: "toolbarSeriesTypeStepLine", icon: "step-line-series", value: "step-line" },
{ label: "toolbarSeriesTypeHLC", icon: "hlc-series", value: "hlc" },
{ label: "toolbarSeriesTypeHighLow", icon: "high-low-series", value: "high-low" }
];
var ChartToolbar = class extends AbstractModuleInstance6 {
constructor(ctx) {
super();
this.ctx = ctx;
this.enabled = false;
this.menu = new Menu3(this.ctx, "chart-toolbar");
this.toolbar = ctx.sharedToolbar.getSharedToolbar("chartToolbar");
this.cleanup.register(
this.toolbar.addToolbarListener("button-pressed", this.onButtonPressed.bind(this)),
ctx.layoutManager.registerElement(LayoutElement2.ToolbarLeft, this.onLayoutStart.bind(this)),
() => this.toolbar.destroy()
);
}
onLayoutStart(ctx) {
if (!this.enabled)
return;
this.updateButton();
this.toolbar.layout(ctx.layoutBox);
}
onButtonPressed({ event, buttonBounds, buttonWidget }) {
this.menu.setAnchor({ x: buttonBounds.x + buttonBounds.width + 6, y: buttonBounds.y });
this.menu.show(buttonWidget, {
items: menuItems,
menuItemRole: "menuitemradio",
ariaLabel: this.ctx.localeManager.t("toolbarSeriesTypeDropdown"),
class: "ag-charts-chart-toolbar__menu",
value: this.getChartType(),
sourceEvent: event.sourceEvent,
onPress: (item) => {
this.setChartType(item.value);
this.hidePopover();
},
onHide: () => {
this.toolbar.clearActiveButton();
}
});
this.toolbar.toggleActiveButtonByIndex(0);
}
updateButton() {
const chartType = this.getChartType();
const icon = menuItems.find((item) => item.value === chartType)?.icon;
if (icon != null) {
this.toolbar.updateButtons([{ icon, tooltip: "toolbarSeriesTypeDropdown", value: "menu" }]);
}
}
hidePopover() {
this.toolbar.clearActiveButton();
this.menu.hide();
}
setChartType(chartType) {
const options = { chartType };
this.ctx.chartService.publicApi?.updateDelta(options).catch((e) => Logger4.error(e));
}
getChartType() {
const chartType = this.ctx.chartService.publicApi?.getOptions()?.chartType;
if (chartType == null || !menuItems.some((item) => item.value === chartType)) {
return "candlestick";
}
return chartType;
}
};
__decorateClass([
Property39,
ActionOnSet5({
changeValue(enabled) {
this.toolbar?.setHidden(!enabled);
}
})
], ChartToolbar.prototype, "enabled", 2);
// packages/ag-charts-enterprise/src/features/chart-toolbar/chartToolbarModule.ts
var ChartToolbarModule = {
type: "plugin",
name: "chartToolbar",
chartType: "cartesian",
enterprise: true,
version: VERSION9,
options: {
enabled: boolean2
},
create: (ctx) => new ChartToolbar(ctx),
patchContext: (ctx) => {
if (ctx.sharedToolbar)
return;
ctx.sharedToolbar = new SharedToolbar(ctx);
ctx.cleanup.register(() => ctx.sharedToolbar.destroy());
}
};
// packages/ag-charts-enterprise/src/features/context-menu/contextMenuModule.ts
import { VERSION as VERSION10 } from "ag-charts-community";
import {
IS_DARK_THEME,
boolean as boolean3,
callbackOf,
contextMenuItemsArray,
undocumented as undocumented2
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/context-menu/contextMenu.ts
import { _ModuleSupport as _ModuleSupport68, _Widget as _Widget4 } from "ag-charts-community";
import {
AbstractModuleInstance as AbstractModuleInstance7,
Logger as Logger5,
Property as Property40,
callWithContext,
clamp as clamp5,
createElement as createElement5,
getIconClassNames as getIconClassNames3,
toPlainText
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/context-menu/contextMenuItem.ts
import { isKeyOf } from "ag-charts-core";
function showsFor(showOn, showing) {
if (showOn === "always")
return true;
if (showOn === "series-area")
return showing === "series-area" || showing === "series-node";
return showOn === showing;
}
function appendItem(showing, item, result) {
let mustShow = true;
if (item.type === "separator") {
const last = result.at(-1);
mustShow = last !== void 0 && last.type !== "separator";
}
mustShow && (mustShow = showsFor(item.showOn ?? "always", showing));
if (mustShow) {
const menuItem = new ContextMenuItem(item);
result.push(menuItem);
return menuItem;
}
}
function appendBuiltinItem(showing, registry, keyword, result) {
if (registry.isVisible(keyword)) {
appendItem(showing, registry.builtins.items[keyword], result);
}
}
function expandBuiltin(showing, registry, keyword, result) {
const { builtins } = registry;
if (isKeyOf(keyword, builtins.lists)) {
for (const childKeyword of builtins.lists[keyword]) {
appendBuiltinItem(showing, registry, childKeyword, result);
}
} else {
appendBuiltinItem(showing, registry, keyword, result);
}
}
function expandBuiltinLists(showing, items, registry) {
const unfiltered = [];
const { builtins } = registry;
for (const it of items) {
if (typeof it === "string" && isKeyOf(it, builtins.lists)) {
for (const listItem of builtins.lists[it]) {
unfiltered.push(listItem);
}
} else {
unfiltered.push(it);
}
}
return unfiltered.filter((it) => {
if (typeof it === "string") {
const showOn = registry.builtins.items[it].showOn ?? "always";
return registry.isVisible(it) && showsFor(showOn, showing);
} else {
return showsFor(it.showOn ?? "always", showing);
}
});
}
function expandItems(showing, registry, items, result) {
for (const item of items) {
if (typeof item === "string") {
expandBuiltin(showing, registry, item, result);
} else {
const menuItem = appendItem(showing, item, result);
if (item.items && menuItem && item.items.length > 0) {
expandItems(showing, registry, item.items, menuItem.items);
}
}
}
if (result.at(-1)?.type === "separator") {
result.pop();
}
}
var ContextMenuItem = class {
constructor(options) {
this.type = "action";
this.showOn = "always";
this.label = "";
this.iconUrl = void 0;
this.enabled = true;
this.items = [];
this.action = void 0;
if (options)
this.setOptions(options);
this.items = [];
}
setField(key, that, value) {
that[key] = value;
}
setOptions(options) {
let key;
for (key in options) {
if (options[key] !== void 0) {
this.setField(key, this, options[key]);
}
}
}
};
// packages/ag-charts-enterprise/src/features/context-menu/contextMenuStyles.ts
var DEFAULT_CONTEXT_MENU_CLASS = "ag-charts-context-menu";
// packages/ag-charts-enterprise/src/features/context-menu/contextMenu.ts
var { ContextMenuRegistry } = _ModuleSupport68;
var moduleId2 = "context-menu";
var DATUM_KEYS = [
"angleKey",
"calloutLabelKey",
"colorKey",
"labelKey",
"radiusKey",
"sectorLabelKey",
"sizeKey",
"xKey",
"yKey"
];
var ContextMenu = class extends AbstractModuleInstance7 {
constructor(ctx) {
super();
this.ctx = ctx;
this.enabled = true;
this.darkTheme = false;
this.items = ["defaults"];
// State
this.pickedNode = void 0;
this.showEvent = void 0;
this.x = 0;
this.y = 0;
this.collapsingSubMenus = 0;
this.menuWidget = new _Widget4.MenuWidget();
this.interactionManager = ctx.interactionManager;
this.element = ctx.domManager.addChild("canvas-overlay", moduleId2);
this.element.classList.add(DEFAULT_CONTEXT_MENU_CLASS);
this.element.style.display = "none";
this.element.addEventListener("contextmenu", (event) => event.preventDefault());
this.element.addEventListener("focusout", ({ relatedTarget }) => {
if (this.collapsingSubMenus > 0)
return;
if (relatedTarget == null || relatedTarget instanceof Node && !this.element.contains(relatedTarget)) {
this.hide();
}
});
this.cleanup.register(
() => this.element.remove(),
() => this.menuWidget.destroy(),
ctx.eventsHub.on("dom:hidden", () => this.hide()),
this.menuWidget.addListener("collapse-widget", () => this.onCollapse())
);
this.menuWidget.addClass(`${DEFAULT_CONTEXT_MENU_CLASS}__menu`);
if (typeof MutationObserver !== "undefined") {
const observer = new MutationObserver(() => {
if (this.element.contains(this.menuWidget.getElement())) {
this.reposition();
}
});
observer.observe(this.element, { childList: true });
this.mutationObserver = observer;
this.cleanup.register(() => observer.disconnect());
}
this.ctx.contextMenuRegistry.builtins.items["download"].action = () => {
const title = ctx.chartService.title;
let fileName = "image";
if (title?.enabled) {
fileName = title.node.getPlainText().replace(/\.+/, "");
}
this.ctx.chartService.publicApi?.download({ fileName }).catch((e) => {
Logger5.error("Unable to download chart", e);
});
};
this.cleanup.register(this.ctx.eventsHub.on("context-menu:complete", (e) => this.onContext(e)));
}
makeGetItemsParams(event) {
const { showOn } = event;
const { context } = this.ctx.chartService;
const defaultItems = expandBuiltinLists(showOn, this.items, this.ctx.contextMenuRegistry);
switch (showOn) {
case "always":
case "series-area":
return { showOn, context, defaultItems };
case "series-node": {
if (this.pickedNode == null)
throw new Error(`this.pickedNode is null`);
const params = {
showOn,
context,
seriesId: this.pickedNode.series.id,
datum: this.pickedNode.datum,
defaultItems
};
for (const k of DATUM_KEYS) {
if (this.pickedNode[k] !== void 0) {
params[k] = this.pickedNode[k];
}
}
return params;
}
case "legend-item":
if (this.pickedLegendItem == null)
throw new Error(`this.pickedLegendItem is null`);
const { itemId, seriesId, label, enabled } = this.pickedLegendItem;
const text2 = toPlainText(label.text);
if (typeof itemId !== "string") {
throw new Error(`unexpected itemId type: [${typeof itemId}] (expected [string])`);
}
return { showOn, context, itemId, seriesId, text: text2, visible: enabled, defaultItems };
default:
return showOn;
}
}
expandItemsOptions(event) {
const result = [];
let items;
if (this.getItems) {
const cbParams = this.makeGetItemsParams(event);
items = this.getItems(cbParams);
}
items ?? (items = this.items);
expandItems(event.showOn, this.ctx.contextMenuRegistry, items, result);
return result;
}
onContext(event) {
if (!this.enabled)
return;
event.widgetEvent.sourceEvent.preventDefault();
this.showEvent = event.widgetEvent.sourceEvent;
this.x = event.x;
this.y = event.y;
this.pickedNode = void 0;
this.pickedLegendItem = void 0;
if (ContextMenuRegistry.check("series-node", event)) {
this.pickedNode = event.context.pickedNode;
} else if (ContextMenuRegistry.check("legend-item", event)) {
this.pickedLegendItem = event.context.legendItem;
}
const expandedItems = this.expandItemsOptions(event);
if (expandedItems.length === 0)
return;
this.show(event.widgetEvent, expandedItems);
}
show(widgetEvent, expandedItems) {
const { sourceEvent } = widgetEvent;
this.interactionManager.pushState(_ModuleSupport68.InteractionState.ContextMenu);
this.element.style.display = "block";
const overrideFocusVisible = sourceEvent.pointerType === "touch" ? false : void 0;
if (overrideFocusVisible !== void 0) {
this.ctx.chartService.overrideFocusVisible(overrideFocusVisible);
}
this.createMenu(expandedItems);
this.element.appendChild(this.menuWidget.getElement());
this.menuWidget.expand({ sourceEvent, overrideFocusVisible });
}
hide() {
this.menuWidget.collapse();
}
onCollapse() {
this.interactionManager.popState(_ModuleSupport68.InteractionState.ContextMenu);
this.menuWidget.getElement().remove();
this.element.style.display = "none";
}
onSubMenuExpand(button, menu) {
const bounds = button.getBounds();
button.setFocusOverride(true);
button.getElement().insertAdjacentElement("afterend", menu.getElement());
menu.getElement().style.position = "absolute";
const canvasRect = this.ctx.domManager.getBoundingClientRect();
const buttonClientRect = button.getBoundingClientRect();
const remainingSpaceOnRight = canvasRect.right - buttonClientRect.right;
const remainingSpaceOnLeft = buttonClientRect.left - canvasRect.left;
const { offsetWidth: menuOffsetWidth, offsetHeight: menuOffsetHeight } = menu.getElement();
let y = bounds.y;
if (canvasRect.height > menuOffsetHeight) {
const remainingSpaceOnBottom = canvasRect.bottom - buttonClientRect.top;
if (remainingSpaceOnBottom < menuOffsetHeight) {
y -= menuOffsetHeight - remainingSpaceOnBottom;
}
}
if (remainingSpaceOnRight >= menuOffsetWidth) {
menu.setBounds({ x: bounds.x + bounds.width, y });
} else {
const x = bounds.x - menuOffsetWidth;
const leftDelta = remainingSpaceOnLeft + x;
if (leftDelta >= 0) {
menu.setBounds({ x, y });
} else {
menu.setBounds({ x: x - leftDelta, y });
}
}
}
onSubMenuCollapse(button, menu) {
button.setFocusOverride(void 0);
this.collapsingSubMenus++;
menu.remove();
this.collapsingSubMenus--;
}
createMenu(expandedItems) {
const { menuWidget } = this;
menuWidget.clear();
menuWidget.setTabIndex(-1);
this.createMenuItems(menuWidget, expandedItems);
}
createMenuItems(menuWidget, expandedItems) {
for (const item of expandedItems) {
switch (item.type) {
case "separator": {
const sep = menuWidget.addSeparator();
sep.classList.add(`${DEFAULT_CONTEXT_MENU_CLASS}__divider`);
break;
}
case "action": {
if (item.items.length === 0) {
const btn = new _Widget4.MenuItemWidget();
this.initButtonElement(btn, item);
menuWidget.addChild(btn);
} else {
const { subMenuButton, subMenu } = menuWidget.addSubMenu();
subMenu.addClass(`${DEFAULT_CONTEXT_MENU_CLASS}__menu`);
subMenu.addListener("expand-widget", () => this.onSubMenuExpand(subMenuButton, subMenu));
subMenu.addListener("collapse-widget", () => this.onSubMenuCollapse(subMenuButton, subMenu));
this.initButtonElement(subMenuButton, item);
this.createMenuItems(subMenu, item.items);
}
break;
}
default:
throw new Error("unhandled case");
}
}
}
createButtonOnClick(showOn, callback4) {
if (ContextMenuRegistry.checkCallback("legend-item", showOn, callback4)) {
return (widgetEvent) => {
const event = widgetEvent.sourceEvent;
if (this.pickedLegendItem) {
const { seriesId, itemId, label } = this.pickedLegendItem;
const { chartService: chart } = this.ctx;
if (typeof itemId !== "string") {
Logger5.error(`unexpected itemId type: [${typeof itemId}] (expected [string])`);
return;
}
const series = chart.series.find((s) => s.id === seriesId);
const callers = [series?.properties, chart];
const apiEvent = {
type: "contextmenu",
seriesId,
itemId,
text: toPlainText(label.text),
event
};
callWithContext(callers, callback4, apiEvent);
this.hide();
} else {
Logger5.error("legend item not found");
}
};
} else if (ContextMenuRegistry.checkCallback("series-area", showOn, callback4)) {
return () => {
const caller = this.ctx.chartService;
const apiEvent = { type: "seriesContextMenuAction", event: this.showEvent };
callWithContext(caller, callback4, apiEvent);
this.hide();
};
} else if (ContextMenuRegistry.checkCallback("series-node", showOn, callback4)) {
return () => {
const { showEvent } = this;
const { chartService: chart } = this.ctx;
const pickedNode = this.pickedNode;
const callers = [pickedNode?.series.properties, chart];
const apiEvent = pickedNode?.series.createNodeContextMenuActionEvent(showEvent, pickedNode);
if (apiEvent) {
callWithContext(callers, callback4, apiEvent);
} else {
Logger5.error("series node not found");
}
this.hide();
};
}
return () => {
const caller = this.ctx.chartService;
const apiEvent = { type: "contextMenuEvent", event: this.showEvent };
callWithContext(caller, callback4, apiEvent);
this.hide();
};
}
initTableCells(elem) {
const cellIcon = createElement5("div");
const cellLabel = createElement5("div");
const cellArrow = createElement5("div");
cellIcon.classList.toggle(`${DEFAULT_CONTEXT_MENU_CLASS}__icon`, true);
cellLabel.classList.toggle(`${DEFAULT_CONTEXT_MENU_CLASS}__cell`, true);
cellArrow.classList.toggle(`${DEFAULT_CONTEXT_MENU_CLASS}__cell`, true);
cellIcon.ariaHidden = "true";
cellLabel.role = "presentation";
cellArrow.ariaHidden = "true";
elem.append(cellIcon, cellLabel, cellArrow);
return { cellIcon, cellLabel, cellArrow };
}
initButtonElement(button, item) {
button.addClass(`${DEFAULT_CONTEXT_MENU_CLASS}__item`);
button.setEnabled(item.enabled);
const label = this.ctx.localeManager.t(item.label);
const cellPaddingClass = `${DEFAULT_CONTEXT_MENU_CLASS}__cellpadding`;
const { cellIcon, cellLabel, cellArrow } = this.initTableCells(button.getElement());
cellLabel.textContent = label;
cellLabel.classList.add(cellPaddingClass);
if (item.iconUrl != null) {
const img = createElement5("img");
img.src = item.iconUrl;
cellIcon.append(img);
cellIcon.classList.add(cellPaddingClass);
}
if (item.items.length > 0) {
const span = createElement5("span", getIconClassNames3("chevron-right"));
cellArrow.append(span);
cellArrow.classList.add(cellPaddingClass);
}
const { showOn, action } = item;
if (action != null) {
button.addListener("click", this.createButtonOnClick(showOn, action));
}
if (item.items.length === 0) {
button.addListener("mouseleave", () => button.setFocusOverride(false));
button.addListener("mouseenter", () => button.setFocusOverride(void 0));
}
}
reposition() {
let { x, y } = this;
this.element.style.top = "unset";
this.element.style.bottom = "unset";
const canvasRect = this.ctx.domManager.getBoundingClientRect();
const { offsetWidth: width, offsetHeight: height } = this.element;
x = clamp5(0, x, canvasRect.width - width);
y = clamp5(0, y, canvasRect.height - height);
this.element.style.left = `${x}px`;
this.element.style.top = `calc(${y}px - 0.5em)`;
}
destroy() {
super.destroy();
this.mutationObserver?.disconnect();
this.ctx.domManager.removeStyles(moduleId2);
this.ctx.domManager.removeChild("canvas-overlay", moduleId2);
}
};
__decorateClass([
Property40
], ContextMenu.prototype, "enabled", 2);
__decorateClass([
Property40
], ContextMenu.prototype, "darkTheme", 2);
__decorateClass([
Property40
], ContextMenu.prototype, "items", 2);
__decorateClass([
Property40
], ContextMenu.prototype, "getItems", 2);
// packages/ag-charts-enterprise/src/features/context-menu/contextMenuModule.ts
var ContextMenuModule = {
type: "plugin",
name: "contextMenu",
enterprise: true,
version: VERSION10,
options: {
enabled: boolean3,
items: contextMenuItemsArray,
getItems: callbackOf(contextMenuItemsArray, "a menu items array")
},
themeTemplate: {
enabled: true,
darkTheme: IS_DARK_THEME
},
create: (ctx) => new ContextMenu(ctx)
};
ContextMenuModule.options.darkTheme = undocumented2(boolean3);
// packages/ag-charts-enterprise/src/features/crosshair/crosshairModule.ts
import { VERSION as VERSION11 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/features/crosshair/crosshair.ts
import { _ModuleSupport as _ModuleSupport70 } from "ag-charts-community";
import {
AbstractModuleInstance as AbstractModuleInstance8,
ChartAxisDirection as ChartAxisDirection11,
ChartUpdateType as ChartUpdateType5,
Property as Property42,
ZIndexMap as ZIndexMap6,
createId as createId4,
toPlainText as toPlainText2
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/utils/datum.ts
function readDatum(nodeDatum) {
if (typeof nodeDatum?.datum === "object") {
return nodeDatum.datum;
}
return null;
}
// packages/ag-charts-enterprise/src/features/crosshair/crosshairLabel.ts
import { _ModuleSupport as _ModuleSupport69 } from "ag-charts-community";
import { BaseProperties as BaseProperties16, Property as Property41, createId as createId3, setAttribute as setAttribute2 } from "ag-charts-core";
var { FormatManager } = _ModuleSupport69;
var DEFAULT_LABEL_CLASS = "ag-charts-crosshair-label";
var CrosshairLabelProperties = class extends BaseProperties16 {
constructor() {
super(...arguments);
this.enabled = true;
this.xOffset = 0;
this.yOffset = 0;
this.format = void 0;
this.renderer = void 0;
this._cachedFormatter = void 0;
}
formatValue(callWithContext3, type, value, params) {
const { formatter, format } = this;
const { domain, boundSeries } = params;
let result;
if (formatter != null) {
const fractionDigits = params.type === "number" ? params.fractionDigits : void 0;
const unit = params.type === "date" ? params.unit : void 0;
const step = params.type === "date" ? params.step : void 0;
result = callWithContext3(formatter, { value, domain, fractionDigits, unit, step, boundSeries });
}
if (format != null) {
let cachedFormatter = this._cachedFormatter;
if (cachedFormatter?.type !== type || cachedFormatter?.format !== format) {
cachedFormatter = {
type,
format,
formatter: FormatManager.getFormatter(type, format)
};
this._cachedFormatter = cachedFormatter;
}
result ?? (result = cachedFormatter.formatter?.(value));
}
return result == null ? void 0 : String(result);
}
};
__decorateClass([
Property41
], CrosshairLabelProperties.prototype, "enabled", 2);
__decorateClass([
Property41
], CrosshairLabelProperties.prototype, "xOffset", 2);
__decorateClass([
Property41
], CrosshairLabelProperties.prototype, "yOffset", 2);
__decorateClass([
Property41
], CrosshairLabelProperties.prototype, "formatter", 2);
__decorateClass([
Property41
], CrosshairLabelProperties.prototype, "format", 2);
__decorateClass([
Property41
], CrosshairLabelProperties.prototype, "renderer", 2);
var CrosshairLabel = class extends CrosshairLabelProperties {
constructor(domManager, key, axisId) {
super();
this.domManager = domManager;
this.id = createId3(this);
this.element = domManager.addChild("canvas-overlay", `crosshair-label-${this.id}`);
this.element.classList.add(DEFAULT_LABEL_CLASS);
setAttribute2(this.element, "aria-hidden", true);
this.element.dataset.key = key;
this.element.dataset.axisId = axisId;
}
show(meta) {
const { element } = this;
const left = meta.x + this.xOffset;
const top = meta.y + this.yOffset;
element.style.top = `${Math.round(top)}px`;
element.style.left = `${Math.round(left)}px`;
this.toggle(true);
}
setLabelHtml({ html, styles }) {
if (html !== void 0) {
this.element.innerHTML = html;
}
if (styles !== void 0) {
const styleElement = this.element.children[0] ?? this.element;
Object.assign(styleElement.style, styles);
}
}
getBBox() {
const { element } = this;
return new _ModuleSupport69.BBox(
element.clientLeft,
element.clientTop,
element.clientWidth,
element.clientHeight
);
}
toggle(visible) {
this.element.classList.toggle(`ag-charts-crosshair-label--hidden`, !visible);
}
destroy() {
this.domManager.removeChild("canvas-overlay", `crosshair-label-${this.id}`);
}
toLabelHtml(input, defaults) {
if (typeof input === "string") {
return { html: input, styles: {} };
}
defaults = defaults ?? {};
const {
text: text2 = defaults.text ?? "",
color: color7 = defaults.color,
backgroundColor = defaults.backgroundColor,
opacity = defaults.opacity ?? 1
} = input;
const styles = {
opacity,
"background-color": backgroundColor?.toLowerCase(),
color: color7
};
return {
html: `<div class="ag-charts-crosshair-label-content">
<span>${text2}</span>
</div>`,
styles
};
}
};
CrosshairLabel.className = "CrosshairLabel";
// packages/ag-charts-enterprise/src/features/crosshair/crosshair.ts
var { Group: Group5, TranslatableGroup: TranslatableGroup2, Line: Line4, BBox: BBox5, InteractionState: InteractionState4 } = _ModuleSupport70;
var Crosshair = class extends AbstractModuleInstance8 {
constructor(ctx) {
super();
this.ctx = ctx;
this.id = createId4(this);
this.enabled = false;
this.stroke = "rgb(195, 195, 195)";
this.lineDash = [6, 3];
this.lineDashOffset = 0;
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.snap = true;
this.label = new CrosshairLabelProperties();
this.seriesRect = new BBox5(0, 0, 0, 0);
this.bounds = new BBox5(0, 0, 0, 0);
this.crosshairGroup = new TranslatableGroup2({
name: "crosshairs",
zIndex: ZIndexMap6.SERIES_CROSSHAIR
});
this.lineGroup = this.crosshairGroup.appendChild(
new Group5({
name: `${this.id}-crosshair-lines`,
zIndex: ZIndexMap6.SERIES_CROSSHAIR
})
);
this.lineGroupSelection = _ModuleSupport70.Selection.select(this.lineGroup, Line4, false);
this.activeHighlight = void 0;
this.axisCtx = ctx.parent;
this.labels = {};
this.hideCrosshairs();
ctx.domManager.addEventListener("focusin", ({ target }) => {
if (this.checkInteractionState())
return;
const isSeriesAreaChild = target instanceof HTMLElement && ctx.domManager.contains(target, "series-area");
if (this.crosshairGroup.visible && !isSeriesAreaChild) {
this.hideCrosshairs();
this.ctx.updateService.update(ChartUpdateType5.SCENE_RENDER);
}
});
const { seriesDragInterpreter } = ctx.widgets;
this.cleanup.register(
ctx.scene.attachNode(this.crosshairGroup),
ctx.widgets.seriesWidget.addListener("mousemove", (event) => this.onMouseHoverLike(event)),
ctx.widgets.seriesWidget.addListener("mouseleave", () => this.onMouseOut()),
ctx.eventsHub.on("series:focus-change", () => this.onKeyPress()),
ctx.eventsHub.on("zoom:pan-start", () => this.onMouseOut()),
ctx.eventsHub.on("zoom:change-complete", () => this.onMouseOut()),
ctx.eventsHub.on("highlight:change", (event) => this.onHighlightChange(event)),
ctx.eventsHub.on("layout:complete", (event) => this.layout(event)),
() => {
for (const label of Object.values(this.labels)) {
label.destroy();
}
}
);
if (seriesDragInterpreter) {
this.cleanup.register(
seriesDragInterpreter.events.on("drag-move", (event) => this.onMouseHoverLike(event)),
seriesDragInterpreter.events.on("click", (event) => this.onClick(event))
);
}
}
checkInteractionState() {
return this.ctx.interactionManager.isState(InteractionState4.Frozen);
}
layout({ series: { rect, visible }, axes }) {
if (!visible || !axes || !this.enabled)
return;
this.seriesRect = rect;
const { position: axisPosition = "left", axisId } = this.axisCtx;
const axisLayout = axes[axisId];
if (!axisLayout)
return;
this.axisLayout = axisLayout;
this.bounds = rect.clone().grow(axisLayout.gridPadding + axisLayout.seriesAreaPadding, axisPosition);
const { crosshairGroup, bounds } = this;
crosshairGroup.translationX = Math.round(bounds.x);
crosshairGroup.translationY = Math.round(bounds.y);
const crosshairKeys = ["pointer", ...this.axisCtx.seriesKeyProperties()];
this.updateSelections(crosshairKeys);
this.updateLines();
this.updateLabels(crosshairKeys);
this.refreshPositions();
}
updateSelections(data) {
this.lineGroupSelection.update(data, void 0, (key) => key);
}
updateLabels(keys) {
const { labels, ctx } = this;
for (const key of keys) {
if (this.label.enabled) {
labels[key] ?? (labels[key] = new CrosshairLabel(ctx.domManager, key, this.axisCtx.axisId));
}
if (labels[key]) {
this.updateLabel(labels[key]);
}
}
}
updateLabel(label) {
const { enabled, xOffset, yOffset, format, renderer } = this.label;
label.enabled = enabled;
label.xOffset = xOffset;
label.yOffset = yOffset;
label.format = format;
label.renderer = renderer;
}
updateLines() {
const { lineGroupSelection, bounds, stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset, axisLayout } = this;
if (!axisLayout)
return;
const isVertical = this.isVertical();
lineGroupSelection.each((line) => {
line.stroke = stroke3;
line.strokeWidth = strokeWidth;
line.strokeOpacity = strokeOpacity;
line.lineDash = lineDash;
line.lineDashOffset = lineDashOffset;
line.y1 = 0;
line.y2 = isVertical ? bounds.height : 0;
line.x1 = 0;
line.x2 = isVertical ? 0 : bounds.width;
});
}
isVertical() {
return this.axisCtx.direction === ChartAxisDirection11.X;
}
isHover(event) {
return event.type === "mousemove" || event.type === "click" || event.device === "touch" && this.ctx.chartService.touch.dragAction === "hover";
}
formatValue(value) {
return toPlainText2(this.axisCtx.formatScaleValue(value, "crosshair", this.label));
}
onClick(event) {
if (event.device === "touch") {
this.onMouseHoverLike(event);
}
}
onMouseHoverLike(event) {
if (!this.enabled || this.snap)
return;
const requiredState = this.isHover(event) ? InteractionState4.Clickable : InteractionState4.AnnotationsMoveable;
if (!this.ctx.interactionManager.isState(requiredState))
return;
this.updatePositions(this.getData(event));
this.crosshairGroup.visible = true;
this.ctx.updateService.update(ChartUpdateType5.SCENE_RENDER);
}
onMouseOut() {
if (!this.ctx.interactionManager.isState(InteractionState4.Clickable))
return;
this.hideCrosshairs();
this.ctx.updateService.update(ChartUpdateType5.SCENE_RENDER);
}
onKeyPress() {
if (this.enabled && !this.snap && this.ctx.interactionManager.isState(InteractionState4.Default)) {
this.hideCrosshairs();
}
}
onHighlightChange(event) {
if (!this.enabled)
return;
const { crosshairGroup, axisCtx } = this;
const { datum, series } = event.currentHighlight ?? {};
const hasCrosshair = datum && (series?.axes.x?.id === axisCtx.axisId || series?.axes.y?.id === axisCtx.axisId);
this.activeHighlight = hasCrosshair ? event.currentHighlight : void 0;
if (!this.activeHighlight) {
this.hideCrosshairs();
} else if (this.snap) {
const activeHighlightData = this.getActiveHighlightData(this.activeHighlight);
this.updatePositions(activeHighlightData);
crosshairGroup.visible = true;
}
}
isInRange(value) {
return this.axisCtx.inRange(value);
}
refreshPositions() {
if (this.activeHighlight) {
this.updatePositions(this.getActiveHighlightData(this.activeHighlight));
}
}
updatePositions(data) {
const { seriesRect, lineGroupSelection } = this;
lineGroupSelection.each((line, key) => {
const lineData = data[key];
if (!lineData) {
line.visible = false;
this.hideLabel(key);
return;
}
line.visible = true;
const { value, position } = lineData;
let x = 0;
let y = 0;
if (this.isVertical()) {
x = position;
line.x = Math.round(x);
} else {
y = position;
line.y = Math.round(y);
}
if (this.label.enabled) {
this.showLabel(x + seriesRect.x, y + seriesRect.y, value, key);
} else {
this.hideLabel(key);
}
});
}
getData(event) {
const { axisCtx } = this;
const key = "pointer";
const { xKey = "", yKey = "" } = this.activeHighlight ?? {};
const { currentX, currentY } = event;
const datum = readDatum(this.activeHighlight);
const isVertical = this.isVertical();
const position = isVertical ? currentX : currentY;
let value = datum?.[isVertical ? xKey : yKey] ?? "";
if (axisCtx.continuous) {
value = axisCtx.scaleInvert(position);
}
return { [key]: { position, value } };
}
getActiveHighlightData(activeHighlight) {
const { axisCtx } = this;
const { series, xKey = "", aggregatedValue, cumulativeValue, midPoint } = activeHighlight;
const datum = readDatum(activeHighlight);
const seriesKeyProperties = series.getKeyProperties(axisCtx.direction);
const halfBandwidth = (axisCtx.scale.bandwidth ?? 0) / 2;
const matchingAxisId = series.axes[axisCtx.direction]?.id === axisCtx.axisId;
const isYKey = seriesKeyProperties.includes("yKey") && matchingAxisId;
const isXKey = seriesKeyProperties.includes("xKey") && matchingAxisId;
const datumValue = aggregatedValue ?? cumulativeValue;
if (isYKey && datumValue !== void 0) {
const position = axisCtx.scale.convert(datumValue) + halfBandwidth;
const isInRange = this.isInRange(position);
return isInRange ? {
yKey: { value: datumValue, position }
} : {};
}
if (isXKey) {
const position = (this.isVertical() ? midPoint?.x : midPoint?.y) ?? 0;
const value = axisCtx.continuous ? axisCtx.scaleInvert(position) : datum?.[xKey];
return this.isInRange(position) ? { xKey: { value, position } } : {};
}
const activeHighlightData = {};
for (const key of seriesKeyProperties) {
const keyValue = series.properties[key];
const value = datum?.[keyValue];
const position = axisCtx.scale.convert(value) + halfBandwidth;
const isInRange = this.isInRange(position);
if (isInRange) {
activeHighlightData[key] = { value, position };
}
}
return activeHighlightData;
}
getLabelHtml(value, label) {
const fractionDigits = this.axisLayout?.label?.fractionDigits ?? 0;
const defaults = { text: this.formatValue(value) };
if (this.label.renderer) {
return label.toLabelHtml(this.label.renderer({ value, fractionDigits }), defaults);
}
return label.toLabelHtml(defaults);
}
showLabel(x, y, value, key) {
if (!this.axisLayout)
return;
const { bounds } = this;
const label = this.labels[key];
const html = this.getLabelHtml(value, label);
label.setLabelHtml(html);
const { width, height } = label.getBBox();
const axisPosition = this.axisCtx.position;
let padding2 = this.axisLayout.label.spacing + this.axisLayout.tickSize;
if (this.axisCtx.direction === ChartAxisDirection11.X) {
padding2 -= 4;
label.show({
x: x - width / 2,
y: axisPosition === "bottom" ? bounds.y + bounds.height + padding2 : bounds.y - height - padding2
});
} else {
padding2 -= 8;
label.show({
x: axisPosition === "right" ? bounds.x + bounds.width + padding2 : bounds.x - width - padding2,
y: y - height / 2
});
}
}
hideCrosshairs() {
this.crosshairGroup.visible = false;
for (const key of Object.keys(this.labels)) {
this.hideLabel(key);
}
}
hideLabel(key) {
this.labels[key]?.toggle(false);
}
};
Crosshair.className = "Crosshair";
__decorateClass([
Property42
], Crosshair.prototype, "enabled", 2);
__decorateClass([
Property42
], Crosshair.prototype, "stroke", 2);
__decorateClass([
Property42
], Crosshair.prototype, "lineDash", 2);
__decorateClass([
Property42
], Crosshair.prototype, "lineDashOffset", 2);
__decorateClass([
Property42
], Crosshair.prototype, "strokeWidth", 2);
__decorateClass([
Property42
], Crosshair.prototype, "strokeOpacity", 2);
__decorateClass([
Property42
], Crosshair.prototype, "snap", 2);
__decorateClass([
Property42
], Crosshair.prototype, "label", 2);
// packages/ag-charts-enterprise/src/features/crosshair/crosshairModule.ts
var CrosshairModule = {
type: "axis:plugin",
name: "crosshair",
chartType: "cartesian",
enterprise: true,
version: VERSION11,
themeTemplate: {
enabled: {
$if: [
{
$or: [
{ $eq: [{ $path: "../type" }, "number"] },
{ $eq: [{ $path: "../type" }, "log"] },
{ $eq: [{ $path: "../type" }, "time"] },
{ $eq: [{ $path: "../type" }, "unit-time"] },
{ $eq: [{ $path: "../type" }, "ordinal-time"] }
]
},
true,
false
]
},
snap: true,
stroke: { $ref: "subtleTextColor" },
strokeWidth: 1,
strokeOpacity: 1,
lineDash: [5, 6],
lineDashOffset: 0,
label: {
enabled: true
}
},
create: (ctx) => new Crosshair(ctx)
};
// packages/ag-charts-enterprise/src/features/data-source/dataSourceModule.ts
import { VERSION as VERSION12 } from "ag-charts-community";
import { boolean as boolean4, callback, positiveNumber as positiveNumber2, undocumented as undocumented3 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/data-source/dataSource.ts
import "ag-charts-community";
import { AbstractModuleInstance as AbstractModuleInstance9, ActionOnSet as ActionOnSet6, Property as Property43 } from "ag-charts-core";
var DataSource = class extends AbstractModuleInstance9 {
constructor(ctx) {
super();
this.enabled = true;
this.getData = () => Promise.resolve();
this.dataService = ctx.dataService;
let dirty = false;
this.cleanup.register(
ctx.eventsHub.on("data:load", () => {
dirty = true;
}),
ctx.eventsHub.on("layout:complete", () => {
if (dirty) {
ctx.zoomManager.updateZoom({ source: "data-update", sourceDetail: "dataSource" });
}
})
);
}
updateCallback(enabled, getData) {
if (!this.dataService)
return;
if (enabled && getData != null) {
this.dataService.updateCallback(getData);
} else {
this.dataService.clearCallback();
}
}
};
__decorateClass([
ActionOnSet6({
newValue(enabled) {
this.updateCallback(enabled, this.getData);
}
}),
Property43
], DataSource.prototype, "enabled", 2);
__decorateClass([
ActionOnSet6({
newValue(getData) {
this.updateCallback(this.enabled, getData);
}
}),
Property43
], DataSource.prototype, "getData", 2);
__decorateClass([
ActionOnSet6({
newValue(requestThrottle) {
this.dataService.requestThrottle = requestThrottle;
}
})
], DataSource.prototype, "requestThrottle", 2);
__decorateClass([
ActionOnSet6({
newValue(updateThrottle) {
this.dataService.dispatchThrottle = updateThrottle;
}
})
], DataSource.prototype, "updateThrottle", 2);
__decorateClass([
ActionOnSet6({
newValue(updateDuringInteraction) {
this.dataService.dispatchOnlyLatest = !updateDuringInteraction;
}
})
], DataSource.prototype, "updateDuringInteraction", 2);
// packages/ag-charts-enterprise/src/features/data-source/dataSourceModule.ts
var DataSourceModule = {
type: "plugin",
name: "dataSource",
enterprise: true,
version: VERSION12,
options: {
getData: callback,
requestThrottle: undocumented3(positiveNumber2),
updateThrottle: undocumented3(positiveNumber2),
updateDuringInteraction: undocumented3(boolean4)
},
create: (ctx) => new DataSource(ctx)
};
// packages/ag-charts-enterprise/src/features/error-bar/errorBarModule.ts
import { VERSION as VERSION13 } from "ag-charts-community";
import { errorBarOptionsDefs } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/error-bar/errorBar.ts
import { _ModuleSupport as _ModuleSupport73 } from "ag-charts-community";
import {
AbstractModuleInstance as AbstractModuleInstance10,
ChartAxisDirection as ChartAxisDirection12,
Logger as Logger6,
isDefined,
mergeDefaults as mergeDefaults2
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/error-bar/errorBarNode.ts
import { _ModuleSupport as _ModuleSupport72 } from "ag-charts-community";
import {
mergeDefaults,
nearestSquared,
nearestSquaredInContainer,
partialAssign
} from "ag-charts-core";
var { BBox: BBox6 } = _ModuleSupport72;
var HierarchicalBBox = class {
constructor(components) {
this.components = components;
this.union = BBox6.merge(components);
}
containsPoint(x, y) {
if (!this.union.containsPoint(x, y)) {
return false;
}
for (const bbox of this.components) {
if (bbox.containsPoint(x, y)) {
return true;
}
}
return false;
}
};
var ErrorBarNode = class extends _ModuleSupport72.Group {
constructor() {
super();
this.capLength = Number.NaN;
this._datum = void 0;
this.whiskerPath = new _ModuleSupport72.Path();
this.capsPath = new _ModuleSupport72.Path();
this.bboxes = new HierarchicalBBox([]);
this.append([this.whiskerPath, this.capsPath]);
}
get datum() {
return this._datum;
}
set datum(datum) {
this._datum = datum;
}
calculateCapLength(capsTheme, capDefaults) {
const { lengthRatio = 1, length } = capsTheme;
const { lengthRatioMultiplier, lengthMax } = capDefaults;
const desiredLength = length ?? lengthRatio * lengthRatioMultiplier;
return Math.min(desiredLength, lengthMax);
}
getItemStylerParams(options, style, highlighted, highlightState) {
const { datum } = this;
if (datum == null || options.itemStyler == null)
return;
const { xLowerKey, xUpperKey, yLowerKey, yUpperKey } = options;
return {
...style,
datum: datum.datum,
seriesId: datum.series.id,
xKey: datum.xKey,
yKey: datum.yKey,
xLowerKey,
xUpperKey,
yLowerKey,
yUpperKey,
highlighted,
highlightState
};
}
formatStyles(style, options, caller, highlighted, highlightState) {
let { cap: capsStyle, ...whiskerStyle } = style;
const params = this.getItemStylerParams(options, style, highlighted, highlightState);
if (params != null && options.itemStyler != null) {
const result = caller.callWithContext(options.itemStyler, params);
whiskerStyle = mergeDefaults(result, whiskerStyle);
capsStyle = mergeDefaults(result?.cap, result, capsStyle);
}
return { whiskerStyle, capsStyle };
}
applyStyling(target, source) {
partialAssign(
["visible", "stroke", "strokeWidth", "strokeOpacity", "lineDash", "lineDashOffset"],
target,
source
);
}
update(style, formatters, caller, highlighted, highlightState) {
if (this.datum === void 0) {
return;
}
const { whiskerStyle, capsStyle } = this.formatStyles(style, formatters, caller, highlighted, highlightState);
const { xBar, yBar, capDefaults } = this.datum;
const whisker = this.whiskerPath;
this.applyStyling(whisker, whiskerStyle);
whisker.path.clear(true);
if (yBar !== void 0) {
whisker.path.moveTo(yBar.lowerPoint.x, yBar.lowerPoint.y);
whisker.path.lineTo(yBar.upperPoint.x, yBar.upperPoint.y);
}
if (xBar !== void 0) {
whisker.path.moveTo(xBar.lowerPoint.x, xBar.lowerPoint.y);
whisker.path.lineTo(xBar.upperPoint.x, xBar.upperPoint.y);
}
whisker.path.closePath();
this.capLength = this.calculateCapLength(capsStyle ?? {}, capDefaults);
const capOffset = this.capLength / 2;
const caps = this.capsPath;
this.applyStyling(caps, capsStyle);
caps.path.clear(true);
if (yBar !== void 0) {
caps.path.moveTo(yBar.lowerPoint.x - capOffset, yBar.lowerPoint.y);
caps.path.lineTo(yBar.lowerPoint.x + capOffset, yBar.lowerPoint.y);
caps.path.moveTo(yBar.upperPoint.x - capOffset, yBar.upperPoint.y);
caps.path.lineTo(yBar.upperPoint.x + capOffset, yBar.upperPoint.y);
}
if (xBar !== void 0) {
caps.path.moveTo(xBar.lowerPoint.x, xBar.lowerPoint.y - capOffset);
caps.path.lineTo(xBar.lowerPoint.x, xBar.lowerPoint.y + capOffset);
caps.path.moveTo(xBar.upperPoint.x, xBar.upperPoint.y - capOffset);
caps.path.lineTo(xBar.upperPoint.x, xBar.upperPoint.y + capOffset);
}
caps.path.closePath();
}
updateBBoxes() {
const { capLength, whiskerPath: whisker, capsPath: caps } = this;
const { yBar, xBar } = this.datum ?? {};
const capOffset = capLength / 2;
const components = [];
if (yBar !== void 0) {
const whiskerHeight = yBar.lowerPoint.y - yBar.upperPoint.y;
components.push(
new BBox6(yBar.lowerPoint.x, yBar.upperPoint.y, whisker.strokeWidth, whiskerHeight),
new BBox6(yBar.lowerPoint.x - capOffset, yBar.lowerPoint.y, capLength, caps.strokeWidth),
new BBox6(yBar.upperPoint.x - capOffset, yBar.upperPoint.y, capLength, caps.strokeWidth)
);
}
if (xBar !== void 0) {
const whiskerWidth = xBar.upperPoint.x - xBar.lowerPoint.x;
components.push(
new BBox6(xBar.lowerPoint.x, xBar.upperPoint.y, whiskerWidth, whisker.strokeWidth),
new BBox6(xBar.lowerPoint.x, xBar.lowerPoint.y - capOffset, caps.strokeWidth, capLength),
new BBox6(xBar.upperPoint.x, xBar.upperPoint.y - capOffset, caps.strokeWidth, capLength)
);
}
this.bboxes.components = components;
this.bboxes.union = BBox6.merge(components);
}
containsPoint(x, y) {
return this.bboxes.containsPoint(x, y);
}
pickNode(x, y) {
return this.containsPoint(x, y) ? this : void 0;
}
nearestSquared(x, y, maxDistance) {
const { bboxes } = this;
if (bboxes.union.distanceSquared(x, y) > maxDistance) {
return { nearest: void 0, distanceSquared: Infinity };
}
const { distanceSquared } = nearestSquared(x, y, bboxes.components);
return { nearest: this, distanceSquared };
}
};
var ErrorBarGroup = class extends _ModuleSupport72.Group {
nearestSquared(x, y) {
const { nearest, distanceSquared } = nearestSquaredInContainer(x, y, {
children: this.children()
});
if (nearest !== void 0 && !Number.isNaN(distanceSquared)) {
return { datum: nearest.datum, distanceSquared };
}
}
};
// packages/ag-charts-enterprise/src/features/error-bar/errorBarProperties.ts
import "ag-charts-community";
import { BaseProperties as BaseProperties17, Property as Property44 } from "ag-charts-core";
var ErrorBarCap = class extends BaseProperties17 {
};
__decorateClass([
Property44
], ErrorBarCap.prototype, "visible", 2);
__decorateClass([
Property44
], ErrorBarCap.prototype, "stroke", 2);
__decorateClass([
Property44
], ErrorBarCap.prototype, "strokeWidth", 2);
__decorateClass([
Property44
], ErrorBarCap.prototype, "strokeOpacity", 2);
__decorateClass([
Property44
], ErrorBarCap.prototype, "lineDash", 2);
__decorateClass([
Property44
], ErrorBarCap.prototype, "lineDashOffset", 2);
__decorateClass([
Property44
], ErrorBarCap.prototype, "length", 2);
__decorateClass([
Property44
], ErrorBarCap.prototype, "lengthRatio", 2);
var ErrorBarProperties = class extends BaseProperties17 {
constructor() {
super(...arguments);
this.visible = true;
this.stroke = "black";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.cap = new ErrorBarCap();
}
};
__decorateClass([
Property44
], ErrorBarProperties.prototype, "yLowerKey", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "yLowerName", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "yUpperKey", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "yUpperName", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "xLowerKey", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "xLowerName", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "xUpperKey", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "xUpperName", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "visible", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "stroke", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "lineDash", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "itemStyler", 2);
__decorateClass([
Property44
], ErrorBarProperties.prototype, "cap", 2);
// packages/ag-charts-enterprise/src/features/error-bar/errorBar.ts
var { fixNumericExtent, groupAccumulativeValueProperty, valueProperty: valueProperty2 } = _ModuleSupport73;
var ErrorBars = class _ErrorBars extends AbstractModuleInstance10 {
constructor(ctx) {
super();
this.properties = new ErrorBarProperties();
const series = ctx.series;
const { annotationGroup, annotationSelections } = series;
this.cartesianSeries = series;
this.groupNode = new ErrorBarGroup({
name: `${annotationGroup.id}-errorBars`
});
annotationGroup.appendChild(this.groupNode);
this.selection = _ModuleSupport73.Selection.select(this.groupNode, () => this.errorBarFactory());
annotationSelections.add(this.selection);
series.addEventListener("seriesVisibilityChange", (e) => this.onToggleSeriesItem(e));
this.cleanup.register(
series.events.on("data-processed", (e) => this.onDataProcessed(e)),
series.events.on("data-update", (e) => this.onDataUpdate(e)),
ctx.eventsHub.on("highlight:change", (event) => this.onHighlightChange(event)),
() => this.groupNode.remove(),
() => annotationSelections.delete(this.selection)
);
}
hasErrorBars() {
const { xLowerKey, xUpperKey, yLowerKey, yUpperKey } = this.properties;
return isDefined(xLowerKey) && isDefined(xUpperKey) || isDefined(yLowerKey) && isDefined(yUpperKey);
}
isStacked() {
const stackCount = this.cartesianSeries.seriesGrouping?.stackCount;
return stackCount == null ? false : stackCount > 0;
}
getUnstackPropertyDefinition(opts) {
const props = [];
const { xLowerKey, xUpperKey, yLowerKey, yUpperKey, xErrorsID, yErrorsID } = this.getMaybeFlippedKeys();
const { xScaleType, yScaleType } = opts;
if (yLowerKey != null && yUpperKey != null) {
props.push(
valueProperty2(yLowerKey, yScaleType, { id: `${yErrorsID}-lower` }),
valueProperty2(yUpperKey, yScaleType, { id: `${yErrorsID}-upper` })
);
}
if (xLowerKey != null && xUpperKey != null) {
props.push(
valueProperty2(xLowerKey, xScaleType, { id: `${xErrorsID}-lower` }),
valueProperty2(xUpperKey, xScaleType, { id: `${xErrorsID}-upper` })
);
}
return props;
}
getStackPropertyDefinition(opts) {
const props = [];
const { cartesianSeries } = this;
const { xLowerKey, xUpperKey, yLowerKey, yUpperKey, xErrorsID, yErrorsID } = this.getMaybeFlippedKeys();
const { xScaleType, yScaleType } = opts;
const groupIndex = cartesianSeries.seriesGrouping?.groupIndex ?? cartesianSeries.id;
const groupOpts = {
invalidValue: null,
missingValue: 0,
separateNegative: true,
...cartesianSeries.visible ? {} : { forceValue: 0 }
};
const makeErrorProperty = (key, id, type, scaleType) => {
return groupAccumulativeValueProperty(
key,
"normal",
{
id: `${id}-${type}`,
groupId: `errorGroup-${groupIndex}-${type}`,
...groupOpts
},
scaleType
);
};
const pushErrorProperties = (lowerKey, upperKey, id, scaleType) => {
props.push(
...makeErrorProperty(lowerKey, id, "lower", scaleType),
...makeErrorProperty(upperKey, id, "upper", scaleType)
);
};
if (yLowerKey != null && yUpperKey != null) {
pushErrorProperties(yLowerKey, yUpperKey, yErrorsID, yScaleType);
}
if (xLowerKey != null && xUpperKey != null) {
pushErrorProperties(xLowerKey, xUpperKey, xErrorsID, xScaleType);
}
return props;
}
getPropertyDefinitions(opts) {
if (this.isStacked()) {
return this.getStackPropertyDefinition(opts);
} else {
return this.getUnstackPropertyDefinition(opts);
}
}
onDataProcessed(event) {
this.dataModel = event.dataModel;
this.processedData = event.processedData;
}
getDomain(direction) {
const { xLowerKey, xUpperKey, xErrorsID, yLowerKey, yUpperKey, yErrorsID } = this.getMaybeFlippedKeys();
const hasAxisErrors = direction === ChartAxisDirection12.X ? isDefined(xLowerKey) && isDefined(xUpperKey) : isDefined(yLowerKey) && isDefined(yUpperKey);
if (hasAxisErrors) {
const { dataModel, processedData, cartesianSeries: series } = this;
if (dataModel != null && processedData != null) {
const id = { x: xErrorsID, y: yErrorsID }[direction];
const lowerDomain = dataModel.getDomain(series, `${id}-lower`, "value", processedData).domain;
const upperDomain = dataModel.getDomain(series, `${id}-upper`, "value", processedData).domain;
const domain = [Math.min(...lowerDomain, ...upperDomain), Math.max(...lowerDomain, ...upperDomain)];
return fixNumericExtent(domain);
}
}
return [];
}
onDataUpdate(event) {
this.dataModel = event.dataModel;
this.processedData = event.processedData;
if (isDefined(event.dataModel) && isDefined(event.processedData)) {
this.createNodeData();
this.update();
}
}
getNodeData() {
return this.hasErrorBars() ? this.cartesianSeries.contextNodeData?.nodeData : void 0;
}
createNodeData() {
const nodeData = this.getNodeData();
const xScale = this.cartesianSeries.axes[ChartAxisDirection12.X]?.scale;
const yScale = this.cartesianSeries.axes[ChartAxisDirection12.Y]?.scale;
if (!xScale || !yScale || !nodeData) {
return;
}
for (let i = 0; i < nodeData.length; i++) {
const { midPoint, xLower, xUpper, yLower, yUpper } = this.getDatum(nodeData, i);
if (midPoint != null) {
let xBar, yBar;
if (isDefined(xLower) && isDefined(xUpper)) {
xBar = {
lowerPoint: { x: this.convert(xScale, xLower), y: midPoint.y },
upperPoint: { x: this.convert(xScale, xUpper), y: midPoint.y }
};
}
if (isDefined(yLower) && isDefined(yUpper)) {
yBar = {
lowerPoint: { x: midPoint.x, y: this.convert(yScale, yLower) },
upperPoint: { x: midPoint.x, y: this.convert(yScale, yUpper) }
};
}
nodeData[i].xBar = xBar;
nodeData[i].yBar = yBar;
}
}
}
getMaybeFlippedKeys() {
let { xLowerKey, xUpperKey, yLowerKey, yUpperKey } = this.properties;
let [xErrorsID, yErrorsID] = ["xValue-errors", "yValue-errors"];
if (this.cartesianSeries.shouldFlipXY()) {
[xLowerKey, yLowerKey] = [yLowerKey, xLowerKey];
[xUpperKey, yUpperKey] = [yUpperKey, xUpperKey];
[xErrorsID, yErrorsID] = [yErrorsID, xErrorsID];
}
return { xLowerKey, xUpperKey, xErrorsID, yLowerKey, yUpperKey, yErrorsID };
}
static getDatumKey(nodeDatum, key, offset) {
if (key == null) {
return;
}
const datum = readDatum(nodeDatum);
const value = datum?.[key];
if (value == null) {
return;
}
if (typeof value !== "number") {
Logger6.warnOnce(`Found [${key}] error value of type ${typeof value}. Expected number type`);
return;
}
return value + offset;
}
getDatum(nodeData, datumIndex) {
const { xLowerKey, xUpperKey, yLowerKey, yUpperKey } = this.getMaybeFlippedKeys();
const datum = nodeData[datumIndex];
const d = datum.cumulativeValue == null || !this.isStacked() ? 0 : datum.cumulativeValue - datum.yValue;
const [xOffset, yOffset] = this.cartesianSeries.shouldFlipXY() ? [d, 0] : [0, d];
return {
midPoint: datum.midPoint,
xLower: _ErrorBars.getDatumKey(datum, xLowerKey, xOffset),
xUpper: _ErrorBars.getDatumKey(datum, xUpperKey, xOffset),
yLower: _ErrorBars.getDatumKey(datum, yLowerKey, yOffset),
yUpper: _ErrorBars.getDatumKey(datum, yUpperKey, yOffset)
};
}
convert(scale, value) {
const offset = (scale.bandwidth ?? 0) / 2;
return scale.convert(value) + offset;
}
update() {
const nodeData = this.getNodeData();
if (nodeData != null) {
this.selection.update(nodeData);
this.selection.each((node, datum, i) => this.updateNode(node, datum, i));
}
}
updateNode(node, datum, _index) {
node.datum = datum;
node.update(this.getDefaultStyle(), this.properties, this.cartesianSeries, false, "none");
node.updateBBoxes();
}
pickNodeExact(point) {
const { x, y } = point;
const node = this.groupNode.pickNode(x, y);
if (node != null) {
return { datum: node.datum, distanceSquared: 0 };
}
}
pickNodeNearest(point) {
return this.groupNode.nearestSquared(point.x, point.y);
}
pickNodeMainAxisFirst(point, majorDirection) {
let closestDatum;
let closestDistance = [Infinity, Infinity];
const referencePoints = [point.x, point.y];
if (majorDirection === ChartAxisDirection12.Y) {
referencePoints.reverse();
}
for (const child of this.groupNode.children()) {
const childBBox = child.getBBox();
const childReferencePoints = [childBBox.x + childBBox.width / 2, childBBox.y + childBBox.height / 2];
if (majorDirection === ChartAxisDirection12.Y) {
childReferencePoints.reverse();
}
const childDistances = [];
for (let i = 0; i < referencePoints.length; i++) {
childDistances.push(Math.abs(referencePoints[i] - childReferencePoints[i]));
}
if (childDistances[0] < closestDistance[0] || childDistances[0] == closestDistance[0] && childDistances[1] < closestDistance[1]) {
closestDatum = child.datum;
closestDistance = childDistances;
}
}
if (closestDatum) {
return {
datum: closestDatum,
distanceSquared: Math.pow(closestDistance[0], 2) + Math.pow(closestDistance[1], 2)
};
}
}
getTooltipParams() {
const {
xLowerKey,
xUpperKey,
yLowerKey,
yUpperKey,
xLowerName = xLowerKey,
xUpperName = xUpperKey,
yLowerName = yLowerKey,
yUpperName = yUpperKey
} = this.properties;
return { xLowerKey, xLowerName, xUpperKey, xUpperName, yLowerKey, yLowerName, yUpperKey, yUpperName };
}
onToggleSeriesItem(event) {
this.groupNode.visible = event.visible;
}
makeStyle(baseStyle) {
return {
visible: baseStyle.visible,
lineDash: baseStyle.lineDash,
lineDashOffset: baseStyle.lineDashOffset,
stroke: baseStyle.stroke,
strokeWidth: baseStyle.strokeWidth,
strokeOpacity: baseStyle.strokeOpacity,
cap: mergeDefaults2(this.properties.cap, baseStyle)
};
}
getDefaultStyle() {
return this.makeStyle(this.getWhiskerProperties());
}
getHighlightStyle() {
return this.makeStyle(this.getWhiskerProperties());
}
restyleHighlightChange(highlightChange, style, highlighted) {
const nodeData = this.getNodeData();
if (nodeData == null)
return;
for (let i = 0; i < nodeData.length; i++) {
if (highlightChange === nodeData[i]) {
this.selection.at(i)?.update(
style,
this.properties,
this.cartesianSeries,
highlighted,
highlighted ? "highlighted-item" : "unhighlighted-item"
);
break;
}
}
}
onHighlightChange(event) {
const { previousHighlight, currentHighlight } = event;
if (currentHighlight?.series === this.cartesianSeries) {
this.restyleHighlightChange(currentHighlight, this.getHighlightStyle(), true);
}
if (previousHighlight?.series === this.cartesianSeries) {
this.restyleHighlightChange(previousHighlight, this.getDefaultStyle(), false);
}
this.groupNode.opacity = this.cartesianSeries.getOpacity();
}
errorBarFactory() {
return new ErrorBarNode();
}
getWhiskerProperties() {
const { stroke: stroke3, strokeWidth, visible, strokeOpacity, lineDash, lineDashOffset } = this.properties;
return { stroke: stroke3, strokeWidth, visible, strokeOpacity, lineDash, lineDashOffset };
}
};
// packages/ag-charts-enterprise/src/features/error-bar/errorBarModule.ts
var ErrorBarsModule = {
type: "series:plugin",
name: "errorBar",
chartType: "cartesian",
seriesTypes: ["bar", "line", "scatter"],
enterprise: true,
version: VERSION13,
options: errorBarOptionsDefs,
themeTemplate: {
visible: true,
stroke: { $ref: "foregroundColor" },
strokeWidth: 1,
strokeOpacity: 1,
cap: {
lengthRatio: {
$if: [{ $eq: [{ $path: "../../type" }, "bar"] }, 0.3, 1]
}
}
},
create: (ctx) => new ErrorBars(ctx)
};
// packages/ag-charts-enterprise/src/features/flash-on-update/flashOnUpdateModule.ts
import { VERSION as VERSION14 } from "ag-charts-community";
import { boolean as boolean5, color, positiveNumber as positiveNumber3, ratio, strictUnion } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/flash-on-update/flashOnUpdate.ts
import { _ModuleSupport as _ModuleSupport74 } from "ag-charts-community";
import {
BaseProperties as BaseProperties18,
ChartAxisDirection as ChartAxisDirection13,
CleanupRegistry as CleanupRegistry4,
Property as Property45,
createElement as createElement6,
setAttribute as setAttribute3,
setElementBBox,
setElementStyle
} from "ag-charts-core";
function findPrimaryCategoryAxisContext(ctx) {
for (const dir of [ChartAxisDirection13.X, ChartAxisDirection13.Y]) {
for (const axisCtx of ctx.axisManager.getAxisContext(dir)) {
if (_ModuleSupport74.BandScale.is(axisCtx.scale)) {
return axisCtx;
}
}
}
}
var FlashOnUpdate = class extends BaseProperties18 {
constructor(ctx) {
super();
this.ctx = ctx;
this.enabled = false;
this.item = "chart";
this.color = "#cfeeff";
this.opacity = 1;
this.flashDuration = 100;
this.fadeDuration = 900;
this.cleanup = new CleanupRegistry4();
this.element = this.ctx.domManager.addChild("canvas-background", "flashOnUpdate");
this.element.role = "presentation";
let firstUpdate = true;
const onDataUpdate = (ev) => {
if (firstUpdate) {
firstUpdate = false;
} else {
this.onDataUpdate(ev);
}
};
this.cleanup.register(
this.ctx.eventsHub.on("data:update", onDataUpdate),
this.ctx.eventsHub.on("datamodel:diff", (e) => this.onDataModelDiff(e))
);
}
destroy() {
this.ctx.domManager.removeChild("canvas-background", "flashOnUpdate");
this.cleanup.flush();
}
clearFlash() {
this.element.innerHTML = "";
clearTimeout(this.animationTimeout);
this.animationTimeout = void 0;
}
flashElem(el) {
const { flashDuration, fadeDuration } = this;
const duration = flashDuration + fadeDuration;
el.animate(
[
{ background: this.color, offset: 0 },
{ background: this.color, offset: flashDuration / duration },
{ background: "transparent", offset: 1 }
],
{ duration, easing: "ease-out" }
);
}
flashCategoryBands(diff8) {
const axisCtx = findPrimaryCategoryAxisContext(this.ctx);
if (!axisCtx)
return;
this.clearFlash();
const flashBounds = this.computeCategoryFlashBounds(axisCtx, diff8);
for (const bounds of flashBounds) {
const e = createElement6("div");
setAttribute3(e, "role", "presentation");
setElementStyle(e, "position", "absolute");
setElementBBox(e, bounds);
this.element.appendChild(e);
this.flashElem(e);
}
const duration = this.flashDuration + this.fadeDuration;
this.animationTimeout = setTimeout(() => this.clearFlash(), duration);
}
computeCategories(diff8) {
const result = /* @__PURE__ */ new Set();
for (const seriesId of Object.keys(diff8)) {
for (const key of ["updated", "added", "moved"]) {
for (const value of diff8[seriesId][key]) {
result.add(value);
}
}
}
return result;
}
computeCategoryFlashBounds(axisCtx, diff8) {
const seriesBounds = this.ctx.widgets.seriesWidget.getBounds();
const makeBox = axisCtx.direction === ChartAxisDirection13.X ? ([start, end]) => {
return {
x: seriesBounds.x + start,
y: seriesBounds.y,
width: end - start,
height: seriesBounds.height
};
} : ([start, end]) => {
return {
x: seriesBounds.x,
y: seriesBounds.y + start,
width: seriesBounds.width,
height: end - start
};
};
const result = [];
const categories = this.computeCategories(diff8);
for (const c of categories) {
const measurements = axisCtx.measureBand(c);
if (measurements?.band) {
result.push(makeBox(measurements.band));
}
}
return result;
}
onDataUpdate(ev) {
if (!this.enabled || this.item !== "chart" || !ev)
return;
this.flashElem(this.ctx.widgets.containerWidget.getElement());
}
onDataModelDiff(ev) {
if (!this.enabled || this.item !== "category")
return;
this.flashCategoryBands(ev.diff);
}
};
FlashOnUpdate.className = "FlashOnUpdate";
__decorateClass([
Property45
], FlashOnUpdate.prototype, "enabled", 2);
__decorateClass([
Property45
], FlashOnUpdate.prototype, "item", 2);
__decorateClass([
Property45
], FlashOnUpdate.prototype, "color", 2);
__decorateClass([
Property45
], FlashOnUpdate.prototype, "opacity", 2);
__decorateClass([
Property45
], FlashOnUpdate.prototype, "flashDuration", 2);
__decorateClass([
Property45
], FlashOnUpdate.prototype, "fadeDuration", 2);
// packages/ag-charts-enterprise/src/features/flash-on-update/flashOnUpdateModule.ts
var FlashOnUpdateModule = {
type: "plugin",
name: "flashOnUpdate",
enterprise: true,
version: VERSION14,
options: {
enabled: boolean5,
item: strictUnion()("chart", "category"),
color,
opacity: ratio,
flashDuration: positiveNumber3,
fadeDuration: positiveNumber3
},
themeTemplate: {
enabled: false,
item: "chart",
color: "#cfeeff",
opacity: 1,
flashDuration: 100,
fadeDuration: 900
},
create: (ctx) => new FlashOnUpdate(ctx)
};
// packages/ag-charts-enterprise/src/features/navigator/navigatorModule.ts
import { VERSION as VERSION22 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/features/navigator/navigator.ts
import { _ModuleSupport as _ModuleSupport81 } from "ag-charts-community";
import { AbstractModuleInstance as AbstractModuleInstance12, Logger as Logger8, ObserveChanges as ObserveChanges4, Property as Property49, clamp as clamp7 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/navigator/miniChart.ts
import { _ModuleSupport as _ModuleSupport76 } from "ag-charts-community";
import {
AbstractModuleInstance as AbstractModuleInstance11,
ActionOnSet as ActionOnSet7,
Logger as Logger7,
Padding,
Property as Property46,
ProxyProperty as ProxyProperty2,
ZIndexMap as ZIndexMap7,
calcLineHeight as calcLineHeight4
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/navigator/shapes/miniChartGroup.ts
import { _ModuleSupport as _ModuleSupport75 } from "ag-charts-community";
import { SceneChangeDetection, getPath2D } from "ag-charts-core";
var { TranslatableGroup: TranslatableGroup3 } = _ModuleSupport75;
var MiniChartGroup = class extends TranslatableGroup3 {
constructor() {
super(...arguments);
this.inset = 0;
this.cornerRadius = 0;
}
applyClip(ctx, clipRect) {
const { cornerRadius, inset } = this;
const { x, y, width, height } = clipRect;
const Path2DCtor = getPath2D();
const path = new Path2DCtor();
path.roundRect(x + inset, y + inset, width - 2 * inset, height - 2 * inset, cornerRadius);
ctx.clip(path);
}
};
__decorateClass([
SceneChangeDetection()
], MiniChartGroup.prototype, "inset", 2);
__decorateClass([
SceneChangeDetection()
], MiniChartGroup.prototype, "cornerRadius", 2);
// packages/ag-charts-enterprise/src/features/navigator/miniChart.ts
var { CategoryAxis, Group: Group6, BBox: BBox7, stackCartesianSeries } = _ModuleSupport76;
var MiniChartPadding = class {
constructor() {
this.top = 0;
this.bottom = 0;
}
};
__decorateClass([
Property46
], MiniChartPadding.prototype, "top", 2);
__decorateClass([
Property46
], MiniChartPadding.prototype, "bottom", 2);
var MiniChart = class extends AbstractModuleInstance11 {
constructor(ctx) {
super();
this.ctx = ctx;
this.enabled = false;
this.padding = new MiniChartPadding();
this.root = new Group6({ name: "root" });
this.seriesRoot = this.root.appendChild(
new MiniChartGroup({ name: "Series-root", zIndex: ZIndexMap7.SERIES_LAYER, renderToOffscreenCanvas: true })
);
this.axisGridGroup = this.root.appendChild(new Group6({ name: "Axes-Grids", zIndex: ZIndexMap7.AXIS_GRID }));
this.axisGroup = this.root.appendChild(new Group6({ name: "Axes-Grids", zIndex: ZIndexMap7.AXIS_GRID }));
this.axisLabelGroup = this.root.appendChild(new Group6({ name: "Axes-Labels", zIndex: ZIndexMap7.SERIES_LABEL }));
this.axisCrosslineRangeGroup = this.root.appendChild(
new Group6({ name: "Axes-Crosslines-Range", zIndex: ZIndexMap7.SERIES_CROSSLINE_RANGE })
);
this.axisCrosslineLineGroup = this.root.appendChild(
new Group6({ name: "Axes-Crosslines-Line", zIndex: ZIndexMap7.SERIES_CROSSLINE_LINE })
);
this.axisCrosslineLabelGroup = this.root.appendChild(
new Group6({ name: "Axes-Crosslines-Label", zIndex: ZIndexMap7.SERIES_LABEL })
);
this.data = [];
this._destroyed = false;
this.miniChartAnimationPhase = "initial";
// Should be available after the first layout.
this.seriesRect = void 0;
this.axes = new _ModuleSupport76.ChartAxes();
this.series = [];
this.cleanup.register(this.ctx.eventsHub.on("data:update", (data) => this.updateData(data)));
}
destroy() {
if (this._destroyed) {
return;
}
super.destroy();
this.destroySeries(this.series);
this.axes.destroy();
this._destroyed = true;
}
onSeriesChange(newValue, oldValue) {
const seriesToDestroy = oldValue?.filter((series) => !newValue.includes(series)) ?? [];
this.destroySeries(seriesToDestroy);
for (const series of newValue) {
if (oldValue?.includes(series))
continue;
series.attachSeries(this.seriesRoot, this.seriesRoot, void 0);
series.chart = {};
Object.defineProperty(series.chart, "mode", {
get: () => "standalone"
});
Object.defineProperty(series.chart, "isMiniChart", {
get: () => true
});
Object.defineProperty(series.chart, "flashOnUpdateEnabled", {
get: () => false
});
Object.defineProperty(series.chart, "seriesRect", {
get: () => this.seriesRect
});
series.resetAnimation(this.miniChartAnimationPhase === "initial" ? "initial" : "disabled");
}
this.seriesRect = void 0;
}
destroySeries(allSeries) {
if (allSeries) {
for (const series of allSeries) {
series.destroy();
series.detachSeries(this.seriesRoot, this.seriesRoot, void 0);
series.chart = void 0;
}
}
}
assignSeriesToAxes() {
for (const axis of this.axes) {
axis.boundSeries = this.series.filter((s) => {
const seriesAxis = s.axes[axis.direction];
return seriesAxis === axis;
});
}
}
assignAxesToSeries() {
const directionToAxesMap = {};
for (const axis of this.axes) {
const direction = axis.direction;
const directionAxes = directionToAxesMap[direction] ?? (directionToAxesMap[direction] = []);
directionAxes.push(axis);
}
for (const series of this.series) {
for (const direction of series.directions) {
const seriesAxisId = series.getKeyAxis(direction) ?? direction;
const newAxis = this.axes.findById(seriesAxisId);
if (!newAxis) {
Logger7.warnOnce(
`no matching axis for direction [${direction}] and id [${seriesAxisId}]; check series and axes configuration.`
);
return;
}
series.axes[direction] = newAxis;
}
}
}
updateData(data) {
for (const s of this.series) {
s.setChartData(data);
}
if (this.miniChartAnimationPhase === "initial") {
this.ctx.animationManager.onBatchStop(() => {
this.miniChartAnimationPhase = "ready";
for (const s of this.series) {
s.resetAnimation("disabled");
}
});
}
}
async processData(dataController) {
if (this.series.some((s) => s.canHaveAxes)) {
this.assignAxesToSeries();
this.assignSeriesToAxes();
}
await Promise.all(
this.series.map(async (s) => {
s.resetDatumCallbackCache();
return s.processData(dataController);
})
);
for (const axis of this.axes) {
axis.processData();
}
}
computeAxisPadding() {
const padding2 = new Padding();
if (!this.enabled) {
return padding2;
}
for (const { position, thickness, line, label } of this.axes) {
if (position == null)
continue;
let size;
if (thickness) {
size = thickness;
} else {
size = (line.enabled ? line.width : 0) + (label.enabled ? calcLineHeight4(label.fontSize ?? 0) + label.spacing : 0);
}
padding2[position] = Math.ceil(size);
}
return padding2;
}
async layout(width, height) {
var _a;
const { padding: padding2 } = this;
const animated = this.seriesRect != null;
const seriesRect = new BBox7(0, 0, width, height - (padding2.top + padding2.bottom));
const resized = this.seriesRect?.width !== width || this.seriesRect?.height !== height;
this.seriesRect = seriesRect;
this.seriesRoot.translationY = padding2.top;
this.seriesRoot.setClipRectCanvasSpace(new BBox7(0, -padding2.top, width, height));
for (const axis of this.axes) {
const { position = "left" } = axis;
switch (position) {
case "top":
case "bottom":
axis.range = [0, seriesRect.width];
axis.gridLength = seriesRect.height;
break;
case "right":
case "left": {
const isCategoryAxis = axis instanceof CategoryAxis;
axis.range = isCategoryAxis ? [0, seriesRect.height] : [seriesRect.height, 0];
axis.gridLength = seriesRect.width;
break;
}
}
axis.gridPadding = 0;
axis.translation.x = 0;
axis.translation.y = 0;
if (position === "right") {
axis.translation.x = width;
} else if (position === "bottom") {
axis.translation.y = height;
}
if (!animated) {
axis.resetAnimation("initial");
}
if (axis.crossLines) {
for (const crossLine of axis.crossLines) {
if (crossLine instanceof _ModuleSupport76.CartesianCrossLine) {
crossLine.position = axis.position ?? "top";
(_a = crossLine.label).parallel ?? (_a.parallel = axis.label?.parallel);
}
}
}
axis.calculateLayout();
axis.update();
}
if (resized) {
stackCartesianSeries(this.series);
}
await Promise.all(this.series.map(async (series) => series.update({ seriesRect })));
}
};
__decorateClass([
Property46
], MiniChart.prototype, "enabled", 2);
__decorateClass([
ProxyProperty2(["seriesRoot", "inset"])
], MiniChart.prototype, "inset", 2);
__decorateClass([
ProxyProperty2(["seriesRoot", "cornerRadius"])
], MiniChart.prototype, "cornerRadius", 2);
__decorateClass([
ActionOnSet7({
changeValue(newValue, oldValue = new _ModuleSupport76.ChartAxes()) {
const axisNodes = {
axisNode: this.axisGroup,
gridNode: this.axisGridGroup,
labelNode: this.axisLabelGroup,
crossLineLineNode: this.axisCrosslineLineGroup,
crossLineRangeNode: this.axisCrosslineRangeGroup,
crossLineLabelNode: this.axisCrosslineLabelGroup
};
for (const axis of oldValue) {
if (newValue.includes(axis))
continue;
axis.detachAxis();
axis.destroy();
}
for (const axis of newValue) {
if (oldValue?.includes(axis))
continue;
axis.attachAxis(axisNodes);
}
}
})
], MiniChart.prototype, "axes", 2);
__decorateClass([
ActionOnSet7({
changeValue(newValue, oldValue) {
this.onSeriesChange(newValue, oldValue);
}
})
], MiniChart.prototype, "series", 2);
// packages/ag-charts-enterprise/src/features/navigator/navigatorDOMProxy.ts
import { _ModuleSupport as _ModuleSupport77 } from "ag-charts-community";
import { clamp as clamp6 } from "ag-charts-core";
var { SliderWidget } = _ModuleSupport77;
var NavigatorDOMProxy = class {
constructor(ctx, sliderHandlers) {
this.ctx = ctx;
this.sliderHandlers = sliderHandlers;
this._min = 0;
this._max = 1;
this.minRange = 1e-3;
this.dragStartX = 0;
this.ctx = ctx;
this.toolbar = ctx.proxyInteractionService.createProxyContainer({
type: "toolbar",
domManagerId: `navigator-toolbar`,
classList: ["ag-charts-proxy-navigator-toolbar"],
orientation: "vertical",
ariaLabel: { id: "ariaLabelNavigator" }
});
this.sliders = [
ctx.proxyInteractionService.createProxyElement({
type: "slider",
domIndex: 1,
ariaLabel: { id: "ariaLabelNavigatorMinimum" },
parent: this.toolbar,
cursor: "ew-resize"
}),
ctx.proxyInteractionService.createProxyElement({
type: "slider",
domIndex: -Infinity,
ariaLabel: { id: "ariaLabelNavigatorRange" },
parent: this.toolbar,
cursor: "grab"
}),
ctx.proxyInteractionService.createProxyElement({
type: "slider",
domIndex: 2,
ariaLabel: { id: "ariaLabelNavigatorMaximum" },
parent: this.toolbar,
cursor: "ew-resize"
})
];
for (const [index, key] of ["min", "pan", "max"].entries()) {
const slider = this.sliders[index];
slider.step = SliderWidget.STEP_HUNDRETH;
slider.keyboardStep = SliderWidget.STEP_ONE;
slider.orientation = "horizontal";
slider.setPreventsDefault(false);
slider.addListener("drag-start", (ev) => this.onDragStart(index, ev, key));
slider.addListener("drag-move", (ev) => this.onDrag(slider, ev, key));
slider.addListener("drag-end", () => this.updateSliderRatios());
slider.addListener("contextmenu", (ev) => this.onContextMenu(slider, ev));
}
this.sliders[0].addListener("change", () => this.onMinSliderChange());
this.sliders[1].addListener("change", () => this.onPanSliderChange());
this.sliders[2].addListener("change", () => this.onMaxSliderChange());
this.updateSliderRatios();
this.updateVisibility(false);
}
destroy() {
this.toolbar.destroy();
}
updateVisibility(visible) {
this.toolbar.setHidden(!visible);
}
updateZoom() {
const { _min: min, _max: max } = this;
if (min == null || max == null)
return;
this.ctx.zoomManager.updateZoom(
{ source: "user-interaction", sourceDetail: "navigatorDOM" },
{ x: { min, max } }
);
}
updateBounds(bounds) {
this.toolbar.setBounds(bounds);
}
updateSliderBounds(sliderIndex, bounds) {
this.sliders[sliderIndex].setBounds(bounds);
}
updateMinMax(min, max) {
this._min = min;
this._max = max;
this.updateSliderRatios();
}
updateSliderRatios() {
let { _min: min, _max: max } = this;
min = Math.round(min * 100) / 100;
max = Math.round(max * 100) / 100;
const panAria = this.ctx.localeManager.t("ariaValuePanRange", { min, max });
this.sliders[0].setValueRatio(min);
this.sliders[1].setValueRatio(min, { ariaValueText: panAria });
this.sliders[2].setValueRatio(max);
}
toCanvasOffsets(event) {
return { offsetX: this.dragStartX + event.originDeltaX };
}
moveToFront(index) {
if (index === 1)
return;
const frontSlider = this.sliders[index];
const otherSlider = this.sliders[2 - index];
this.toolbar.moveChild(otherSlider, frontSlider.domIndex - 1);
}
onDragStart(index, event, key) {
const slider = this.sliders[index];
const toolbarLeft = this.toolbar.cssLeft();
const sliderLeft = slider.cssLeft();
this.dragStartX = toolbarLeft + sliderLeft + event.offsetX;
this.moveToFront(index);
event.sourceEvent.preventDefault();
this.sliderHandlers.onDragStart(key, this.toCanvasOffsets(event));
}
onDrag(_slider, event, key) {
event.sourceEvent.preventDefault();
this.sliderHandlers.onDrag(key, this.toCanvasOffsets(event));
}
onContextMenu(slider, widgetEvent) {
const { offsetX, offsetY } = widgetEvent;
const { x: toolbarX, y: toolbarY } = this.toolbar.getBounds();
const { x: sliderX, y: sliderY } = slider.getBounds();
const canvasX = offsetX + toolbarX + sliderX;
const canvasY = offsetY + toolbarY + sliderY;
this.ctx.contextMenuRegistry.dispatchContext("always", { widgetEvent, canvasX, canvasY }, void 0);
}
onPanSliderChange() {
const ratio8 = this.sliders[1].getValueRatio();
const span = this._max - this._min;
this._min = clamp6(0, ratio8, 1 - span);
this._max = this._min + span;
this.updateZoom();
}
onMinSliderChange() {
this._min = this.sliders[0].clampValueRatio(0, this._max - this.minRange);
this.updateZoom();
}
onMaxSliderChange() {
this._max = this.sliders[2].clampValueRatio(this._min + this.minRange, 1);
this.updateZoom();
}
};
// packages/ag-charts-enterprise/src/features/navigator/shapes/rangeHandle.ts
import { _ModuleSupport as _ModuleSupport78 } from "ag-charts-community";
import { Property as Property47, SceneChangeDetection as SceneChangeDetection2 } from "ag-charts-core";
var { BBox: BBox8, ExtendedPath2D } = _ModuleSupport78;
var RangeHandle = class extends _ModuleSupport78.Path {
constructor() {
super(...arguments);
this.zIndex = 3;
this.centerX = 0;
this.centerY = 0;
this.width = 8;
this.height = 16;
this.cornerRadius = 4;
this.grip = true;
this.gripPath = new ExtendedPath2D();
}
setCenter(x, y) {
this.dirtyPath = true;
if (this.centerX !== x || this.centerY !== y) {
this.centerX = x;
this.centerY = y;
this.markDirty("center");
}
}
static align(minHandle, maxHandle, x, y, width, height, min, max, pixelAlign) {
const minHandleX = minHandle.align(x + width * min) + pixelAlign;
const maxHandleX = minHandleX + minHandle.align(x + width * min, width * (max - min)) - 2 * pixelAlign;
const handleY = minHandle.align(y + height / 2);
minHandle.setCenter(minHandleX, handleY);
maxHandle.setCenter(maxHandleX, handleY);
}
computeBBox() {
const { centerX, centerY, width, height } = this;
const x = centerX - width / 2;
const y = centerY - height / 2;
return new BBox8(x, y, width, height);
}
isPointInPath(x, y) {
const bbox = this.getBBox();
return bbox.containsPoint(x, y);
}
updatePath() {
const { centerX, centerY, path, gripPath, strokeWidth, cornerRadius, grip } = this;
const pixelAlign = strokeWidth / 2;
const pixelRatio = this.layerManager?.canvas?.pixelRatio ?? 1;
path.clear();
gripPath.clear();
const halfWidth = Math.floor(this.width / 2 * pixelRatio) / pixelRatio;
const halfHeight = Math.floor(this.height / 2 * pixelRatio) / pixelRatio;
path.roundRect(
centerX - halfWidth + pixelAlign,
centerY - halfHeight + pixelAlign,
2 * (halfWidth - pixelAlign),
2 * (halfHeight - pixelAlign),
cornerRadius
);
const gripSpacing = 3;
if (grip) {
for (let x = -0.5; x <= 0.5; x += 1) {
for (let y = -1; y <= 1; y += 1) {
gripPath.arc(centerX + x * gripSpacing, centerY + y * gripSpacing, 1, 0, 2 * Math.PI);
gripPath.closePath();
}
}
}
}
renderFill(ctx, path) {
const { stroke: stroke3 } = this;
super.renderFill(ctx, path);
ctx.fillStyle = typeof stroke3 === "string" ? stroke3 : "black";
ctx.fill(this.gripPath.getPath2D());
}
};
RangeHandle.className = "RangeHandle";
__decorateClass([
Property47,
SceneChangeDetection2()
], RangeHandle.prototype, "width", 2);
__decorateClass([
Property47,
SceneChangeDetection2()
], RangeHandle.prototype, "height", 2);
__decorateClass([
Property47,
SceneChangeDetection2()
], RangeHandle.prototype, "cornerRadius", 2);
__decorateClass([
Property47,
SceneChangeDetection2()
], RangeHandle.prototype, "grip", 2);
// packages/ag-charts-enterprise/src/features/navigator/shapes/rangeMask.ts
import { _ModuleSupport as _ModuleSupport79 } from "ag-charts-community";
import { Property as Property48, SceneChangeDetection as SceneChangeDetection3 } from "ag-charts-core";
var { Path: Path6, BBox: BBox9, ExtendedPath2D: ExtendedPath2D2, clippedRoundRect } = _ModuleSupport79;
var RangeMask = class extends Path6 {
constructor() {
super(...arguments);
this.cornerRadius = 4;
this.zIndex = 2;
this.x = 0;
this.y = 0;
this.width = 200;
this.height = 30;
this.min = 0;
this.max = 1;
this.visiblePath = new ExtendedPath2D2();
}
layout(x, y, width, height, min, max) {
min = Number.isNaN(min) ? this.min : min;
max = Number.isNaN(max) ? this.max : max;
if (x !== this.x || y !== this.y || width !== this.width || this.height !== height || min !== this.min || max !== this.max) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.min = min;
this.max = max;
this.dirtyPath = true;
this.markDirty("RangeMask.layout");
}
}
computeBBox() {
const { x, y, width, height } = this;
return new BBox9(x, y, width, height);
}
computeVisibleRangeBBox() {
const { x, y, width, height, min, max } = this;
const minX = x + width * min;
const maxX = x + width * max;
return new BBox9(minX, y, maxX - minX, height);
}
updatePath() {
const { path, visiblePath, x, y, width, height, min, max, strokeWidth, cornerRadius } = this;
const pixelAlign = strokeWidth / 2;
path.clear();
visiblePath.clear();
const ax = this.align(x) + pixelAlign;
const ay = this.align(y) + pixelAlign;
const aw = this.align(x, width) - 2 * pixelAlign;
const ah = this.align(y, height) - 2 * pixelAlign;
const minX = this.align(x + width * min) + pixelAlign;
const maxX = minX + this.align(x + width * min, width * (max - min)) - 2 * pixelAlign;
const cornerRadiusParams = {
topLeft: cornerRadius,
topRight: cornerRadius,
bottomRight: cornerRadius,
bottomLeft: cornerRadius
};
const drawRect = (p, x0, x1) => {
if (x1 - x0 < 1)
return;
const bbox = new BBox9(x0, ay, x1 - x0, ah);
clippedRoundRect(p, ax, ay, aw, ah, cornerRadiusParams, bbox);
};
drawRect(path, ax, minX);
drawRect(path, maxX, aw + ax);
drawRect(visiblePath, minX, maxX);
}
renderStroke(ctx, path) {
super.renderStroke(ctx, path);
super.renderStroke(ctx, this.visiblePath.getPath2D());
}
};
RangeMask.className = "RangeMask";
__decorateClass([
Property48,
SceneChangeDetection3()
], RangeMask.prototype, "cornerRadius", 2);
// packages/ag-charts-enterprise/src/features/navigator/shapes/rangeSelector.ts
import { _ModuleSupport as _ModuleSupport80 } from "ag-charts-community";
import { ZIndexMap as ZIndexMap8 } from "ag-charts-core";
var RangeSelector = class extends _ModuleSupport80.Group {
constructor(children) {
super({ name: "rangeSelectorGroup", zIndex: ZIndexMap8.NAVIGATOR });
this.x = 0;
this.y = 0;
this.width = 200;
this.height = 30;
this.lOffset = 0;
this.rOffset = 0;
this.background = this.appendChild(
new _ModuleSupport80.TranslatableGroup({ name: "navigator-background", zIndex: 1 })
);
this.append(children);
}
layout(x, y, width, height, lOffset, rOffset) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.lOffset = lOffset;
this.rOffset = rOffset;
this.background.translationX = x;
this.background.translationY = y;
this.markDirty("RangeSelector");
}
updateBackground(oldGroup, newGroup) {
if (oldGroup != null) {
oldGroup.remove();
}
if (newGroup != null) {
this.background.appendChild(newGroup);
}
this.markDirty("RangeSelector");
}
computeBBox() {
const { x, y, width, height, lOffset, rOffset } = this;
return new _ModuleSupport80.BBox(x - lOffset, y, width + (lOffset + rOffset), height);
}
};
// packages/ag-charts-enterprise/src/features/navigator/navigator.ts
var Navigator = class extends AbstractModuleInstance12 {
constructor(ctx) {
super();
this.ctx = ctx;
this.enabled = false;
this.mask = new RangeMask();
this.minHandle = new RangeHandle();
this.maxHandle = new RangeHandle();
this.maskVisibleRange = {
id: "navigator-mask-visible-range",
getBBox: () => this.mask.computeVisibleRangeBBox(),
toCanvasBBox: () => this.mask.computeVisibleRangeBBox(),
fromCanvasPoint: (x, y) => ({ x, y })
};
this.height = 30;
this.cornerRadius = 0;
this.spacing = 10;
this.x = 0;
this.y = 0;
this.width = 0;
this.rangeSelector = new RangeSelector([this.mask, this.minHandle, this.maxHandle]);
this.cleanup.register(
ctx.scene.attachNode(this.rangeSelector),
ctx.eventsHub.on("locale:change", () => this.updateZoom()),
ctx.layoutManager.registerElement(_ModuleSupport81.LayoutElement.Navigator, (e) => this.onLayoutStart(e)),
ctx.eventsHub.on("layout:complete", (e) => this.onLayoutComplete(e)),
ctx.eventsHub.on("zoom:change-complete", (event) => this.onZoomChange(event))
);
this.domProxy = new NavigatorDOMProxy(ctx, this);
this.updateGroupVisibility();
this.miniChart = new MiniChart(ctx);
}
updateBackground(oldGroup, newGroup) {
this.rangeSelector?.updateBackground(oldGroup, newGroup);
}
updateGroupVisibility() {
const { enabled } = this;
if (this.rangeSelector == null || enabled === this.rangeSelector.visible)
return;
this.rangeSelector.visible = enabled;
this.domProxy.updateVisibility(enabled);
if (enabled) {
this.updateZoom();
} else {
this.ctx.zoomManager.updateZoom(
{ source: "chart-update", sourceDetail: "navigator" },
{ x: { min: 0, max: 1 } }
);
}
}
onLayoutStart({ layoutBox }) {
if (this.enabled) {
const navigatorTotalHeight = this.height + this.spacing;
layoutBox.shrink(navigatorTotalHeight, "bottom");
this.y = layoutBox.y + layoutBox.height + this.spacing;
} else {
this.y = 0;
}
if (this.enabled && this.miniChart) {
const { top, bottom } = this.miniChart.computeAxisPadding();
layoutBox.shrink(top + bottom, "bottom");
this.y -= bottom;
this.miniChart.inset = this.mask.strokeWidth / 2;
this.miniChart.cornerRadius = this.mask.cornerRadius;
}
}
onLayoutComplete(opts) {
const { x, width } = opts.series.rect;
const { y, height } = this;
this.domProxy.updateVisibility(this.enabled);
if (this.enabled) {
const { _min: min, _max: max } = this.domProxy;
this.layoutNodes(x, y, width, height, min, max);
this.domProxy.updateBounds({ x, y, width, height });
}
this.x = x;
this.width = width;
this.miniChart?.layout(width, height).catch((e) => Logger8.error(e));
}
canDrag() {
return this.enabled && this.ctx.interactionManager.isState(_ModuleSupport81.InteractionState.ZoomDraggable);
}
onDragStart(dragging, { offsetX }) {
if (!this.canDrag())
return;
if (dragging === "pan") {
this.panStart = (offsetX - this.x) / this.width - this.domProxy._min;
}
this.ctx.zoomManager.fireZoomPanStartEvent("navigator");
}
onDrag(dragging, { offsetX }) {
if (!this.canDrag())
return;
const { panStart, x, width } = this;
const { minRange } = this.domProxy;
let { _min: min, _max: max } = this.domProxy;
const ratio8 = (offsetX - x) / width;
if (dragging === "min") {
min = clamp7(0, ratio8, max - minRange);
} else if (dragging === "max") {
max = clamp7(min + minRange, ratio8, 1);
} else if (dragging === "pan" && panStart != null) {
const span = max - min;
min = clamp7(0, ratio8 - panStart, 1 - span);
max = min + span;
}
this.domProxy._min = min;
this.domProxy._max = max;
this.updateZoom();
}
onZoomChange(event) {
const { x: xZoom } = event;
if (!xZoom)
return;
const { x, y, width, height } = this;
const { min, max } = xZoom;
this.domProxy.updateMinMax(min, max);
this.layoutNodes(x, y, width, height, min, max);
}
layoutNodes(x, y, width, height, min, max) {
const { rangeSelector, mask, minHandle, maxHandle } = this;
mask.layout(x, y, width, height, min, max);
rangeSelector.layout(x, y, width, height, minHandle.width / 2, maxHandle.width / 2);
RangeHandle.align(minHandle, maxHandle, x, y, width, height, min, max, mask.strokeWidth / 2);
if (min + (max - min) / 2 < 0.5) {
minHandle.zIndex = 3;
maxHandle.zIndex = 4;
} else {
minHandle.zIndex = 4;
maxHandle.zIndex = 3;
}
for (const [index, node] of [minHandle, this.maskVisibleRange, maxHandle].entries()) {
const bbox = node.getBBox();
const tbox = { x: bbox.x - x, y: bbox.y - y, height: bbox.height, width: bbox.width };
this.domProxy.updateSliderBounds(index, tbox);
}
}
updateZoom() {
if (!this.enabled)
return;
this.domProxy.updateZoom();
}
async processData(dataController) {
return this.miniChart?.processData(dataController);
}
};
__decorateClass([
ObserveChanges4((target, value, oldValue) => {
target.updateBackground(oldValue?.root, value?.root);
})
], Navigator.prototype, "miniChart", 2);
__decorateClass([
Property49,
ObserveChanges4((target, value) => {
target.ctx.zoomManager.setNavigatorEnabled(Boolean(value));
target.updateGroupVisibility();
})
], Navigator.prototype, "enabled", 2);
__decorateClass([
Property49
], Navigator.prototype, "height", 2);
__decorateClass([
Property49,
ObserveChanges4((target, value) => {
target.mask.cornerRadius = value;
})
], Navigator.prototype, "cornerRadius", 2);
__decorateClass([
Property49
], Navigator.prototype, "spacing", 2);
// packages/ag-charts-enterprise/src/features/navigator/navigatorOptionsDefs.ts
import {
AreaSeriesModule,
BarSeriesModule,
BubbleSeriesModule,
HistogramSeriesModule,
LineSeriesModule,
ScatterSeriesModule
} from "ag-charts-community";
import {
array,
arrayOfDefs as arrayOfDefs2,
boolean as boolean11,
callbackOf as callbackOf2,
color as color3,
fontOptionsDef,
number as number5,
numberFormatValidator,
positiveNumber as positiveNumber5,
ratio as ratio4,
textOrSegments,
typeUnion,
without as without2
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/box-plot/boxPlotModule.ts
import { CartesianChartModule, VERSION as VERSION15, _ModuleSupport as _ModuleSupport86 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection16, DIRECTION_SWAP_AXES } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/box-plot/boxPlotSeries.ts
import {
_ModuleSupport as _ModuleSupport84
} from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection15, deepClone as deepClone2, mergeDefaults as mergeDefaults4 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/box-plot/blotPlotUtil.ts
function prepareBoxPlotFromTo(isVertical) {
const from = isVertical ? { scalingX: 1, scalingY: 0 } : { scalingX: 0, scalingY: 1 };
const to = { scalingX: 1, scalingY: 1 };
return { from, to };
}
function resetBoxPlotSelectionsScalingCenterFn(isVertical) {
return (_node, datum) => {
if (isVertical) {
return { scalingCenterY: datum.scaledValues.medianValue };
}
return { scalingCenterX: datum.scaledValues.medianValue };
};
}
// packages/ag-charts-enterprise/src/series/box-plot/boxPlotNode.ts
import { _ModuleSupport as _ModuleSupport82 } from "ag-charts-community";
import { SceneArrayChangeDetection, SceneChangeDetection as SceneChangeDetection4 } from "ag-charts-core";
var { Path: Path7, Scalable, ExtendedPath2D: ExtendedPath2D3, BBox: BBox10, clippedRoundRect: baseClippedRoundRect } = _ModuleSupport82;
var BoxPlotNode = class extends Scalable(Path7) {
constructor() {
super(...arguments);
this.wickPath = new ExtendedPath2D3();
this.horizontal = false;
this.center = 0;
this.thickness = 0;
this.min = 0;
this.q1 = 0;
this.median = 0;
this.q3 = 0;
this.max = 0;
this.cornerRadius = 0;
this.crisp = false;
this.strokeAlignment = 0;
this.wickStroke = void 0;
this.wickStrokeWidth = void 0;
this.wickStrokeOpacity = void 0;
this.capLengthRatio = 1;
this.wickStrokeAlignment = 0;
}
computeBBox() {
const { horizontal, center, thickness, min, max } = this;
return horizontal ? new BBox10(Math.min(min, max), center - thickness / 2, Math.abs(max - min), thickness) : new BBox10(center - thickness / 2, Math.min(min, max), thickness, Math.abs(max - min));
}
computeDefaultGradientFillBBox() {
const { horizontal, center, thickness, q1, q3 } = this;
return horizontal ? new BBox10(Math.min(q1, q3), center - thickness / 2, Math.abs(q3 - q1), thickness) : new BBox10(center - thickness / 2, Math.min(q1, q3), thickness, Math.abs(q3 - q1));
}
isPointInPath(x, y) {
return this.getBBox().containsPoint(x, y);
}
distanceSquared(x, y) {
return this.getBBox().distanceSquared(x, y);
}
get midPoint() {
return this.horizontal ? { x: (this.min + this.max) / 2, y: this.center } : { x: this.center, y: (this.min + this.max) / 2 };
}
alignedCoordinates() {
const { thickness, crisp } = this;
let { center, min, q1, median, q3, max } = this;
let x0 = center - thickness / 2;
let x1 = center + thickness / 2;
if (crisp && thickness > 1) {
min = this.align(min);
q1 = this.align(q1);
median = this.align(median);
q3 = this.align(q3);
max = min + this.align(min, max - min);
const halfWidth = this.align(thickness / 2);
center = this.align(center);
x0 = center - halfWidth;
x1 = center + halfWidth;
}
return { center, x0, x1, min, max, q1, median, q3 };
}
updatePath() {
const {
path,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
wickStroke,
wickStrokeWidth,
wickStrokeOpacity,
wickLineDash,
wickLineDashOffset,
strokeAlignment,
cornerRadius,
capLengthRatio,
horizontal
} = this;
const { center, x0, x1, min, max, q1, median, q3 } = this.alignedCoordinates();
const pixelRatio = this.layerManager?.canvas.pixelRatio ?? 1;
const wickStrokeAlignment = this.wickStrokeAlignment > 0 ? pixelRatio / this.wickStrokeAlignment / 2 % 1 : 0;
this.path.clear();
this.wickPath.clear();
const needsWickPath = wickStroke != null && wickStroke !== stroke3 || wickStrokeWidth != null && wickStrokeWidth !== strokeWidth || wickStrokeOpacity != null && wickStrokeOpacity !== strokeOpacity || wickLineDash != null && wickLineDash !== lineDash || wickLineDashOffset != null && wickLineDashOffset !== lineDashOffset;
const wickPath = needsWickPath ? this.wickPath : path;
if (Math.abs(x1 - x0) <= 3) {
moveTo(wickPath, horizontal, center, min);
lineTo(wickPath, horizontal, center, max);
return;
}
const wickTop = Math.min(min, max);
const wickBottom = Math.max(min, max);
const boxTop = Math.min(q1, q3);
const boxBottom = Math.max(q1, q3);
const capX0 = center - Math.abs((x1 - x0) * capLengthRatio) / 2;
const capX1 = center + Math.abs((x1 - x0) * capLengthRatio) / 2;
moveTo(wickPath, horizontal, capX0, wickTop - wickStrokeAlignment);
lineTo(wickPath, horizontal, capX1, wickTop - wickStrokeAlignment);
moveTo(wickPath, horizontal, center - wickStrokeAlignment, wickTop - wickStrokeAlignment);
lineTo(wickPath, horizontal, center - wickStrokeAlignment, boxTop + strokeWidth / 2);
moveTo(wickPath, horizontal, center - wickStrokeAlignment, wickBottom + wickStrokeAlignment);
lineTo(wickPath, horizontal, center - wickStrokeAlignment, boxBottom - strokeWidth / 2);
moveTo(wickPath, horizontal, capX0, wickBottom + wickStrokeAlignment);
lineTo(wickPath, horizontal, capX1, wickBottom + wickStrokeAlignment);
const horizontalBoxStrokeAdjustment = strokeWidth / 2 + strokeAlignment;
const verticalBoxStrokeAdjustment = strokeWidth / 2 - strokeAlignment;
const rectHeight = boxBottom - boxTop - 2 * verticalBoxStrokeAdjustment;
if (rectHeight > 0) {
const rectX = x0 + horizontalBoxStrokeAdjustment;
const rectY = boxTop + verticalBoxStrokeAdjustment;
const rectWidth = x1 - x0 - 2 * horizontalBoxStrokeAdjustment;
const cornerRadii = {
topLeft: cornerRadius,
topRight: cornerRadius,
bottomRight: cornerRadius,
bottomLeft: cornerRadius
};
clippedRoundRect2(
path,
horizontal,
rectX,
rectY,
rectWidth,
rectHeight,
cornerRadii,
new BBox10(rectX, rectY, rectWidth, median - rectY)
);
clippedRoundRect2(
path,
horizontal,
rectX,
rectY,
rectWidth,
rectHeight,
cornerRadii,
new BBox10(rectX, median, rectWidth, rectY + rectHeight - median)
);
} else {
const boxMid = (boxTop + boxBottom) / 2;
moveTo(path, horizontal, x0, boxMid);
lineTo(path, horizontal, x1, boxMid);
}
}
drawPath(ctx) {
super.drawPath(ctx);
const { wickPath } = this;
if (wickPath.isEmpty())
return;
const {
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
wickStroke = stroke3,
wickStrokeWidth = strokeWidth,
wickStrokeOpacity = strokeOpacity,
wickLineDash = lineDash,
wickLineDashOffset = lineDashOffset
} = this;
if (wickStrokeWidth === 0)
return;
ctx.globalAlpha *= wickStrokeOpacity;
if (typeof wickStroke === "string") {
ctx.strokeStyle = wickStroke;
}
ctx.lineWidth = wickStrokeWidth;
if (wickLineDash != null) {
ctx.setLineDash([...wickLineDash]);
}
ctx.lineDashOffset = wickLineDashOffset;
ctx.stroke(wickPath.getPath2D());
}
};
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "horizontal", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "center", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "thickness", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "min", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "q1", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "median", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "q3", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "max", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "cornerRadius", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "crisp", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "strokeAlignment", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "wickStroke", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "wickStrokeWidth", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "wickStrokeOpacity", 2);
__decorateClass([
SceneArrayChangeDetection()
], BoxPlotNode.prototype, "wickLineDash", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "wickLineDashOffset", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "capLengthRatio", 2);
__decorateClass([
SceneChangeDetection4()
], BoxPlotNode.prototype, "wickStrokeAlignment", 2);
function moveTo(path, horizontal, x, y) {
if (horizontal) {
path.moveTo(y, x);
} else {
path.moveTo(x, y);
}
}
function lineTo(path, horizontal, x, y) {
if (horizontal) {
path.lineTo(y, x);
} else {
path.lineTo(x, y);
}
}
function clippedRoundRect2(path, horizontal, x, y, width, height, cornerRadii, clipBBox) {
if (horizontal) {
baseClippedRoundRect(
// eslint-disable-next-line sonarjs/arguments-order
path,
y,
x,
height,
width,
cornerRadii,
clipBBox == null ? void 0 : new BBox10(clipBBox.y, clipBBox.x, clipBBox.height, clipBBox.width)
);
} else {
baseClippedRoundRect(path, x, y, width, height, cornerRadii, clipBBox);
}
}
// packages/ag-charts-enterprise/src/series/box-plot/boxPlotSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport83 } from "ag-charts-community";
import { BaseProperties as BaseProperties19, Property as Property50, mergeDefaults as mergeDefaults3 } from "ag-charts-core";
var { AbstractBarSeriesProperties, makeSeriesTooltip } = _ModuleSupport83;
var BoxPlotSeriesCap = class extends BaseProperties19 {
constructor() {
super(...arguments);
this.lengthRatio = 0.5;
}
};
__decorateClass([
Property50
], BoxPlotSeriesCap.prototype, "lengthRatio", 2);
var BoxPlotSeriesWhisker = class extends BaseProperties19 {
};
__decorateClass([
Property50
], BoxPlotSeriesWhisker.prototype, "stroke", 2);
__decorateClass([
Property50
], BoxPlotSeriesWhisker.prototype, "strokeWidth", 2);
__decorateClass([
Property50
], BoxPlotSeriesWhisker.prototype, "strokeOpacity", 2);
__decorateClass([
Property50
], BoxPlotSeriesWhisker.prototype, "lineDash", 2);
__decorateClass([
Property50
], BoxPlotSeriesWhisker.prototype, "lineDashOffset", 2);
var BoxPlotSeriesProperties = class extends AbstractBarSeriesProperties {
constructor() {
super(...arguments);
this.fill = "#c16068";
this.fillOpacity = 1;
this.stroke = "#333";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.cornerRadius = 0;
this.cap = new BoxPlotSeriesCap();
this.whisker = new BoxPlotSeriesWhisker();
this.tooltip = makeSeriesTooltip();
}
toJson() {
const { stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = this;
const properties = super.toJson();
properties.whisker = mergeDefaults3(properties.whisker, {
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
});
return properties;
}
};
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "xKey", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "minKey", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "q1Key", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "medianKey", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "q3Key", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "maxKey", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "xName", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "yName", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "minName", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "q1Name", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "medianName", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "q3Name", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "maxName", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "fill", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "stroke", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "cornerRadius", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "styler", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "cap", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "whisker", 2);
__decorateClass([
Property50
], BoxPlotSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/box-plot/boxPlotSeries.ts
var {
fixNumericExtent: fixNumericExtent2,
keyProperty: keyProperty2,
SeriesNodePickMode,
SMALLEST_KEY_INTERVAL,
valueProperty: valueProperty3,
diff,
animationValidation,
computeBarFocusBounds,
createDatumId,
HighlightState,
motion,
getItemStyles,
calculateSegments,
toHighlightString,
processedDataIsAnimatable,
upsertNodeDatum
} = _ModuleSupport84;
var BoxPlotSeriesNodeEvent = class extends _ModuleSupport84.SeriesNodeEvent {
constructor(type, nativeEvent, datum, series) {
super(type, nativeEvent, datum, series);
this.xKey = series.properties.xKey;
this.minKey = series.properties.minKey;
this.q1Key = series.properties.q1Key;
this.medianKey = series.properties.medianKey;
this.q3Key = series.properties.q3Key;
this.maxKey = series.properties.maxKey;
}
};
var BoxPlotSeries = class extends _ModuleSupport84.AbstractBarSeries {
constructor(moduleCtx) {
super({
moduleCtx,
pickModes: [SeriesNodePickMode.NEAREST_NODE, SeriesNodePickMode.EXACT_SHAPE_MATCH],
propertyKeys: {
x: ["xKey"],
y: ["medianKey", "q1Key", "q3Key", "minKey", "maxKey"]
},
propertyNames: {
x: ["xName"],
y: ["medianName", "q1Name", "q3Name", "minName", "maxName"]
},
categoryKey: "xValue",
pathsPerSeries: []
});
this.properties = new BoxPlotSeriesProperties();
this.NodeEvent = BoxPlotSeriesNodeEvent;
}
async processData(dataController) {
if (!this.visible)
return;
const { xKey, minKey, q1Key, medianKey, q3Key, maxKey } = this.properties;
const animationEnabled = !this.ctx.animationManager.isSkipped();
const xScale = this.getCategoryAxis()?.scale;
const yScale = this.getValueAxis()?.scale;
const { isContinuousX, xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
const extraProps = [];
if (this.needsDataModelDiff() && this.processedData) {
extraProps.push(diff(this.id, this.processedData));
}
if (animationEnabled) {
extraProps.push(animationValidation());
}
const allowNullKey = this.properties.allowNullKeys ?? false;
const { processedData } = await this.requestDataModel(dataController, this.data, {
props: [
keyProperty2(xKey, xScaleType, { id: `xValue`, allowNullKey }),
valueProperty3(minKey, yScaleType, { id: `minValue` }),
valueProperty3(q1Key, yScaleType, { id: `q1Value` }),
valueProperty3(medianKey, yScaleType, { id: `medianValue` }),
valueProperty3(q3Key, yScaleType, { id: `q3Value` }),
valueProperty3(maxKey, yScaleType, { id: `maxValue` }),
...isContinuousX ? [SMALLEST_KEY_INTERVAL] : [],
...extraProps
]
});
this.smallestDataInterval = processedData.reduced?.smallestKeyInterval;
this.animationState.transition("updateData");
}
getSeriesDomain(direction) {
const { processedData, dataModel } = this;
if (!(processedData && dataModel))
return { domain: [] };
if (direction !== this.getBarDirection()) {
const { index, def } = dataModel.resolveProcessedDataDefById(this, `xValue`);
const keys = processedData.domain.keys[index];
if (def.type === "key" && def.valueType === "category") {
const sortMetadata = dataModel.getKeySortMetadata(this, "xValue", processedData);
return { domain: keys, sortMetadata };
}
return { domain: this.padBandExtent(keys) };
}
const yExtent = this.domainForClippedRange(direction, ["minValue", "maxValue"], "xValue");
return { domain: fixNumericExtent2(yExtent) };
}
getSeriesRange(_direction, visibleRange) {
return this.domainForVisibleRange(ChartAxisDirection15.Y, ["maxValue", "minValue"], "xValue", visibleRange);
}
/**
* Creates the shared context for datum creation.
* Caches expensive lookups and computations that are constant across all datums.
*/
createNodeDatumContext(xAxis, yAxis) {
const { dataModel, processedData, contextNodeData } = this;
if (!dataModel || !processedData)
return void 0;
const canIncrementallyUpdate = contextNodeData?.nodeData != null && processedData.changeDescription != null;
const animationEnabled = !this.ctx.animationManager.isSkipped();
const { groupOffset, barOffset, barWidth } = this.getBarDimensions();
return {
xAxis,
yAxis,
rawData: processedData.dataSources.get(this.id)?.data ?? [],
xValues: dataModel.resolveKeysById(this, "xValue", processedData),
minValues: dataModel.resolveColumnById(this, "minValue", processedData),
q1Values: dataModel.resolveColumnById(this, "q1Value", processedData),
medianValues: dataModel.resolveColumnById(this, "medianValue", processedData),
q3Values: dataModel.resolveColumnById(this, "q3Value", processedData),
maxValues: dataModel.resolveColumnById(this, "maxValue", processedData),
xScale: xAxis.scale,
yScale: yAxis.scale,
groupOffset,
barOffset,
barWidth,
isVertical: this.isVertical(),
xKey: this.properties.xKey,
animationEnabled,
canIncrementallyUpdate,
nodes: canIncrementallyUpdate ? contextNodeData.nodeData : [],
nodeIndex: 0
};
}
/**
* Validates box plot values and checks ordering constraints.
* Returns true if values are valid (all numbers, min <= q1 <= median <= q3 <= max).
*/
validateBoxPlotValues(minValue, q1Value, medianValue, q3Value, maxValue) {
return [minValue, q1Value, medianValue, q3Value, maxValue].every((value) => typeof value === "number") && minValue <= q1Value && q1Value <= medianValue && medianValue <= q3Value && q3Value <= maxValue;
}
/**
* Computes scaled values for a single datum.
* Populates the scratch object to avoid allocations.
*/
computeScaledValues(ctx, scratch, datumIndex) {
const x = ctx.xScale.convert(ctx.xValues[datumIndex]);
if (!Number.isFinite(x))
return false;
scratch.xValue = x + ctx.groupOffset + ctx.barOffset + ctx.barWidth / 2;
scratch.minValue = ctx.yScale.convert(ctx.minValues[datumIndex]);
scratch.q1Value = ctx.yScale.convert(ctx.q1Values[datumIndex]);
scratch.medianValue = ctx.yScale.convert(ctx.medianValues[datumIndex]);
scratch.q3Value = ctx.yScale.convert(ctx.q3Values[datumIndex]);
scratch.maxValue = ctx.yScale.convert(ctx.maxValues[datumIndex]);
return true;
}
/**
* Creates a skeleton BoxPlotNodeDatum with minimal required fields.
* The node will be populated by updateNodeDatum.
*/
createSkeletonNodeDatum(ctx, params) {
return {
series: this,
datum: params.datum,
datumIndex: params.datumIndex,
xKey: ctx.xKey,
bandwidth: ctx.barWidth,
scaledValues: {
xValue: 0,
minValue: 0,
q1Value: 0,
medianValue: 0,
q3Value: 0,
maxValue: 0
},
midPoint: { x: 0, y: 0 },
focusRect: { x: 0, y: 0, width: 0, height: 0 }
};
}
/**
* Updates an existing BoxPlotNodeDatum in-place.
* This is more efficient than recreating the entire node when only data values change.
*/
updateNodeDatum(ctx, node, params) {
const { isVertical, barWidth } = ctx;
const scaledValues = params.scaledValues;
const mutableNode = node;
mutableNode.datum = params.datum;
mutableNode.datumIndex = params.datumIndex;
mutableNode.bandwidth = barWidth;
const mutableScaledValues = mutableNode.scaledValues;
mutableScaledValues.xValue = scaledValues.xValue;
mutableScaledValues.minValue = scaledValues.minValue;
mutableScaledValues.q1Value = scaledValues.q1Value;
mutableScaledValues.medianValue = scaledValues.medianValue;
mutableScaledValues.q3Value = scaledValues.q3Value;
mutableScaledValues.maxValue = scaledValues.maxValue;
const height = Math.abs(scaledValues.q3Value - scaledValues.q1Value);
const midX = scaledValues.xValue;
const midY = Math.min(scaledValues.q3Value, scaledValues.q1Value) + height / 2;
const midPointX = isVertical ? midX : midY;
const midPointY = isVertical ? midY : midX;
if (mutableNode.midPoint) {
mutableNode.midPoint.x = midPointX;
mutableNode.midPoint.y = midPointY;
} else {
mutableNode.midPoint = { x: midPointX, y: midPointY };
}
const focusRect = mutableNode.focusRect;
if (isVertical) {
focusRect.x = midPointX - barWidth / 2;
focusRect.y = scaledValues.minValue;
focusRect.width = barWidth;
focusRect.height = scaledValues.maxValue - scaledValues.minValue;
} else {
focusRect.x = scaledValues.minValue;
focusRect.y = midPointY - barWidth / 2;
focusRect.width = scaledValues.maxValue - scaledValues.minValue;
focusRect.height = barWidth;
}
}
/**
* Creates a BoxPlotNodeDatum for a single data point.
* Creates a skeleton node and uses updateNodeDatum to populate it.
*/
createNodeDatum(ctx, params) {
const node = this.createSkeletonNodeDatum(ctx, params);
this.updateNodeDatum(ctx, node, params);
return node;
}
/**
* Initialize the result object shell before populating node data.
*/
initializeResult(ctx) {
return {
itemId: this.properties.xKey,
nodeData: ctx.nodes,
labelData: [],
scales: this.calculateScaling(),
visible: this.visible,
// Set by assembleResult()
groupScale: void 0,
styles: void 0,
segments: void 0
};
}
/**
* Populate node data by iterating over raw data.
*/
populateNodeData(ctx) {
const scaledValuesScratch = {
xValue: 0,
minValue: 0,
q1Value: 0,
medianValue: 0,
q3Value: 0,
maxValue: 0
};
const paramsScratch = {
datumIndex: 0,
datum: void 0,
scaledValues: scaledValuesScratch
};
for (let datumIndex = 0; datumIndex < ctx.rawData.length; datumIndex++) {
const datum = ctx.rawData[datumIndex];
const xValue = ctx.xValues[datumIndex];
if (xValue === void 0 && !this.properties.allowNullKeys)
continue;
const minValue = ctx.minValues[datumIndex];
const q1Value = ctx.q1Values[datumIndex];
const medianValue = ctx.medianValues[datumIndex];
const q3Value = ctx.q3Values[datumIndex];
const maxValue = ctx.maxValues[datumIndex];
if (!this.validateBoxPlotValues(minValue, q1Value, medianValue, q3Value, maxValue)) {
continue;
}
if (!this.computeScaledValues(ctx, scaledValuesScratch, datumIndex)) {
continue;
}
paramsScratch.datumIndex = datumIndex;
paramsScratch.datum = datum;
upsertNodeDatum(
ctx,
paramsScratch,
(c, p) => this.createNodeDatum(c, p),
(c, n, p) => this.updateNodeDatum(c, n, p)
);
}
}
/**
* Finalize node data by trimming excess nodes.
*/
finalizeNodeData(ctx) {
if (ctx.canIncrementallyUpdate && ctx.nodeIndex < ctx.nodes.length) {
ctx.nodes.length = ctx.nodeIndex;
}
}
/**
* Assemble the final result with computed fields.
*/
assembleResult(ctx, result) {
const segments = calculateSegments(
this.properties.segmentation,
ctx.xAxis,
ctx.yAxis,
this.chart.seriesRect,
this.ctx.scene
);
result.groupScale = this.getScaling(this.ctx.seriesStateManager.getGroupScale(this));
result.styles = getItemStyles(this.getItemStyle.bind(this));
result.segments = segments;
return result;
}
legendItemSymbol() {
const { fill, stroke: stroke3, strokeWidth, fillOpacity, strokeOpacity, lineDash, lineDashOffset } = this.getStyle(
false,
HighlightState.None
);
return {
marker: {
fill: deepClone2(fill),
fillOpacity,
stroke: stroke3,
strokeOpacity,
strokeWidth,
lineDash,
lineDashOffset
}
};
}
getLegendData(legendType) {
const {
id: seriesId,
ctx: { legendManager },
visible
} = this;
const { xKey, yName, showInLegend, legendItemName } = this.properties;
if (!xKey || legendType !== "category") {
return [];
}
return [
{
legendType: "category",
id: seriesId,
itemId: seriesId,
seriesId,
enabled: visible && legendManager.getItemEnabled({ seriesId, itemId: seriesId }),
label: {
text: legendItemName ?? yName ?? seriesId
},
symbol: this.legendItemSymbol(),
legendItemName,
hideInLegend: !showInLegend
}
];
}
getTooltipContent(datumIndex) {
const { id: seriesId, dataModel, processedData, properties } = this;
const {
xKey,
xName,
yName,
medianKey,
medianName,
q1Key,
q1Name,
q3Key,
q3Name,
minKey,
minName,
maxKey,
maxName,
legendItemName,
tooltip
} = properties;
const xAxis = this.getCategoryAxis();
const yAxis = this.getValueAxis();
if (!dataModel || !processedData || !xAxis || !yAxis)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const xValue = dataModel.resolveKeysById(this, `xValue`, processedData)[datumIndex];
const minValue = dataModel.resolveColumnById(this, `minValue`, processedData)[datumIndex];
const q1Value = dataModel.resolveColumnById(this, `q1Value`, processedData)[datumIndex];
const medianValue = dataModel.resolveColumnById(this, `medianValue`, processedData)[datumIndex];
const q3Value = dataModel.resolveColumnById(this, `q3Value`, processedData)[datumIndex];
const maxValue = dataModel.resolveColumnById(this, `maxValue`, processedData)[datumIndex];
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (xValue === void 0 && !allowNullKeys)
return;
const format = this.getItemStyle(datumIndex, false);
const data = [
{
label: minName,
fallbackLabel: minKey,
value: this.getAxisValueText(yAxis, "tooltip", minValue, datum, minKey, legendItemName),
missing: _ModuleSupport84.isTooltipValueMissing(minValue)
},
{
label: q1Name,
fallbackLabel: q1Key,
value: this.getAxisValueText(yAxis, "tooltip", q1Value, datum, q1Key, legendItemName),
missing: _ModuleSupport84.isTooltipValueMissing(q1Value)
},
{
label: medianName,
fallbackLabel: medianKey,
value: this.getAxisValueText(yAxis, "tooltip", medianValue, datum, medianKey, legendItemName),
missing: _ModuleSupport84.isTooltipValueMissing(medianValue)
},
{
label: q3Name,
fallbackLabel: q3Key,
value: this.getAxisValueText(yAxis, "tooltip", q3Value, datum, q3Key, legendItemName),
missing: _ModuleSupport84.isTooltipValueMissing(q3Value)
},
{
label: maxName,
fallbackLabel: maxKey,
value: this.getAxisValueText(yAxis, "tooltip", maxValue, datum, maxKey, legendItemName),
missing: _ModuleSupport84.isTooltipValueMissing(maxValue)
}
];
return this.formatTooltipWithContext(
tooltip,
{
heading: this.getAxisValueText(xAxis, "tooltip", xValue, datum, xKey, legendItemName),
title: legendItemName ?? yName,
symbol: this.legendItemSymbol(),
data
},
{
seriesId,
datum,
title: yName,
xKey,
xName,
yName,
medianKey,
medianName,
q1Key,
q1Name,
q3Key,
q3Name,
minKey,
minName,
maxKey,
maxName,
...format
}
);
}
animateEmptyUpdateReady({
datumSelection
}) {
const isVertical = this.isVertical();
const { from, to } = prepareBoxPlotFromTo(isVertical);
motion.resetMotion([datumSelection], resetBoxPlotSelectionsScalingCenterFn(isVertical));
motion.staticFromToMotion(this.id, "datums", this.ctx.animationManager, [datumSelection], from, to, {
phase: "initial"
});
}
isLabelEnabled() {
return false;
}
updateDatumSelection(opts) {
const data = opts.nodeData ?? [];
if (!processedDataIsAnimatable(this.processedData)) {
return opts.datumSelection.update(data);
}
return opts.datumSelection.update(data, void 0, (datum) => createDatumId(datum.datumIndex));
}
makeStylerParams(highlightStateEnum) {
const { id: seriesId } = this;
const {
cornerRadius,
cap: { lengthRatio },
fill,
fillOpacity,
lineDash,
lineDashOffset,
stroke: stroke3,
strokeOpacity,
strokeWidth,
maxKey,
maxName,
medianKey,
medianName,
minKey,
minName,
q1Key,
q1Name,
q3Key,
q3Name,
whisker: {
lineDash: whiskerLineDash,
lineDashOffset: whiskerLineDashOffset,
stroke: whiskerStroke,
strokeOpacity: whiskerStrokeOpacity,
strokeWidth: whiskerStrokeWidth
},
xKey,
xName,
yName
} = this.properties;
const highlightState = toHighlightString(highlightStateEnum ?? HighlightState.None);
return {
cap: { lengthRatio },
cornerRadius,
fill,
fillOpacity,
highlightState,
lineDash,
lineDashOffset,
maxKey,
maxName: maxName ?? maxKey,
medianKey,
medianName: medianName ?? medianKey,
minKey,
minName: minName ?? minKey,
q1Key,
q1Name: q1Name ?? q1Key,
q3Key,
q3Name: q3Name ?? q3Key,
seriesId,
stroke: stroke3,
strokeOpacity,
strokeWidth,
whisker: {
lineDash: whiskerLineDash ?? lineDash,
lineDashOffset: whiskerLineDashOffset ?? lineDashOffset,
stroke: whiskerStroke ?? stroke3,
strokeOpacity: whiskerStrokeOpacity ?? strokeOpacity,
strokeWidth: whiskerStrokeWidth ?? strokeWidth
},
xKey,
xName: xName ?? xKey,
yName
};
}
getStyle(ignoreStylerCallback, highlightState) {
const {
cap,
cornerRadius,
fill,
fillOpacity,
lineDash,
lineDashOffset,
stroke: stroke3,
strokeOpacity,
strokeWidth,
styler,
whisker
} = this.properties;
let stylerResult = {};
if (!ignoreStylerCallback && styler) {
const stylerParams = this.makeStylerParams(highlightState);
stylerResult = this.ctx.optionsGraphService.resolvePartial(
["series", `${this.declarationOrder}`],
this.cachedCallWithContext(styler, stylerParams) ?? {},
{ pick: false }
) ?? {};
}
return {
cornerRadius: stylerResult.cornerRadius ?? cornerRadius,
fill: stylerResult.fill ?? fill,
fillOpacity: stylerResult.fillOpacity ?? fillOpacity,
lineDash: stylerResult.lineDash ?? lineDash,
lineDashOffset: stylerResult.lineDashOffset ?? lineDashOffset,
opacity: 1,
stroke: stylerResult.stroke ?? stroke3,
strokeOpacity: stylerResult.strokeOpacity ?? strokeOpacity,
strokeWidth: stylerResult.strokeWidth ?? strokeWidth,
cap: { lengthRatio: stylerResult.cap?.lengthRatio ?? cap.lengthRatio },
whisker: {
lineDash: stylerResult.whisker?.lineDash ?? whisker.lineDash,
lineDashOffset: stylerResult.whisker?.lineDashOffset ?? whisker.lineDashOffset,
stroke: stylerResult.whisker?.stroke ?? whisker.stroke,
strokeOpacity: stylerResult.whisker?.strokeOpacity ?? whisker.strokeOpacity,
strokeWidth: stylerResult.whisker?.strokeWidth ?? whisker.strokeWidth
}
};
}
getItemStyle(datumIndex, isHighlight, highlightState) {
const { properties } = this;
const { itemStyler } = properties;
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex, highlightState);
let style = mergeDefaults4(highlightStyle, this.getStyle(datumIndex === void 0, highlightState));
if (itemStyler != null && datumIndex != null) {
const overrides = this.cachedDatumCallback(
createDatumId(datumIndex, isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(datumIndex, isHighlight, style);
return this.ctx.optionsGraphService.resolvePartial(
["series", `${this.declarationOrder}`],
this.callWithContext(itemStyler, params)
);
}
);
if (overrides) {
style = mergeDefaults4(overrides, style);
}
}
const { stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = style;
style.whisker = mergeDefaults4(style.whisker, {
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
});
return style;
}
makeItemStylerParams(datumIndex, isHighlight, style) {
const { id: seriesId } = this;
const { xKey, minKey, q1Key, medianKey, q3Key, maxKey } = this.properties;
const datum = this.processedData?.dataSources.get(seriesId)?.data[datumIndex];
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightStateString = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum,
xKey,
minKey,
q1Key,
medianKey,
q3Key,
maxKey,
highlightState: highlightStateString,
...style,
fill
};
}
updateDatumStyles({
datumSelection,
isHighlight
}) {
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
datumSelection.each((_, nodeDatum) => {
const highlightState = this.getHighlightState(highlightedDatum, isHighlight, nodeDatum.datumIndex);
nodeDatum.style = this.getItemStyle(nodeDatum.datumIndex, isHighlight, highlightState);
});
}
updateDatumNodes({
datumSelection,
isHighlight
}) {
const { contextNodeData, properties } = this;
if (!contextNodeData) {
return;
}
const isVertical = this.isVertical();
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
const fillBBox = this.getShapeFillBBox();
const strokeAlignment = this.getStyle(false, HighlightState.None).strokeWidth / 2;
const wickStrokeAlignment = properties.whisker.strokeWidth ?? properties.strokeWidth;
datumSelection.each((boxPlotNode, nodeDatum) => {
const style = nodeDatum.style ?? contextNodeData.styles[this.getHighlightState(highlightedDatum, isHighlight, nodeDatum.datumIndex)];
boxPlotNode.setFillProperties(style.fill, fillBBox);
const nodeOpacity = style.opacity ?? 1;
const whiskerOpacity = style.whisker?.strokeOpacity ?? style.strokeOpacity;
boxPlotNode.fill = style.fill;
boxPlotNode.fillOpacity = style.fillOpacity * nodeOpacity;
boxPlotNode.stroke = style.stroke;
boxPlotNode.strokeWidth = style.strokeWidth;
boxPlotNode.strokeOpacity = style.strokeOpacity * nodeOpacity;
boxPlotNode.lineDash = style.lineDash;
boxPlotNode.lineDashOffset = style.lineDashOffset;
boxPlotNode.wickStroke = style.whisker.stroke;
boxPlotNode.wickStrokeWidth = style.whisker.strokeWidth;
boxPlotNode.wickStrokeOpacity = whiskerOpacity * nodeOpacity;
boxPlotNode.wickLineDash = style.whisker.lineDash;
boxPlotNode.wickLineDashOffset = style.whisker.lineDashOffset;
boxPlotNode.cornerRadius = style.cornerRadius;
boxPlotNode.crisp = true;
boxPlotNode.horizontal = !isVertical;
boxPlotNode.center = nodeDatum.scaledValues.xValue;
boxPlotNode.thickness = nodeDatum.bandwidth;
boxPlotNode.min = nodeDatum.scaledValues.minValue;
boxPlotNode.q1 = nodeDatum.scaledValues.q1Value;
boxPlotNode.median = nodeDatum.scaledValues.medianValue;
boxPlotNode.q3 = nodeDatum.scaledValues.q3Value;
boxPlotNode.max = nodeDatum.scaledValues.maxValue;
boxPlotNode.capLengthRatio = style.cap.lengthRatio;
boxPlotNode.strokeAlignment = strokeAlignment;
boxPlotNode.wickStrokeAlignment = wickStrokeAlignment;
});
}
updateLabelNodes() {
}
updateLabelSelection(opts) {
const { labelData, labelSelection } = opts;
return labelSelection.update(labelData);
}
nodeFactory() {
return new BoxPlotNode();
}
computeFocusBounds({ datumIndex }) {
return computeBarFocusBounds(this, this.contextNodeData?.nodeData[datumIndex].focusRect);
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.styler != null;
}
};
BoxPlotSeries.className = "BoxPlotSeries";
BoxPlotSeries.type = "box-plot";
// packages/ag-charts-enterprise/src/series/box-plot/boxPlotSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport85 } from "ag-charts-community";
import {
boolean as boolean6,
commonSeriesOptionsDefs,
constant,
positiveNumberNonZero,
ratio as ratio2,
required,
shapeSegmentation,
string
} from "ag-charts-core";
var { boxPlotSeriesThemeableOptionsDef } = _ModuleSupport85;
var boxPlotSeriesOptionsDef = {
...commonSeriesOptionsDefs,
...boxPlotSeriesThemeableOptionsDef,
type: required(constant("box-plot")),
xKey: required(string),
minKey: required(string),
q1Key: required(string),
medianKey: required(string),
q3Key: required(string),
maxKey: required(string),
xKeyAxis: string,
yKeyAxis: string,
xName: string,
yName: string,
minName: string,
q1Name: string,
medianName: string,
q3Name: string,
maxName: string,
grouped: boolean6,
legendItemName: string,
segmentation: shapeSegmentation,
width: positiveNumberNonZero,
widthRatio: ratio2
};
// packages/ag-charts-enterprise/src/series/box-plot/boxPlotThemes.ts
import {
CARTESIAN_AXIS_TYPE,
FILL_GRADIENT_LINEAR_DEFAULTS,
FILL_IMAGE_DEFAULTS,
FILL_PATTERN_DEFAULTS,
SAFE_FILL_OPERATION,
SEGMENTATION_DEFAULTS
} from "ag-charts-core";
var BOX_PLOT_SERIES_THEME = {
series: {
direction: "vertical",
fill: {
$applySwitch: [
{ $path: "type" },
{
$if: [
{
$or: [
{ $isGradient: { $palette: "fill" } },
{ $isPattern: { $palette: "fill" } },
{ $isImage: { $palette: "fill" } }
]
},
{ $palette: "fill" },
{ $mix: [SAFE_FILL_OPERATION, { $ref: "chartBackgroundColor" }, 0.7] }
]
},
["gradient", FILL_GRADIENT_LINEAR_DEFAULTS],
["image", FILL_IMAGE_DEFAULTS],
["pattern", FILL_PATTERN_DEFAULTS]
]
},
stroke: { $palette: "stroke" },
strokeWidth: 2,
fillOpacity: 1,
strokeOpacity: 1,
lineDash: void 0,
lineDashOffset: 0,
highlight: {
unhighlightedItem: {
opacity: 0.5
},
unhighlightedSeries: {
opacity: 0.1
}
},
segmentation: SEGMENTATION_DEFAULTS
},
axes: {
[CARTESIAN_AXIS_TYPE.NUMBER]: {
crosshair: {
snap: false
}
},
[CARTESIAN_AXIS_TYPE.CATEGORY]: {
groupPaddingInner: 0.2,
crosshair: {
enabled: false,
snap: false
}
}
}
};
// packages/ag-charts-enterprise/src/series/box-plot/boxPlotModule.ts
var { predictCartesianNonPrimitiveAxis } = _ModuleSupport86;
var BoxPlotSeriesModule = {
type: "series",
name: "box-plot",
chartType: "cartesian",
enterprise: true,
groupable: true,
version: VERSION15,
dependencies: [CartesianChartModule],
options: boxPlotSeriesOptionsDef,
matchingKeys: ["xKey", "lowKey", "q1Key", "medianKey", "q3Key", "highKey", "outlierKey", "normalizedTo"],
predictAxis: predictCartesianNonPrimitiveAxis,
defaultAxes: DIRECTION_SWAP_AXES,
axisKeys: { [ChartAxisDirection16.X]: "xKeyAxis", [ChartAxisDirection16.Y]: "yKeyAxis" },
axisKeysFlipped: { [ChartAxisDirection16.X]: "yKeyAxis", [ChartAxisDirection16.Y]: "xKeyAxis" },
themeTemplate: BOX_PLOT_SERIES_THEME,
create: (ctx) => new BoxPlotSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/candlestick/candlestickModule.ts
import { CartesianChartModule as CartesianChartModule2, VERSION as VERSION16, _ModuleSupport as _ModuleSupport95 } from "ag-charts-community";
import { CARTESIAN_AXIS_TYPE as CARTESIAN_AXIS_TYPE3, CARTESIAN_POSITION, ChartAxisDirection as ChartAxisDirection18 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/candlestick/candlestickSeries.ts
import "ag-charts-community";
import { isGradientFill, isImageFill, isPatternFill } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/ohlc/ohlcSeriesBase.ts
import {
_ModuleSupport as _ModuleSupport89
} from "ag-charts-community";
import {
AGGREGATION_INDEX_X_MAX,
AGGREGATION_INDEX_X_MIN,
AGGREGATION_INDEX_Y_MAX,
AGGREGATION_INDEX_Y_MIN,
AGGREGATION_SPAN,
ChartAxisDirection as ChartAxisDirection17,
DebugMetrics,
Logger as Logger9,
mergeDefaults as mergeDefaults5
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/ohlc/ohlcAggregation.ts
import "ag-charts-community";
import {
aggregationDomain,
computeExtremesAggregation,
computeExtremesAggregationPartial,
simpleMemorize2
} from "ag-charts-core";
function aggregateOhlcData(scale, xValues, highValues, lowValues, domainInput, smallestKeyInterval, xNeedsValueOf, yNeedsValueOf) {
const [d0, d1] = aggregationDomain(scale, domainInput);
return computeExtremesAggregation([d0, d1], xValues, highValues, lowValues, {
smallestKeyInterval,
xNeedsValueOf,
yNeedsValueOf
});
}
var memoizedAggregateOhlcData = simpleMemorize2(aggregateOhlcData);
function aggregateOhlcDataFromDataModel(scale, dataModel, processedData, series, existingFilters) {
const xValues = dataModel.resolveKeysById(series, "xValue", processedData);
const highValues = dataModel.resolveColumnById(series, "highValue", processedData);
const lowValues = dataModel.resolveColumnById(series, "lowValue", processedData);
const domainInput = dataModel.getDomain(series, "xValue", "key", processedData);
const xNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "xValue", processedData);
const yNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "highValue", processedData) ?? dataModel.resolveColumnNeedsValueOf(series, "lowValue", processedData);
if (existingFilters) {
const [d0, d1] = aggregationDomain(scale, domainInput);
return computeExtremesAggregation([d0, d1], xValues, highValues, lowValues, {
smallestKeyInterval: processedData.reduced?.smallestKeyInterval,
xNeedsValueOf,
yNeedsValueOf,
existingFilters
});
}
return memoizedAggregateOhlcData(
scale,
xValues,
highValues,
lowValues,
domainInput,
processedData.reduced?.smallestKeyInterval,
xNeedsValueOf,
yNeedsValueOf
);
}
function aggregateOhlcDataFromDataModelPartial(scale, dataModel, processedData, series, targetRange, existingFilters) {
const xValues = dataModel.resolveKeysById(series, "xValue", processedData);
const highValues = dataModel.resolveColumnById(series, "highValue", processedData);
const lowValues = dataModel.resolveColumnById(series, "lowValue", processedData);
const domainInput = dataModel.getDomain(series, "xValue", "key", processedData);
const xNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "xValue", processedData);
const yNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "highValue", processedData) ?? dataModel.resolveColumnNeedsValueOf(series, "lowValue", processedData);
const [d0, d1] = aggregationDomain(scale, domainInput);
return computeExtremesAggregationPartial([d0, d1], xValues, highValues, lowValues, {
smallestKeyInterval: processedData.reduced?.smallestKeyInterval,
targetRange,
xNeedsValueOf,
yNeedsValueOf,
existingFilters
});
}
// packages/ag-charts-enterprise/src/series/ohlc/ohlcNode.ts
import { _ModuleSupport as _ModuleSupport88 } from "ag-charts-community";
import { DeclaredSceneChangeDetection } from "ag-charts-core";
var { Path: Path8, BBox: BBox11 } = _ModuleSupport88;
var OhlcBaseNode = class extends Path8 {
constructor() {
super(...arguments);
this.centerX = 0;
this.y = 0;
this.width = 0;
this.height = 0;
this.yOpen = 0;
this.yClose = 0;
this.crisp = false;
}
/**
* High-performance static property setter that bypasses the decorator system entirely.
* Writes directly to backing fields (__propertyName) to avoid:
* - Decorator setter chains and equality checks
* - Multiple onChangeDetection calls per property
* - Object.keys() iteration in assignIfNotStrictlyEqual
* - Object allocation overhead
*
* A single markDirty() call at the end ensures the scene graph is properly invalidated.
* WARNING: Only use for hot paths where performance is critical and properties don't need
* individual change detection (e.g., when updating many nodes in a loop).
*/
setStaticProperties(centerX, width, y, height, yOpen, yClose, crisp) {
this.__centerX = centerX;
this.__width = width;
this.__y = y;
this.__height = height;
this.__yOpen = yOpen;
this.__yClose = yClose;
this.__crisp = crisp;
this.dirtyPath = true;
this.markDirty();
}
computeBBox() {
const { __centerX: centerX, __y: y, __width: width, __height: height } = this;
return new BBox11(centerX - width / 2, y, width, height);
}
isPointInPath(x, y) {
return this.getBBox().containsPoint(x, y);
}
distanceSquared(x, y) {
return this.getBBox().distanceSquared(x, y);
}
get midPoint() {
return { x: this.__centerX, y: this.__y + this.__height / 2 };
}
alignedCoordinates() {
const { __y: y, __width: width, __height: height, __crisp: crisp } = this;
let { __centerX: centerX, __yOpen: yOpen, __yClose: yClose } = this;
let x0 = centerX - width / 2;
let x1 = centerX + width / 2;
let y0 = y;
let y1 = y + height;
if (crisp && width > 1) {
centerX = this.align(centerX);
if (yOpen <= yClose) {
const h = this.align(yOpen, yClose - yOpen);
yOpen = this.align(yOpen);
yClose = yOpen + h;
} else {
const h = this.align(yClose, yOpen - yClose);
yClose = this.align(yClose);
yOpen = yClose + h;
}
const halfWidth = this.align(width / 2);
x0 = centerX - halfWidth;
x1 = centerX + halfWidth;
y0 = this.align(y);
y1 = y0 + this.align(y0, height);
}
return { centerX, x0, x1, y0, y1, yOpen, yClose };
}
executeStroke(ctx, path) {
const { __width: width, strokeWidth } = this;
if (width < strokeWidth) {
ctx.lineWidth = width;
}
super.executeStroke(ctx, path);
}
};
__decorateClass([
DeclaredSceneChangeDetection()
], OhlcBaseNode.prototype, "centerX", 2);
__decorateClass([
DeclaredSceneChangeDetection()
], OhlcBaseNode.prototype, "y", 2);
__decorateClass([
DeclaredSceneChangeDetection()
], OhlcBaseNode.prototype, "width", 2);
__decorateClass([
DeclaredSceneChangeDetection()
], OhlcBaseNode.prototype, "height", 2);
__decorateClass([
DeclaredSceneChangeDetection()
], OhlcBaseNode.prototype, "yOpen", 2);
__decorateClass([
DeclaredSceneChangeDetection()
], OhlcBaseNode.prototype, "yClose", 2);
__decorateClass([
DeclaredSceneChangeDetection()
], OhlcBaseNode.prototype, "crisp", 2);
var OhlcNode = class extends OhlcBaseNode {
constructor() {
super(...arguments);
this.strokeAlignment = 0;
}
updatePath() {
const { path } = this;
const { centerX, x0, x1, y0, y1, yOpen, yClose } = this.alignedCoordinates();
const pixelRatio = this.layerManager?.canvas.pixelRatio ?? 1;
const strokeAlignment = this.__strokeAlignment > 0 ? pixelRatio / this.__strokeAlignment / 2 % 1 : 0;
path.clear();
path.moveTo(centerX - strokeAlignment, y0);
path.lineTo(centerX - strokeAlignment, y1);
if (Math.abs(x1 - x0) > 1) {
path.moveTo(x0, yOpen - strokeAlignment);
path.lineTo(centerX - strokeAlignment, yOpen - strokeAlignment);
path.moveTo(centerX - strokeAlignment, yClose - strokeAlignment);
path.lineTo(x1, yClose - strokeAlignment);
}
}
};
__decorateClass([
DeclaredSceneChangeDetection()
], OhlcNode.prototype, "strokeAlignment", 2);
// packages/ag-charts-enterprise/src/series/ohlc/ohlcSeriesBase.ts
var OPEN = AGGREGATION_INDEX_X_MIN;
var HIGH = AGGREGATION_INDEX_Y_MAX;
var LOW = AGGREGATION_INDEX_Y_MIN;
var CLOSE = AGGREGATION_INDEX_X_MAX;
var SPAN = AGGREGATION_SPAN;
var {
AggregationManager,
fixNumericExtent: fixNumericExtent3,
keyProperty: keyProperty3,
createDatumId: createDatumId2,
SeriesNodePickMode: SeriesNodePickMode2,
SMALLEST_KEY_INTERVAL: SMALLEST_KEY_INTERVAL2,
valueProperty: valueProperty4,
diff: diff2,
animationValidation: animationValidation2,
computeBarFocusBounds: computeBarFocusBounds2,
visibleRangeIndices,
BandScale,
processedDataIsAnimatable: processedDataIsAnimatable2,
getItemStylesPerItemId
} = _ModuleSupport89;
var OhlcSeriesNodeEvent = class extends _ModuleSupport89.SeriesNodeEvent {
constructor(type, nativeEvent, datum, series) {
super(type, nativeEvent, datum, series);
this.xKey = series.properties.xKey;
this.openKey = series.properties.openKey;
this.closeKey = series.properties.closeKey;
this.highKey = series.properties.highKey;
this.lowKey = series.properties.lowKey;
}
};
function resetOhlcSelectionsDirect(selections) {
for (const selection of selections) {
const nodes = selection.nodes();
selection.batchedUpdate(function resetOhlcNodes() {
for (const node of nodes) {
const datum = node.datum;
if (datum == null)
continue;
node.setStaticProperties(
datum.centerX,
datum.width,
datum.y,
datum.height,
datum.yOpen,
datum.yClose,
datum.crisp
);
}
selection.cleanup();
});
}
}
var OhlcSeriesBase = class extends _ModuleSupport89.AbstractBarSeries {
constructor(moduleCtx) {
super({
moduleCtx,
pickModes: [SeriesNodePickMode2.AXIS_ALIGNED, SeriesNodePickMode2.EXACT_SHAPE_MATCH],
propertyKeys: {
x: ["xKey"],
y: ["lowKey", "highKey", "openKey", "closeKey"]
},
propertyNames: {
x: ["xName"],
y: ["lowName", "highName", "openName", "closeName"]
},
categoryKey: "xValue",
pathsPerSeries: []
});
this.NodeEvent = OhlcSeriesNodeEvent;
this.aggregationManager = new AggregationManager();
}
async processData(dataController) {
if (!this.visible)
return;
const { xKey, openKey, closeKey, highKey, lowKey } = this.properties;
const animationEnabled = !this.ctx.animationManager.isSkipped();
const xScale = this.getCategoryAxis()?.scale;
const yScale = this.getValueAxis()?.scale;
const { isContinuousX, xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
const extraProps = [];
if (this.needsDataModelDiff() && this.processedData) {
extraProps.push(diff2(this.id, this.processedData));
}
if (animationEnabled) {
extraProps.push(animationValidation2());
}
if (openKey) {
extraProps.push(
valueProperty4(openKey, yScaleType, {
id: `openValue`,
invalidValue: void 0,
missingValue: void 0
})
);
}
const allowNullKey = this.properties.allowNullKeys ?? false;
const { dataModel, processedData } = await this.requestDataModel(dataController, this.data, {
props: [
keyProperty3(xKey, xScaleType, { id: `xValue`, allowNullKey }),
valueProperty4(closeKey, yScaleType, { id: `closeValue` }),
valueProperty4(highKey, yScaleType, { id: `highValue` }),
valueProperty4(lowKey, yScaleType, { id: `lowValue` }),
...isContinuousX ? [SMALLEST_KEY_INTERVAL2] : [],
...extraProps
]
});
this.smallestDataInterval = processedData.reduced?.smallestKeyInterval;
this.aggregateData(dataModel, processedData);
this.animationState.transition("updateData");
}
aggregateData(dataModel, processedData) {
this.aggregationManager.markStale(processedData.input.count);
if (processedData.type !== "ungrouped")
return;
if (processedDataIsAnimatable2(processedData))
return;
const xAxis = this.axes[ChartAxisDirection17.X];
if (xAxis == null)
return;
const targetRange = this.estimateTargetRange();
this.aggregationManager.aggregate({
computePartial: (existingFilters) => aggregateOhlcDataFromDataModelPartial(
xAxis.scale.type,
dataModel,
processedData,
this,
targetRange,
existingFilters
),
computeFull: (existingFilters) => aggregateOhlcDataFromDataModel(xAxis.scale.type, dataModel, processedData, this, existingFilters),
targetRange
});
const filters = this.aggregationManager.filters;
if (filters && filters.length > 0) {
DebugMetrics.record(
`${this.type}:aggregation`,
filters.map((f) => f.maxRange)
);
}
}
estimateTargetRange() {
const xAxis = this.axes[ChartAxisDirection17.X];
if (!xAxis)
return -1;
const [r0, r1] = xAxis.scale.range;
return Math.abs(r1 - r0);
}
getSeriesDomain(direction) {
const { processedData, dataModel } = this;
if (!(processedData && dataModel))
return { domain: [] };
if (direction !== this.getBarDirection()) {
const { def } = dataModel.resolveProcessedDataDefById(this, `xValue`);
const keys = dataModel.getDomain(this, `xValue`, "key", processedData);
if (def.type === "key" && def.valueType === "category") {
return keys;
}
return { domain: this.padBandExtent(keys.domain) };
}
const yExtent = this.domainForClippedRange(direction, ["highValue", "lowValue"], "xValue");
return { domain: fixNumericExtent3(yExtent) };
}
getSeriesRange(_direction, visibleRange) {
return this.domainForVisibleRange(ChartAxisDirection17.Y, ["highValue", "lowValue"], "xValue", visibleRange);
}
getZoomRangeFittingItems(xVisibleRange, yVisibleRange, minVisibleItems) {
return this.zoomFittingVisibleItems(
"xValue",
["highValue", "lowValue"],
xVisibleRange,
yVisibleRange,
minVisibleItems
);
}
getVisibleItems(xVisibleRange, yVisibleRange, minVisibleItems) {
return this.countVisibleItems(
"xValue",
["highValue", "lowValue"],
xVisibleRange,
yVisibleRange,
minVisibleItems
);
}
/**
* Creates shared context for node datum creation/update operations.
* This context is instantiated once and reused across all datum operations
* to minimize memory allocations. Only caches values that are expensive to
* compute - cheap property lookups use `this` directly.
*/
buildDatumContext(xAxis, yAxis) {
const { dataModel, processedData } = this;
if (!dataModel || !processedData)
return void 0;
const rawData = processedData.dataSources.get(this.id)?.data ?? [];
if (rawData.length === 0)
return void 0;
const xScale = xAxis.scale;
const yScale = yAxis.scale;
const applyWidthOffset = BandScale.is(xScale);
const [r0, r1] = xScale.range;
const range2 = Math.abs(r1 - r0);
this.aggregationManager.ensureLevelForRange(range2);
const dataAggregationFilter = this.aggregationManager.getFilterForRange(range2);
const crisp = dataAggregationFilter == null;
const canIncrementallyUpdate = this.contextNodeData?.nodeData != null && (processedData.changeDescription != null || !processedDataIsAnimatable2(processedData) || dataAggregationFilter != null);
const { groupOffset, barWidth } = this.getBarDimensions();
return {
rawData,
xValues: dataModel.resolveKeysById(this, "xValue", processedData),
openValues: dataModel.resolveColumnById(this, "openValue", processedData),
closeValues: dataModel.resolveColumnById(this, "closeValue", processedData),
highValues: dataModel.resolveColumnById(this, "highValue", processedData),
lowValues: dataModel.resolveColumnById(this, "lowValue", processedData),
xScale,
yScale,
xAxis,
yAxis,
groupOffset,
barWidth,
applyWidthOffset,
// TODO: replace with barOffset?
crisp,
xKey: this.properties.xKey,
openKey: this.properties.openKey,
closeKey: this.properties.closeKey,
highKey: this.properties.highKey,
lowKey: this.properties.lowKey,
dataAggregationFilter,
range: range2,
nodeDatumStateScratch: {
datum: void 0,
xValue: void 0,
openValue: 0,
closeValue: 0,
highValue: 0,
lowValue: 0,
isRising: true,
itemType: "up"
},
canIncrementallyUpdate,
nodeIndex: 0,
nodeData: canIncrementallyUpdate ? this.contextNodeData.nodeData : []
};
}
/**
* Validates and prepares state for a single OHLC datum.
* Mutates ctx.nodeDatumStateScratch with computed values.
* Returns the scratch object if valid, undefined if invalid.
*/
prepareOhlcNodeDatumState(ctx, datumIndex) {
const xValue = ctx.xValues[datumIndex];
if (xValue === void 0 && !this.properties.allowNullKeys) {
return void 0;
}
const openValue = ctx.openValues[datumIndex];
const closeValue = ctx.closeValues[datumIndex];
const highValue = ctx.highValues[datumIndex];
const lowValue = ctx.lowValues[datumIndex];
const validLowValue = lowValue != null && lowValue <= openValue && lowValue <= closeValue;
const validHighValue = highValue != null && highValue >= openValue && highValue >= closeValue;
if (!validLowValue) {
Logger9.warnOnce(
`invalid low value for key [${ctx.lowKey}] in data element, low value cannot be higher than datum open or close values`
);
return void 0;
}
if (!validHighValue) {
Logger9.warnOnce(
`invalid high value for key [${ctx.highKey}] in data element, high value cannot be lower than datum open or close values.`
);
return void 0;
}
const datum = ctx.rawData[datumIndex];
const isRising = closeValue > openValue;
const itemType = isRising ? "up" : "down";
const scratch = ctx.nodeDatumStateScratch;
scratch.datum = datum;
scratch.xValue = xValue;
scratch.openValue = openValue;
scratch.closeValue = closeValue;
scratch.highValue = highValue;
scratch.lowValue = lowValue;
scratch.isRising = isRising;
scratch.itemType = itemType;
return scratch;
}
/**
* Creates a skeleton OhlcNodeDatum from prepared state.
* Takes pre-computed positioning and state from scratch object.
*/
createSkeletonNodeDatum(ctx, scratch, datumIndex, centerX, width, crisp) {
const xOffset = ctx.applyWidthOffset ? width / 2 : 0;
const adjustedCenterX = centerX + xOffset;
const yOpen = ctx.yScale.convert(scratch.openValue);
const yClose = ctx.yScale.convert(scratch.closeValue);
const yHigh = ctx.yScale.convert(scratch.highValue);
const yLow = ctx.yScale.convert(scratch.lowValue);
const y = Math.min(yHigh, yLow);
const height = Math.max(yHigh, yLow) - y;
return {
series: this,
itemType: scratch.itemType,
datum: scratch.datum,
datumIndex,
xKey: ctx.xKey,
xValue: scratch.xValue,
openValue: scratch.openValue,
closeValue: scratch.closeValue,
highValue: scratch.highValue,
lowValue: scratch.lowValue,
midPoint: {
x: adjustedCenterX,
y: y + height / 2
},
aggregatedValue: scratch.closeValue,
isRising: scratch.isRising,
centerX: adjustedCenterX,
width,
y,
height,
yOpen,
yClose,
crisp
};
}
/**
* Updates an existing OhlcNodeDatum in-place for value-only changes.
* This is more efficient than recreating the entire node when only data values change
* but the structure (insertions/removals) remains the same.
*/
updateNodeDatum(ctx, node, prepared, datumIndex, centerX, width, crisp) {
const mutableNode = node;
const xOffset = ctx.applyWidthOffset ? width / 2 : 0;
const adjustedCenterX = centerX + xOffset;
const yOpen = ctx.yScale.convert(prepared.openValue);
const yClose = ctx.yScale.convert(prepared.closeValue);
const yHigh = ctx.yScale.convert(prepared.highValue);
const yLow = ctx.yScale.convert(prepared.lowValue);
const y = Math.min(yHigh, yLow);
const height = Math.max(yHigh, yLow) - y;
mutableNode.datum = prepared.datum;
mutableNode.datumIndex = datumIndex;
mutableNode.itemType = prepared.itemType;
mutableNode.xValue = prepared.xValue;
mutableNode.openValue = prepared.openValue;
mutableNode.closeValue = prepared.closeValue;
mutableNode.highValue = prepared.highValue;
mutableNode.lowValue = prepared.lowValue;
mutableNode.aggregatedValue = prepared.closeValue;
mutableNode.isRising = prepared.isRising;
mutableNode.centerX = adjustedCenterX;
mutableNode.width = width;
mutableNode.y = y;
mutableNode.height = height;
mutableNode.yOpen = yOpen;
mutableNode.yClose = yClose;
mutableNode.crisp = crisp;
const mutableMidPoint = mutableNode.midPoint;
mutableMidPoint.x = adjustedCenterX;
mutableMidPoint.y = y + height / 2;
}
/**
* Handles node creation/update - reuses existing nodes when possible for incremental updates.
* This method decides whether to update existing nodes in-place or create new ones.
*/
upsertNodeDatum(ctx, datumIndex, centerX, width, crisp) {
const prepared = this.prepareOhlcNodeDatumState(ctx, datumIndex);
if (!prepared)
return;
const canReuse = ctx.canIncrementallyUpdate && ctx.nodeIndex < ctx.nodeData.length;
if (canReuse) {
this.updateNodeDatum(ctx, ctx.nodeData[ctx.nodeIndex], prepared, datumIndex, centerX, width, crisp);
} else {
const newNode = this.createSkeletonNodeDatum(ctx, prepared, datumIndex, centerX, width, crisp);
ctx.nodeData.push(newNode);
}
ctx.nodeIndex++;
}
createNodeData() {
const { visible } = this;
const xAxis = this.getCategoryAxis();
const yAxis = this.getValueAxis();
if (!xAxis || !yAxis)
return;
const ctx = this.buildDatumContext(xAxis, yAxis);
const resultContext = {
itemId: this.properties.xKey,
nodeData: ctx?.nodeData ?? [],
labelData: [],
scales: this.calculateScaling(),
groupScale: this.getScaling(this.ctx.seriesStateManager.getGroupScale(this)),
visible: this.visible,
styles: getItemStylesPerItemId(this.getItemStyle.bind(this), "up", "down")
};
if (!visible || !ctx)
return resultContext;
const xPosition = (index) => {
const x = ctx.xScale.convert(ctx.xValues[index]);
if (!Number.isFinite(x))
return Number.NaN;
return x + ctx.groupOffset;
};
if (ctx.dataAggregationFilter == null) {
const invalidData = this.processedData.invalidData?.get(this.id);
let [start, end] = visibleRangeIndices(1, ctx.rawData.length, ctx.xAxis.range, (index) => {
const xOffset = ctx.applyWidthOffset ? 0 : -ctx.barWidth / 2;
const x = xPosition(index) + xOffset;
return [x, x + ctx.barWidth];
});
if (this.processedData.input.count < 1e3) {
start = 0;
end = this.processedData.input.count;
}
for (let datumIndex = start; datumIndex < end; datumIndex += 1) {
if (invalidData?.[datumIndex] === true)
continue;
const centerX = xPosition(datumIndex);
this.upsertNodeDatum(ctx, datumIndex, centerX, ctx.barWidth, ctx.crisp);
}
if (ctx.canIncrementallyUpdate && ctx.nodeIndex < ctx.nodeData.length) {
ctx.nodeData.length = ctx.nodeIndex;
}
} else {
const { maxRange, indexData, midpointIndices } = ctx.dataAggregationFilter;
const [start, end] = visibleRangeIndices(1, maxRange, ctx.xAxis.range, (index) => {
const aggIndex = index * SPAN;
const closeIndex = indexData[aggIndex + CLOSE];
const midDatumIndex = midpointIndices[index];
if (midDatumIndex === -1)
return;
const xOffset = ctx.applyWidthOffset ? 0 : -ctx.barWidth / 2;
return [xPosition(midDatumIndex) + xOffset, xPosition(closeIndex) + xOffset + ctx.barWidth];
});
for (let i = start; i < end; i += 1) {
const aggIndex = i * SPAN;
const openIndex = indexData[aggIndex + OPEN];
const closeIndex = indexData[aggIndex + CLOSE];
const highIndex = indexData[aggIndex + HIGH];
const lowIndex = indexData[aggIndex + LOW];
const midDatumIndex = midpointIndices[i];
if (midDatumIndex === -1)
continue;
const prepared = this.prepareOhlcNodeDatumState(ctx, midDatumIndex);
if (!prepared)
continue;
prepared.openValue = ctx.openValues[openIndex];
prepared.closeValue = ctx.closeValues[closeIndex];
prepared.highValue = ctx.highValues[highIndex];
prepared.lowValue = ctx.lowValues[lowIndex];
prepared.isRising = prepared.closeValue > prepared.openValue;
prepared.itemType = prepared.isRising ? "up" : "down";
const centerX = xPosition(midDatumIndex);
const width = Math.abs(xPosition(closeIndex) - xPosition(openIndex)) + ctx.barWidth;
const canReuse = ctx.canIncrementallyUpdate && ctx.nodeIndex < ctx.nodeData.length;
if (canReuse) {
this.updateNodeDatum(
ctx,
ctx.nodeData[ctx.nodeIndex],
prepared,
midDatumIndex,
centerX,
width,
false
);
} else {
const nodeDatum = this.createSkeletonNodeDatum(ctx, prepared, midDatumIndex, centerX, width, false);
ctx.nodeData.push(nodeDatum);
}
ctx.nodeIndex++;
}
if (ctx.canIncrementallyUpdate && ctx.nodeIndex < ctx.nodeData.length) {
ctx.nodeData.length = ctx.nodeIndex;
}
}
return resultContext;
}
isVertical() {
return true;
}
isLabelEnabled() {
return false;
}
resetDatumAnimation(data) {
resetOhlcSelectionsDirect([data.datumSelection]);
}
updateDatumSelection(opts) {
const data = opts.nodeData ?? [];
if (!processedDataIsAnimatable2(this.processedData)) {
return opts.datumSelection.update(data);
}
return opts.datumSelection.update(data, void 0, (datum) => createDatumId2(datum.xValue));
}
updateLabelNodes(_opts) {
}
updateLabelSelection(opts) {
const { labelData, labelSelection } = opts;
return labelSelection.update(labelData);
}
getItemStyle(datumIndex, isHighlight, highlightState, itemType = "up") {
const { properties, dataModel, processedData } = this;
const { itemStyler } = properties;
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex, highlightState);
const baseStyle = mergeDefaults5(highlightStyle, properties.getStyle(itemType));
let style = baseStyle;
if (itemStyler && dataModel != null && processedData != null && datumIndex != null) {
const xValue = dataModel.resolveKeysById(this, `xValue`, processedData)[datumIndex];
const overrides = this.cachedDatumCallback(
createDatumId2(createDatumId2(xValue), isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(itemType, datumIndex, isHighlight, style);
return this.ctx.optionsGraphService.resolvePartial(
["series", `${this.declarationOrder}`, "item", itemType],
this.callWithContext(itemStyler, params)
);
}
);
if (overrides) {
style = mergeDefaults5(overrides, style);
}
}
return style;
}
makeItemStylerParams(itemType, datumIndex, isHighlight, style) {
const { id: seriesId, properties, processedData } = this;
const { xKey, openKey, closeKey, highKey, lowKey } = properties;
const datum = processedData.dataSources.get(seriesId)?.data[datumIndex];
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightStateString = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
const params = {
seriesId,
datum,
itemType,
xKey,
openKey,
closeKey,
highKey,
lowKey,
highlightState: highlightStateString,
...style
};
if ("fill" in params && "fill" in style) {
params.fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
}
return params;
}
getTooltipContent(datumIndex) {
const { id: seriesId, dataModel, processedData, properties } = this;
const {
xKey,
xName,
yName,
openKey,
openName,
highKey,
highName,
lowKey,
lowName,
closeKey,
closeName,
legendItemName,
tooltip
} = properties;
const xAxis = this.getCategoryAxis();
const yAxis = this.getValueAxis();
if (!dataModel || !processedData || !xAxis || !yAxis)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const xValue = dataModel.resolveKeysById(this, `xValue`, processedData)[datumIndex];
const openValue = dataModel.resolveColumnById(this, `openValue`, processedData)[datumIndex];
const highValue = dataModel.resolveColumnById(this, `highValue`, processedData)[datumIndex];
const lowValue = dataModel.resolveColumnById(this, `lowValue`, processedData)[datumIndex];
const closeValue = dataModel.resolveColumnById(this, `closeValue`, processedData)[datumIndex];
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (xValue === void 0 && !allowNullKeys)
return;
const itemType = closeValue >= openValue ? "up" : "down";
const item = this.properties.item[itemType];
const format = this.getItemStyle(datumIndex, false);
const marker = {
fill: item.fill ?? item.stroke,
fillOpacity: item.fillOpacity ?? item.strokeOpacity ?? 1,
stroke: item.stroke,
strokeWidth: item.strokeWidth ?? 1,
strokeOpacity: item.strokeOpacity ?? 1,
lineDash: item.lineDash ?? [0],
lineDashOffset: item.lineDashOffset ?? 0
};
return this.formatTooltipWithContext(
tooltip,
{
heading: this.getAxisValueText(xAxis, "tooltip", xValue, datum, xKey, legendItemName),
title: legendItemName,
symbol: {
marker
},
data: [
{
label: openName,
fallbackLabel: openKey,
value: this.getAxisValueText(yAxis, "tooltip", openValue, datum, openKey, legendItemName),
missing: _ModuleSupport89.isTooltipValueMissing(openValue)
},
{
label: highName,
fallbackLabel: highKey,
value: this.getAxisValueText(yAxis, "tooltip", highValue, datum, highKey, legendItemName),
missing: _ModuleSupport89.isTooltipValueMissing(highValue)
},
{
label: lowName,
fallbackLabel: lowKey,
value: this.getAxisValueText(yAxis, "tooltip", lowValue, datum, lowKey, legendItemName),
missing: _ModuleSupport89.isTooltipValueMissing(lowValue)
},
{
label: closeName,
fallbackLabel: closeKey,
value: this.getAxisValueText(yAxis, "tooltip", closeValue, datum, closeKey, legendItemName),
missing: _ModuleSupport89.isTooltipValueMissing(closeValue)
}
]
},
{
seriesId,
datum,
title: yName,
itemType,
xKey,
xName,
yName,
openKey,
openName,
highKey,
highName,
lowKey,
lowName,
closeKey,
closeName,
...format
}
);
}
computeFocusBounds(opts) {
const nodeDatum = this.getNodeData()?.at(opts.datumIndex);
if (nodeDatum == null)
return;
const { centerX, y, width, height } = nodeDatum;
const datum = {
x: centerX - width / 2,
y,
width,
height
};
return computeBarFocusBounds2(this, datum);
}
};
// packages/ag-charts-enterprise/src/series/candlestick/candlestickNode.ts
import { _ModuleSupport as _ModuleSupport90 } from "ag-charts-community";
import { DeclaredSceneChangeDetection as DeclaredSceneChangeDetection2, SceneArrayChangeDetection as SceneArrayChangeDetection2 } from "ag-charts-core";
var { ExtendedPath2D: ExtendedPath2D4, BBox: BBox12 } = _ModuleSupport90;
var CandlestickNode = class extends OhlcBaseNode {
constructor() {
super(...arguments);
this.wickPath = new ExtendedPath2D4();
this.wickStroke = void 0;
this.wickStrokeWidth = void 0;
this.wickStrokeOpacity = void 0;
this.wickStrokeAlignment = 0;
}
/**
* High-performance wick property setter that bypasses the decorator system entirely.
* Writes directly to backing fields (__propertyName) to avoid:
* - Decorator setter chains and equality checks
* - Multiple onChangeDetection calls per property
* - Object.keys() iteration in assignIfNotStrictlyEqual
* - Object allocation overhead
*
* A single markDirty() call at the end ensures the scene graph is properly invalidated.
* WARNING: Only use for hot paths where performance is critical and properties don't need
* individual change detection (e.g., when updating many nodes in a loop).
*/
setWickProperties(wickStroke, wickStrokeWidth, wickStrokeOpacity, wickLineDash, wickLineDashOffset) {
this.__wickStroke = wickStroke;
this.__wickStrokeWidth = wickStrokeWidth;
this.__wickStrokeOpacity = wickStrokeOpacity;
this.wickLineDash = wickLineDash;
this.__wickLineDashOffset = wickLineDashOffset;
this.dirtyPath = true;
this.markDirty();
}
computeDefaultGradientFillBBox() {
const { __width: width, __centerX: centerX, __yOpen: yOpen, __yClose: yClose } = this;
const boxTop = Math.min(yOpen, yClose);
const boxBottom = Math.max(yOpen, yClose);
const rectHeight = boxBottom - boxTop;
const x0 = centerX - width / 2;
const x1 = centerX + width / 2;
return new BBox12(x0, boxTop, x1 - x0, rectHeight);
}
updatePath() {
const {
path,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
__wickStroke: wickStroke,
__wickStrokeWidth: wickStrokeWidth,
__wickStrokeOpacity: wickStrokeOpacity,
wickLineDash,
__wickLineDashOffset: wickLineDashOffset
} = this;
const { centerX, x0, x1, y0, y1, yOpen, yClose } = this.alignedCoordinates();
const pixelRatio = this.layerManager?.canvas.pixelRatio ?? 1;
const wickStrokeAlignment = this.__wickStrokeAlignment > 0 ? pixelRatio / this.__wickStrokeAlignment / 2 % 1 : 0;
this.path.clear();
this.wickPath.clear();
const needsWickPath = wickStroke != null && wickStroke !== stroke3 || wickStrokeWidth != null && wickStrokeWidth !== strokeWidth || wickStrokeOpacity != null && wickStrokeOpacity !== strokeOpacity || wickLineDash != null && wickLineDash !== lineDash || wickLineDashOffset != null && wickLineDashOffset !== lineDashOffset;
const wickPath = needsWickPath ? this.wickPath : path;
if (Math.abs(x1 - x0) <= 3) {
wickPath.moveTo(centerX - wickStrokeAlignment, y0);
wickPath.lineTo(centerX - wickStrokeAlignment, y1);
return;
}
const boxTop = Math.min(yOpen, yClose);
const boxBottom = Math.max(yOpen, yClose);
const boxStrokeAdjustment = strokeWidth / 2;
wickPath.moveTo(centerX - wickStrokeAlignment, y0);
wickPath.lineTo(centerX - wickStrokeAlignment, boxTop + boxStrokeAdjustment);
wickPath.moveTo(centerX - wickStrokeAlignment, y1);
wickPath.lineTo(centerX - wickStrokeAlignment, boxBottom - boxStrokeAdjustment);
const rectHeight = boxBottom - boxTop - 2 * boxStrokeAdjustment;
if (rectHeight > 0) {
path.rect(
x0 + boxStrokeAdjustment,
boxTop + boxStrokeAdjustment,
x1 - x0 - 2 * boxStrokeAdjustment,
rectHeight
);
} else {
const boxMid = (boxTop + boxBottom) / 2;
path.moveTo(x0, boxMid);
path.lineTo(x1, boxMid);
}
}
drawPath(ctx) {
super.drawPath(ctx);
const { wickPath } = this;
if (wickPath.isEmpty())
return;
const {
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
__wickStroke: wickStroke = stroke3,
__wickStrokeWidth: wickStrokeWidth = strokeWidth,
__wickStrokeOpacity: wickStrokeOpacity = strokeOpacity,
wickLineDash = lineDash,
__wickLineDashOffset: wickLineDashOffset = lineDashOffset
} = this;
if (wickStrokeWidth === 0)
return;
ctx.globalAlpha *= wickStrokeOpacity;
if (typeof wickStroke === "string") {
ctx.strokeStyle = wickStroke;
}
ctx.lineWidth = wickStrokeWidth;
if (wickLineDash != null) {
ctx.setLineDash([...wickLineDash]);
}
ctx.lineDashOffset = wickLineDashOffset;
ctx.stroke(wickPath.getPath2D());
}
};
__decorateClass([
DeclaredSceneChangeDetection2()
], CandlestickNode.prototype, "wickStroke", 2);
__decorateClass([
DeclaredSceneChangeDetection2()
], CandlestickNode.prototype, "wickStrokeWidth", 2);
__decorateClass([
DeclaredSceneChangeDetection2()
], CandlestickNode.prototype, "wickStrokeOpacity", 2);
__decorateClass([
SceneArrayChangeDetection2()
], CandlestickNode.prototype, "wickLineDash", 2);
__decorateClass([
DeclaredSceneChangeDetection2()
], CandlestickNode.prototype, "wickLineDashOffset", 2);
__decorateClass([
DeclaredSceneChangeDetection2()
], CandlestickNode.prototype, "wickStrokeAlignment", 2);
// packages/ag-charts-enterprise/src/series/candlestick/candlestickSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport92 } from "ag-charts-community";
import { BaseProperties as BaseProperties21, Property as Property52 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/ohlc/ohlcSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport91 } from "ag-charts-community";
import { BaseProperties as BaseProperties20, Property as Property51 } from "ag-charts-core";
var { AbstractBarSeriesProperties: AbstractBarSeriesProperties2, makeSeriesTooltip: makeSeriesTooltip2 } = _ModuleSupport91;
var OhlcSeriesItem = class extends BaseProperties20 {
constructor() {
super(...arguments);
this.stroke = "#333";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
}
};
__decorateClass([
Property51
], OhlcSeriesItem.prototype, "stroke", 2);
__decorateClass([
Property51
], OhlcSeriesItem.prototype, "strokeWidth", 2);
__decorateClass([
Property51
], OhlcSeriesItem.prototype, "strokeOpacity", 2);
__decorateClass([
Property51
], OhlcSeriesItem.prototype, "lineDash", 2);
__decorateClass([
Property51
], OhlcSeriesItem.prototype, "lineDashOffset", 2);
var OhlcSeriesItems = class extends BaseProperties20 {
constructor() {
super(...arguments);
this.up = new OhlcSeriesItem();
this.down = new OhlcSeriesItem();
}
};
__decorateClass([
Property51
], OhlcSeriesItems.prototype, "up", 2);
__decorateClass([
Property51
], OhlcSeriesItems.prototype, "down", 2);
var OhlcSeriesBaseProperties = class extends AbstractBarSeriesProperties2 {
};
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "xKey", 2);
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "openKey", 2);
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "closeKey", 2);
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "highKey", 2);
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "lowKey", 2);
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "xName", 2);
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "yName", 2);
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "openName", 2);
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "closeName", 2);
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "highName", 2);
__decorateClass([
Property51
], OhlcSeriesBaseProperties.prototype, "lowName", 2);
var OhlcSeriesProperties = class extends OhlcSeriesBaseProperties {
constructor() {
super(...arguments);
this.tooltip = makeSeriesTooltip2();
this.item = new OhlcSeriesItems();
}
getStyle(itemType) {
const { strokeWidth, strokeOpacity, stroke: stroke3, lineDash, lineDashOffset } = this.item[itemType];
return {
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
opacity: 1
};
}
};
__decorateClass([
Property51
], OhlcSeriesProperties.prototype, "tooltip", 2);
__decorateClass([
Property51
], OhlcSeriesProperties.prototype, "item", 2);
__decorateClass([
Property51
], OhlcSeriesProperties.prototype, "itemStyler", 2);
// packages/ag-charts-enterprise/src/series/candlestick/candlestickSeriesProperties.ts
var { makeSeriesTooltip: makeSeriesTooltip3 } = _ModuleSupport92;
var CandlestickSeriesWick = class extends BaseProperties21 {
};
__decorateClass([
Property52
], CandlestickSeriesWick.prototype, "stroke", 2);
__decorateClass([
Property52
], CandlestickSeriesWick.prototype, "strokeWidth", 2);
__decorateClass([
Property52
], CandlestickSeriesWick.prototype, "strokeOpacity", 2);
__decorateClass([
Property52
], CandlestickSeriesWick.prototype, "lineDash", 2);
__decorateClass([
Property52
], CandlestickSeriesWick.prototype, "lineDashOffset", 2);
var CandlestickSeriesItem = class extends BaseProperties21 {
constructor() {
super(...arguments);
this.fill = "#c16068";
this.fillOpacity = 1;
this.stroke = "#333";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.cornerRadius = 0;
this.wick = new CandlestickSeriesWick();
}
};
__decorateClass([
Property52
], CandlestickSeriesItem.prototype, "fill", 2);
__decorateClass([
Property52
], CandlestickSeriesItem.prototype, "fillOpacity", 2);
__decorateClass([
Property52
], CandlestickSeriesItem.prototype, "stroke", 2);
__decorateClass([
Property52
], CandlestickSeriesItem.prototype, "strokeWidth", 2);
__decorateClass([
Property52
], CandlestickSeriesItem.prototype, "strokeOpacity", 2);
__decorateClass([
Property52
], CandlestickSeriesItem.prototype, "lineDash", 2);
__decorateClass([
Property52
], CandlestickSeriesItem.prototype, "lineDashOffset", 2);
__decorateClass([
Property52
], CandlestickSeriesItem.prototype, "cornerRadius", 2);
__decorateClass([
Property52
], CandlestickSeriesItem.prototype, "wick", 2);
var CandlestickSeriesItems = class extends BaseProperties21 {
constructor() {
super(...arguments);
this.up = new CandlestickSeriesItem();
this.down = new CandlestickSeriesItem();
}
};
__decorateClass([
Property52
], CandlestickSeriesItems.prototype, "up", 2);
__decorateClass([
Property52
], CandlestickSeriesItems.prototype, "down", 2);
var CandlestickSeriesProperties = class extends OhlcSeriesBaseProperties {
constructor() {
super(...arguments);
this.item = new CandlestickSeriesItems();
this.tooltip = makeSeriesTooltip3();
}
getStyle(itemType) {
const { fill, fillOpacity, strokeWidth, strokeOpacity, stroke: stroke3, lineDash, lineDashOffset, cornerRadius, wick } = this.item[itemType];
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
cornerRadius,
opacity: 1,
wick
};
}
};
__decorateClass([
Property52
], CandlestickSeriesProperties.prototype, "item", 2);
__decorateClass([
Property52
], CandlestickSeriesProperties.prototype, "tooltip", 2);
__decorateClass([
Property52
], CandlestickSeriesProperties.prototype, "itemStyler", 2);
// packages/ag-charts-enterprise/src/series/candlestick/candlestickSeries.ts
var CandlestickSeries = class extends OhlcSeriesBase {
constructor() {
super(...arguments);
this.properties = new CandlestickSeriesProperties();
}
nodeFactory() {
const node = new CandlestickNode();
node.lineCap = "butt";
return node;
}
updateDatumStyles({
datumSelection,
isHighlight
}) {
datumSelection.each((_, datum) => {
datum.style = this.getItemStyle(datum.datumIndex, isHighlight, void 0, datum.itemType);
});
}
updateDatumNodes({
datumSelection,
isHighlight
}) {
const { contextNodeData, properties } = this;
if (!contextNodeData) {
return;
}
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
const { up, down } = properties.item;
const fillBBox = this.getShapeFillBBox();
const series = this;
datumSelection.each(function updateCandlestickNode(node, datum) {
const { centerX, width, y, height, yOpen, yClose, crisp } = datum;
const baseStyle = datum.isRising ? up : down;
const highlightState = series.getHighlightState(highlightedDatum, isHighlight, datum.datumIndex);
const style = datum.style ?? contextNodeData.styles[datum.itemType][highlightState];
node.setStaticProperties(centerX, width, y, height, yOpen, yClose, crisp);
node.setStyleProperties(style, fillBBox);
const styleWick = style?.wick;
node.setWickProperties(
styleWick?.stroke,
styleWick?.strokeWidth,
styleWick?.strokeOpacity,
styleWick?.lineDash,
styleWick?.lineDashOffset
);
node.wickStrokeAlignment = baseStyle.wick.strokeWidth ?? baseStyle.strokeWidth;
});
}
legendItemSymbol() {
const { up, down } = this.properties.item;
const upColorStops = isGradientFill(up.fill) ? up.fill.colorStops.map(
(c) => typeof c === "string" ? c : { color: c.color, stop: c.stop == null ? void 0 : c.stop * 0.5 }
) : [
{ color: isPatternFill(up.fill) || isImageFill(up.fill) ? up.stroke : up.fill, stop: 0 },
{ color: isPatternFill(up.fill) || isImageFill(up.fill) ? up.stroke : up.fill, stop: 0.5 }
];
const downColorStops = isGradientFill(down.fill) ? down.fill.colorStops.map(
(c) => typeof c === "string" ? c : { color: c.color, stop: c.stop == null ? void 0 : c.stop * 0.5 }
) : [{ color: isPatternFill(down.fill) || isImageFill(down.fill) ? down.stroke : down.fill, stop: 0.5 }];
const fill = {
type: "gradient",
gradient: "linear",
rotation: 90,
colorStops: [...upColorStops, ...downColorStops],
reverse: false
};
const stroke3 = {
type: "gradient",
gradient: "linear",
rotation: 90,
colorStops: [
{ color: up.stroke, stop: 0 },
{ color: up.stroke, stop: 0.5 },
{ color: down.stroke, stop: 0.5 }
],
reverse: false
};
return {
marker: {
fill,
fillOpacity: up.fillOpacity,
stroke: stroke3,
strokeWidth: up.strokeWidth ?? 1,
strokeOpacity: up.strokeOpacity ?? 1,
lineDash: up.lineDash,
lineDashOffset: up.lineDashOffset
}
};
}
getLegendData(legendType) {
const {
id,
data,
visible,
ctx: { legendManager }
} = this;
const { xKey, yName, showInLegend, legendItemName } = this.properties;
if (!data?.data.length || !xKey || legendType !== "category") {
return [];
}
return [
{
legendType: "category",
id,
itemId: id,
seriesId: id,
enabled: visible && legendManager.getItemEnabled({ seriesId: id, itemId: id }),
label: {
text: legendItemName ?? yName ?? id
},
symbol: this.legendItemSymbol(),
legendItemName,
hideInLegend: !showInLegend
}
];
}
hasItemStylers() {
return this.properties.itemStyler != null;
}
};
CandlestickSeries.className = "CandleStickSeries";
CandlestickSeries.type = "candlestick";
// packages/ag-charts-enterprise/src/series/candlestick/candlestickSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport94 } from "ag-charts-community";
import {
boolean as boolean7,
commonSeriesOptionsDefs as commonSeriesOptionsDefs2,
constant as constant2,
number,
required as required2,
string as string2,
undocumented as undocumented4
} from "ag-charts-core";
var { candlestickSeriesThemeableOptionsDef } = _ModuleSupport94;
var candlestickSeriesOptionsDef = {
...commonSeriesOptionsDefs2,
...candlestickSeriesThemeableOptionsDef,
type: required2(constant2("candlestick")),
xKey: required2(string2),
openKey: required2(string2),
highKey: required2(string2),
lowKey: required2(string2),
closeKey: required2(string2),
xName: string2,
yName: string2,
openName: string2,
highName: string2,
lowName: string2,
closeName: string2,
xKeyAxis: string2,
yKeyAxis: string2
};
candlestickSeriesOptionsDef.pickOutsideVisibleMinorAxis = undocumented4(boolean7);
candlestickSeriesOptionsDef.focusPriority = undocumented4(number);
// packages/ag-charts-enterprise/src/series/candlestick/candlestickThemes.ts
import "ag-charts-community";
import {
CARTESIAN_AXIS_TYPE as CARTESIAN_AXIS_TYPE2,
FILL_GRADIENT_LINEAR_KEYED_DEFAULTS,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS2,
FILL_PATTERN_KEYED_DEFAULTS,
MULTI_SERIES_HIGHLIGHT_STYLE
} from "ag-charts-core";
function itemTheme(key) {
return {
fill: {
$applySwitch: [
{ $path: "type" },
{
$if: [
{ $eq: [{ $palette: "type" }, "user-indexed"] },
key === "up" ? "transparent" : { $palette: "fill" },
{ $palette: `${key}.fill` }
]
},
["gradient", FILL_GRADIENT_LINEAR_KEYED_DEFAULTS(key)],
["image", FILL_IMAGE_DEFAULTS2],
["pattern", FILL_PATTERN_KEYED_DEFAULTS(key)]
]
},
stroke: {
$if: [
{ $eq: [{ $palette: "type" }, "user-indexed"] },
{ $palette: "stroke" },
{ $palette: `${key}.stroke` }
]
}
};
}
var CANDLESTICK_SERIES_THEME = {
series: {
item: {
up: itemTheme("up"),
down: itemTheme("down")
},
tooltip: {
range: { $path: ["/tooltip/range", "nearest"] }
},
highlight: MULTI_SERIES_HIGHLIGHT_STYLE
},
animation: { enabled: false },
axes: {
[CARTESIAN_AXIS_TYPE2.NUMBER]: {
crosshair: {
snap: false
}
},
[CARTESIAN_AXIS_TYPE2.ORDINAL_TIME]: {
groupPaddingInner: 0,
crosshair: {
enabled: true
}
}
}
};
// packages/ag-charts-enterprise/src/series/candlestick/candlestickModule.ts
var { predictCartesianFinancialAxis } = _ModuleSupport95;
var CandlestickSeriesModule = {
type: "series",
name: "candlestick",
chartType: "cartesian",
enterprise: true,
groupable: false,
version: VERSION16,
dependencies: [CartesianChartModule2],
options: candlestickSeriesOptionsDef,
matchingKeys: ["xKey", "lowKey", "highKey", "openKey", "closeKey", "normalizedTo"],
predictAxis: predictCartesianFinancialAxis,
defaultAxes: {
y: {
type: CARTESIAN_AXIS_TYPE3.NUMBER,
position: CARTESIAN_POSITION.LEFT
},
x: {
type: CARTESIAN_AXIS_TYPE3.ORDINAL_TIME,
position: CARTESIAN_POSITION.BOTTOM
}
},
axisKeys: { [ChartAxisDirection18.X]: "xKeyAxis", [ChartAxisDirection18.Y]: "yKeyAxis" },
themeTemplate: CANDLESTICK_SERIES_THEME,
create: (ctx) => new CandlestickSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/heatmap/heatmapModule.ts
import { CartesianChartModule as CartesianChartModule3, VERSION as VERSION17 } from "ag-charts-community";
import { CARTESIAN_AXIS_TYPE as CARTESIAN_AXIS_TYPE4, CARTESIAN_POSITION as CARTESIAN_POSITION2, ChartAxisDirection as ChartAxisDirection20 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/heatmap/heatmapSeries.ts
import { _ModuleSupport as _ModuleSupport98 } from "ag-charts-community";
import {
ChartAxisDirection as ChartAxisDirection19,
Logger as Logger11,
extent,
formatValue,
mergeDefaults as mergeDefaults6,
toPlainText as toPlainText3
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/util/labelFormatter.ts
import { Logger as Logger10, cachedTextMeasurer as cachedTextMeasurer2, findMaxValue, wrapLines } from "ag-charts-core";
function generateLabelSecondaryLabelFontSizeCandidates(label, secondaryLabel) {
const { fontSize: labelFontSize, minimumFontSize: labelMinimumFontSize = labelFontSize } = label;
const {
fontSize: secondaryLabelFontSize,
minimumFontSize: secondaryLabelMinimumFontSize = secondaryLabelFontSize
} = secondaryLabel;
const labelTracks = labelFontSize - labelMinimumFontSize;
const secondaryLabelTracks = secondaryLabelFontSize - secondaryLabelMinimumFontSize;
let currentLabelFontSize = label.fontSize;
let currentSecondaryLabelFontSize = secondaryLabel.fontSize;
const out = [{ labelFontSize, secondaryLabelFontSize }];
while (currentLabelFontSize > labelMinimumFontSize || currentSecondaryLabelFontSize > secondaryLabelMinimumFontSize) {
const labelProgress = labelTracks > 0 ? (currentLabelFontSize - labelMinimumFontSize) / labelTracks : -1;
const secondaryLabelProgress = secondaryLabelTracks > 0 ? (currentSecondaryLabelFontSize - secondaryLabelMinimumFontSize) / secondaryLabelTracks : -1;
if (labelProgress > secondaryLabelProgress) {
currentLabelFontSize--;
} else {
currentSecondaryLabelFontSize--;
}
out.push({
labelFontSize: currentLabelFontSize,
secondaryLabelFontSize: currentSecondaryLabelFontSize
});
}
out.reverse();
return out;
}
function formatStackedLabels(labelValue, labelProps, secondaryLabelValue, secondaryLabelProps, { padding: padding2 }, sizeFittingHeight) {
const { spacing = 0 } = labelProps;
const widthAdjust = 2 * padding2;
const heightAdjust = 2 * padding2 + spacing;
const minimumHeight = (labelProps.minimumFontSize ?? labelProps.fontSize) + (secondaryLabelProps.minimumFontSize ?? secondaryLabelProps.fontSize);
if (minimumHeight > sizeFittingHeight(minimumHeight + heightAdjust, false).height - heightAdjust)
return;
const fontSizeCandidates = generateLabelSecondaryLabelFontSizeCandidates(labelProps, secondaryLabelProps);
const labelTextSizeProps = {
fontFamily: labelProps.fontFamily,
fontStyle: labelProps.fontStyle,
fontWeight: labelProps.fontWeight
};
const secondaryLabelTextSizeProps = {
fontFamily: secondaryLabelProps.fontFamily,
fontStyle: secondaryLabelProps.fontStyle,
fontWeight: secondaryLabelProps.fontWeight
};
let label;
let secondaryLabel;
return findMaxValue(0, fontSizeCandidates.length - 1, (index) => {
const { labelFontSize, secondaryLabelFontSize } = fontSizeCandidates[index];
const allowTruncation = index === 0;
const labelFont = { ...labelTextSizeProps, fontSize: labelFontSize };
const secondaryLabelFont = { ...secondaryLabelTextSizeProps, fontSize: secondaryLabelFontSize };
const labelLineHeight = cachedTextMeasurer2(labelFont).lineHeight();
const secondaryLabelLineHeight = cachedTextMeasurer2(secondaryLabelFont).lineHeight();
const sizeFitting = sizeFittingHeight(
labelLineHeight + secondaryLabelLineHeight + heightAdjust,
allowTruncation
);
const availableWidth = sizeFitting.width - widthAdjust;
const availableHeight = sizeFitting.height - heightAdjust;
if (labelLineHeight + secondaryLabelLineHeight > availableHeight)
return;
if (label?.fontSize !== labelFontSize) {
label = wrapLabel(
labelProps,
labelValue,
availableWidth,
availableHeight,
labelFont,
labelProps.wrapping,
allowTruncation ? labelProps.overflowStrategy : "hide"
);
}
if (label == null || label.width > availableWidth || label.height > availableHeight)
return;
if (secondaryLabel?.fontSize !== secondaryLabelFontSize) {
secondaryLabel = wrapLabel(
secondaryLabelProps,
secondaryLabelValue,
availableWidth,
availableHeight,
secondaryLabelFont,
secondaryLabelProps.wrapping,
allowTruncation ? secondaryLabelProps.overflowStrategy : "hide"
);
}
if (secondaryLabel == null)
return;
const totalLabelHeight = label.height + secondaryLabel.height;
if (secondaryLabel.width > availableWidth || totalLabelHeight > availableHeight)
return;
return {
width: Math.max(label.width, secondaryLabel.width),
height: totalLabelHeight + spacing,
meta: sizeFitting.meta,
label,
secondaryLabel
};
});
}
function formatSingleLabel(value, props, { padding: padding2 }, sizeFittingHeight) {
const sizeAdjust = 2 * padding2;
const minimumFontSize = Math.min(props.minimumFontSize ?? props.fontSize, props.fontSize);
const textSizeProps = {
fontFamily: props.fontFamily,
fontStyle: props.fontStyle,
fontWeight: props.fontWeight
};
return findMaxValue(minimumFontSize, props.fontSize, (fontSize) => {
const currentFont = { ...textSizeProps, fontSize };
const measurer3 = cachedTextMeasurer2(currentFont);
const allowTruncation = fontSize === minimumFontSize;
const lineHeight = props.lineHeight ?? measurer3.lineHeight();
const sizeFitting = sizeFittingHeight(lineHeight + sizeAdjust, allowTruncation);
const availableWidth = sizeFitting.width - sizeAdjust;
const availableHeight = sizeFitting.height - sizeAdjust;
if (lineHeight > availableHeight || availableWidth < 0)
return;
const lines = wrapLines(value, {
maxWidth: availableWidth,
maxHeight: availableHeight,
font: currentFont,
textWrap: props.wrapping,
overflow: (allowTruncation ? props.overflowStrategy : null) ?? "hide"
});
if (!lines.length)
return;
const { width, height } = measurer3.measureLines(lines);
const text2 = lines.join("\n");
return [{ width, height, text: text2, fontSize, lineHeight }, sizeFitting.meta];
});
}
function hasInvalidFontSize(label) {
return label?.minimumFontSize != null && label?.fontSize != null && label?.minimumFontSize > label?.fontSize;
}
function formatLabels(baseLabelValue, labelProps, baseSecondaryLabelValue, secondaryLabelProps, layoutParams, sizeFittingHeight) {
const labelValue = labelProps.enabled ? baseLabelValue : void 0;
const secondaryLabelValue = secondaryLabelProps.enabled ? baseSecondaryLabelValue : void 0;
if (hasInvalidFontSize(labelProps) || hasInvalidFontSize(secondaryLabelProps)) {
Logger10.warnOnce(`minimumFontSize should be set to a value less than or equal to the font size`);
}
let value;
if (labelValue != null && secondaryLabelValue != null) {
value = formatStackedLabels(
labelValue,
labelProps,
secondaryLabelValue,
secondaryLabelProps,
layoutParams,
sizeFittingHeight
);
}
let labelMeta;
if (value == null && labelValue != null) {
labelMeta = formatSingleLabel(labelValue, labelProps, layoutParams, sizeFittingHeight);
}
if (labelMeta != null) {
const [label, meta] = labelMeta;
value = {
width: label.width,
height: label.height,
meta,
label,
secondaryLabel: void 0
};
}
let secondaryLabelMeta;
if (value == null && labelValue == null && secondaryLabelValue != null) {
secondaryLabelMeta = formatSingleLabel(
secondaryLabelValue,
secondaryLabelProps,
layoutParams,
sizeFittingHeight
);
}
if (secondaryLabelMeta != null) {
const [secondaryLabel, meta] = secondaryLabelMeta;
value = {
width: secondaryLabel.width,
height: secondaryLabel.height,
meta,
label: void 0,
secondaryLabel
};
}
return value;
}
function wrapLabel(props, text2, maxWidth, maxHeight, font3, textWrap, overflow) {
const lines = wrapLines(text2, { maxWidth, maxHeight, font: font3, textWrap, overflow });
if (!lines.length)
return;
const measurer3 = cachedTextMeasurer2(font3);
const lineHeight = props.lineHeight ?? measurer3.lineHeight();
const { width } = measurer3.measureLines(lines);
return {
width,
lineHeight,
text: lines.join("\n"),
height: lines.length * lineHeight,
fontSize: font3.fontSize
};
}
// packages/ag-charts-enterprise/src/series/heatmap/heatmapSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport97 } from "ag-charts-community";
import { Property as Property54 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/util/autoSizedLabel.ts
import { _ModuleSupport as _ModuleSupport96 } from "ag-charts-community";
import { Property as Property53 } from "ag-charts-core";
var BaseAutoSizedLabel = class extends _ModuleSupport96.Label {
constructor() {
super(...arguments);
this.wrapping = "on-space";
this.overflowStrategy = "ellipsis";
}
};
__decorateClass([
Property53
], BaseAutoSizedLabel.prototype, "wrapping", 2);
__decorateClass([
Property53
], BaseAutoSizedLabel.prototype, "overflowStrategy", 2);
__decorateClass([
Property53
], BaseAutoSizedLabel.prototype, "lineHeight", 2);
__decorateClass([
Property53
], BaseAutoSizedLabel.prototype, "minimumFontSize", 2);
var AutoSizedLabel = class extends BaseAutoSizedLabel {
constructor() {
super(...arguments);
this.spacing = 0;
}
};
__decorateClass([
Property53
], AutoSizedLabel.prototype, "spacing", 2);
var AutoSizedSecondaryLabel = class extends BaseAutoSizedLabel {
};
// packages/ag-charts-enterprise/src/series/heatmap/heatmapSeriesProperties.ts
var { CartesianSeriesProperties, makeSeriesTooltip: makeSeriesTooltip4 } = _ModuleSupport97;
var HeatmapSeriesProperties = class extends CartesianSeriesProperties {
constructor() {
super(...arguments);
this.colorRange = ["black", "black"];
this.stroke = "black";
this.strokeOpacity = 1;
this.strokeWidth = 0;
this.textAlign = "center";
this.verticalAlign = "middle";
this.itemPadding = 0;
this.label = new AutoSizedLabel();
this.tooltip = makeSeriesTooltip4();
}
};
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "title", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "xKey", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "yKey", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "colorKey", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "xName", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "yName", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "colorName", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "colorRange", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "stroke", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "textAlign", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "verticalAlign", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "itemPadding", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "label", 2);
__decorateClass([
Property54
], HeatmapSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/heatmap/heatmapSeries.ts
var {
SeriesNodePickMode: SeriesNodePickMode3,
computeBarFocusBounds: computeBarFocusBounds3,
getMissCount,
valueProperty: valueProperty5,
DEFAULT_CARTESIAN_DIRECTION_KEYS,
DEFAULT_CARTESIAN_DIRECTION_NAMES,
createDatumId: createDatumId3,
ColorScale,
Rect,
PointerEvents,
addHitTestersToQuadtree,
findQuadtreeMatch,
updateLabelNode,
upsertNodeDatum: upsertNodeDatum2
} = _ModuleSupport98;
var HeatmapSeriesNodeEvent = class extends _ModuleSupport98.CartesianSeriesNodeEvent {
constructor(type, nativeEvent, datum, series) {
super(type, nativeEvent, datum, series);
this.colorKey = series.properties.colorKey;
}
};
var textAlignFactors = {
left: -0.5,
center: 0,
right: -0.5
};
var verticalAlignFactors = {
top: -0.5,
middle: 0,
bottom: -0.5
};
var HeatmapSeries = class extends _ModuleSupport98.CartesianSeries {
constructor(moduleCtx) {
super({
moduleCtx,
propertyKeys: {
...DEFAULT_CARTESIAN_DIRECTION_KEYS,
color: ["colorKey"]
},
propertyNames: {
...DEFAULT_CARTESIAN_DIRECTION_NAMES,
color: ["colorName"]
},
categoryKey: void 0,
pickModes: [SeriesNodePickMode3.NEAREST_NODE, SeriesNodePickMode3.EXACT_SHAPE_MATCH],
pathsPerSeries: []
});
this.properties = new HeatmapSeriesProperties();
this.NodeEvent = HeatmapSeriesNodeEvent;
this.colorScale = new ColorScale();
}
async processData(dataController) {
const xAxis = this.axes[ChartAxisDirection19.X];
const yAxis = this.axes[ChartAxisDirection19.Y];
if (!xAxis || !yAxis) {
return;
}
const { xKey, yKey, colorRange, colorKey } = this.properties;
const xScale = this.axes[ChartAxisDirection19.X]?.scale;
const yScale = this.axes[ChartAxisDirection19.Y]?.scale;
const { xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
const colorScaleType = this.colorScale.type;
const allowNullKey = this.properties.allowNullKeys ?? false;
const { dataModel, processedData } = await this.requestDataModel(dataController, this.data, {
props: [
valueProperty5(xKey, xScaleType, { id: "xValue", allowNullKey }),
valueProperty5(yKey, yScaleType, { id: "yValue", allowNullKey }),
...colorKey ? [valueProperty5(colorKey, colorScaleType, { id: "colorValue", invalidValue: void 0 })] : []
]
});
if (this.isColorScaleValid()) {
const colorKeyIdx = dataModel.resolveProcessedDataIndexById(this, "colorValue");
const rawDomain = processedData.domain.values[colorKeyIdx].filter((v) => v != null);
const domain = extent(rawDomain);
this.colorScale.domain = domain ?? [];
if (domain?.length && domain[0] === domain[1]) {
const midIndex = Math.floor(colorRange.length / 2);
this.colorScale.range = [colorRange[midIndex], colorRange[midIndex]];
} else {
this.colorScale.range = colorRange;
}
this.colorScale.update();
}
}
isColorScaleValid() {
const { colorKey } = this.properties;
if (!colorKey) {
return false;
}
const { dataModel, processedData } = this;
if (!dataModel || !processedData) {
return false;
}
const colorDataIdx = dataModel.resolveProcessedDataIndexById(this, "colorValue");
const dataCount = processedData.input.count;
const missCount = getMissCount(this, processedData.defs.values[colorDataIdx].missing);
const colorKeyIdx = dataModel.resolveProcessedDataIndexById(this, "colorValue");
const actualCount = processedData.domain.values[colorKeyIdx].filter((v) => v != null).length;
const colorDataMissing = dataCount === 0 || dataCount === missCount || actualCount === 0;
return !colorDataMissing;
}
xCoordinateRange(xValue, pixelSize) {
const xScale = this.axes[ChartAxisDirection19.X].scale;
const xOffset = pixelSize * (xScale.bandwidth ?? 0) / 2;
const x = xScale.convert(xValue) + xOffset;
const width = pixelSize * (xScale.bandwidth ?? 10);
return [x, x + width];
}
yCoordinateRange(yValues, pixelSize) {
const yScale = this.axes[ChartAxisDirection19.Y].scale;
const yOffset = pixelSize * (yScale.bandwidth ?? 0) / 2;
const y = yScale.convert(yValues[0]) + yOffset;
const height = pixelSize * (yScale.bandwidth ?? 10);
return [y, y + height];
}
getSeriesDomain(direction) {
const { dataModel, processedData } = this;
if (!dataModel || !processedData)
return { domain: [] };
if (direction === ChartAxisDirection19.X) {
const domain = dataModel.getDomain(this, `xValue`, "value", processedData).domain;
return { domain };
} else {
const domain = dataModel.getDomain(this, `yValue`, "value", processedData).domain;
return { domain };
}
}
getSeriesRange() {
return [Number.NaN, Number.NaN];
}
/**
* Template method hook: Validates preconditions for createNodeData.
* Overrides base to add heatmap-specific category axis validation.
*/
validateCreateNodeDataPreconditions() {
const result = super.validateCreateNodeDataPreconditions();
if (!result)
return void 0;
const { xAxis, yAxis } = result;
if (xAxis.type !== "category" || yAxis.type !== "category") {
Logger11.warnOnce(
`Heatmap series expected axes to have "category" type, but received "${xAxis.type}" and "${yAxis.type}" instead.`
);
return void 0;
}
return result;
}
/**
* Template method hook: Iterates over data and creates/updates node datums.
*/
populateNodeData(ctx) {
for (const [datumIndex, datum] of ctx.rawData.entries()) {
const nodeDatum = upsertNodeDatum2(
ctx,
{ datumIndex, datum },
(c, p) => this.createNodeDatum(c, p.datumIndex, p.datum),
(c, n, p) => this.updateNodeDatum(c, n, p.datumIndex, p.datum)
);
if (nodeDatum) {
const labelDatum = this.createLabelDatum(ctx, datumIndex, datum, nodeDatum);
if (labelDatum) {
ctx.labels.push(labelDatum);
}
}
}
}
/**
* Template method hook: Creates the result object shell.
*/
initializeResult(ctx) {
return {
itemId: this.properties.yKey ?? this.id,
nodeData: ctx.nodes,
labelData: ctx.labels,
scales: this.calculateScaling(),
visible: this.visible
};
}
/**
* Template method hook: Creates the shared context for datum creation.
* Caches expensive lookups and computations that are constant across all datums.
*/
createNodeDatumContext(xAxis, yAxis) {
const { dataModel, processedData, contextNodeData } = this;
if (!dataModel || !processedData)
return void 0;
const { xKey, xName, yKey, yName, colorKey, colorName, textAlign, verticalAlign, itemPadding } = this.properties;
const xScale = xAxis.scale;
const yScale = yAxis.scale;
const xValues = dataModel.resolveColumnById(this, `xValue`, processedData);
const yValues = dataModel.resolveColumnById(this, `yValue`, processedData);
const colorValues = colorKey ? dataModel.resolveColumnById(this, `colorValue`, processedData) : void 0;
const colorDomain = colorKey ? dataModel.getDomain(this, "colorValue", "value", processedData).domain : [];
const width = xScale.bandwidth ?? 10;
const height = yScale.bandwidth ?? 10;
const rawData = processedData.dataSources.get(this.id)?.data ?? [];
const canIncrementallyUpdate = contextNodeData?.nodeData != null && processedData.changeDescription != null;
return {
// Base context fields
xAxis,
yAxis,
xScale,
yScale,
rawData,
xValues,
xKey,
yKey,
xName,
yName,
animationEnabled: !this.ctx.animationManager.isSkipped(),
canIncrementallyUpdate,
nodes: canIncrementallyUpdate ? contextNodeData.nodeData : [],
nodeIndex: 0,
// Heatmap-specific positioning
xOffset: (xScale.bandwidth ?? 0) / 2,
yOffset: (yScale.bandwidth ?? 0) / 2,
width,
height,
textAlignFactor: (width - 2 * itemPadding) * textAlignFactors[textAlign],
verticalAlignFactor: (height - 2 * itemPadding) * verticalAlignFactors[verticalAlign],
// Heatmap-specific data
yValues,
colorKey,
colorName,
colorValues,
colorDomain,
itemPadding,
// Label support - labels are always rebuilt from scratch (not incrementally updated)
labels: [],
labelIndex: 0
};
}
/**
* Creates a skeleton HeatmapNodeDatum with minimal required fields.
* The node will be populated by updateNodeDatum.
*/
createSkeletonNodeDatum(ctx, datumIndex, datum) {
const { xKey, yKey, width, height, colorValues } = ctx;
const xDatum = ctx.xValues[datumIndex];
const yDatum = ctx.yValues[datumIndex];
const colorValue = colorValues?.[datumIndex];
return {
series: this,
datumIndex,
yKey,
xKey,
xValue: xDatum,
yValue: yDatum,
colorValue,
datum,
point: { x: 0, y: 0, size: 0 },
width,
height,
midPoint: { x: 0, y: 0 },
missing: colorValues != null && colorValue == null,
style: {}
};
}
/**
* Updates an existing HeatmapNodeDatum in-place.
*/
updateNodeDatum(ctx, node, datumIndex, datum) {
const { xScale, yScale, xOffset, yOffset, width, height, xKey, yKey, colorValues } = ctx;
const mutableNode = node;
const xDatum = ctx.xValues[datumIndex];
const yDatum = ctx.yValues[datumIndex];
const x = xScale.convert(xDatum) + xOffset;
const y = yScale.convert(yDatum) + yOffset;
if (!Number.isFinite(x) || !Number.isFinite(y))
return;
const colorValue = colorValues?.[datumIndex];
mutableNode.datumIndex = datumIndex;
mutableNode.datum = datum;
mutableNode.yKey = yKey;
mutableNode.xKey = xKey;
mutableNode.xValue = xDatum;
mutableNode.yValue = yDatum;
mutableNode.colorValue = colorValue;
mutableNode.width = width;
mutableNode.height = height;
mutableNode.missing = colorValues != null && colorValue == null;
const mutablePoint = mutableNode.point;
mutablePoint.x = x;
mutablePoint.y = y;
mutablePoint.size = 0;
mutableNode.midPoint.x = x;
mutableNode.midPoint.y = y;
mutableNode.style = this.getItemStyle({ datumIndex, datum, colorValue }, false);
}
/**
* Creates a HeatmapNodeDatum for a single data point.
* Returns undefined for invalid data points (e.g., null/undefined keys when not allowed).
*/
createNodeDatum(ctx, datumIndex, datum) {
const { xScale, yScale, xOffset, yOffset } = ctx;
const xDatum = ctx.xValues[datumIndex];
const yDatum = ctx.yValues[datumIndex];
const x = xScale.convert(xDatum) + xOffset;
const y = yScale.convert(yDatum) + yOffset;
if (!Number.isFinite(x) || !Number.isFinite(y)) {
return void 0;
}
const node = this.createSkeletonNodeDatum(ctx, datumIndex, datum);
this.updateNodeDatum(ctx, node, datumIndex, datum);
return node;
}
createLabelDatum(ctx, datumIndex, datum, nodeDatum) {
const { label } = this.properties;
const {
width,
height,
textAlignFactor,
verticalAlignFactor,
itemPadding,
colorKey,
colorName,
colorDomain,
xKey,
yKey,
xName,
yName
} = ctx;
const colorValue = ctx.colorValues?.[datumIndex];
const labelText = label.enabled && colorValue != null ? this.getLabelText(
colorValue,
datum,
colorKey,
"color",
colorDomain,
label,
{ value: colorValue, datum, colorKey, colorName, xKey, yKey, xName, yName }
) : void 0;
const sizeFittingHeight = () => ({ width, height, meta: null });
const labels = formatLabels(
toPlainText3(labelText),
this.properties.label,
void 0,
this.properties.label,
{ padding: itemPadding },
sizeFittingHeight
);
if (labels?.label == null) {
return void 0;
}
const { text: text2, fontSize, lineHeight, height: labelHeight } = labels.label;
const { fontStyle, fontFamily, fontWeight, color: color7 } = this.properties.label;
const { textAlign, verticalAlign } = this.properties;
const lx = nodeDatum.point.x + textAlignFactor * (width - 2 * itemPadding);
const ly = nodeDatum.point.y + verticalAlignFactor * (height - 2 * itemPadding) - (labels.height - labelHeight) * 0.5;
return {
series: this,
datum,
datumIndex,
text: text2,
fontSize,
lineHeight,
fontStyle,
fontFamily,
fontWeight,
color: color7,
textAlign,
textBaseline: verticalAlign,
x: lx,
y: ly,
style: nodeDatum.style
};
}
nodeFactory() {
return new Rect();
}
update(params) {
this.ctx.animationManager.skipCurrentBatch();
return super.update(params);
}
updateDatumSelection(opts) {
const { nodeData, datumSelection } = opts;
const data = nodeData ?? [];
return datumSelection.update(data);
}
getItemStyle({ datumIndex, datum, colorValue }, isHighlight, highlightState) {
const { properties } = this;
const { itemStyler, stroke: stroke3, strokeWidth, strokeOpacity } = properties;
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex, highlightState);
const style = mergeDefaults6(highlightStyle, {
fill: this.isColorScaleValid() && colorValue != null ? this.colorScale.convert(colorValue) : "transparent",
fillOpacity: 1,
stroke: stroke3,
strokeWidth,
strokeOpacity,
opacity: 1
});
let overrides;
if (itemStyler != null && datumIndex != null) {
overrides = this.cachedDatumCallback(createDatumId3(datumIndex, isHighlight ? "highlight" : "node"), () => {
const params = this.makeItemStylerParams(datum, datumIndex, isHighlight, style);
return this.callWithContext(itemStyler, params);
});
}
return overrides ? mergeDefaults6(overrides, style) : style;
}
makeItemStylerParams(datum, datumIndex, isHighlight, style) {
const { id: seriesId, properties } = this;
const { xKey, yKey } = properties;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightState = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum,
xKey,
yKey,
highlightState,
...style,
fill
};
}
updateDatumStyles({
datumSelection,
isHighlight
}) {
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
datumSelection.each((_, nodeDatum) => {
const highlightState = this.getHighlightState(activeHighlight, isHighlight, nodeDatum.datumIndex);
nodeDatum.style = this.getItemStyle(nodeDatum, isHighlight, highlightState);
});
}
updateDatumNodes({
datumSelection
}) {
const xAxis = this.axes[ChartAxisDirection19.X];
const [visibleMin, visibleMax] = xAxis?.visibleRange ?? [];
const isZoomed = visibleMin !== 0 || visibleMax !== 1;
const crisp = !isZoomed;
datumSelection.each((rect, nodeDatum) => {
const { point, width, height, style } = nodeDatum;
rect.setStyleProperties(style);
rect.crisp = crisp;
rect.x = Math.floor(point.x - width / 2);
rect.y = Math.floor(point.y - height / 2);
rect.width = Math.ceil(width);
rect.height = Math.ceil(height);
});
}
updateLabelSelection(opts) {
const { labelData, labelSelection } = opts;
const { enabled } = this.properties.label;
const data = enabled ? labelData : [];
return labelSelection.update(data);
}
updateLabelNodes(opts) {
const { isHighlight = false } = opts;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
opts.labelSelection.each((text2, datum) => {
text2.pointerEvents = PointerEvents.None;
text2.text = datum.text;
text2.fillOpacity = this.getHighlightStyle(isHighlight, datum.datumIndex)?.opacity ?? 1;
updateLabelNode(
this,
text2,
this.properties,
this.properties.label,
datum,
isHighlight,
activeHighlight
);
});
}
getTooltipContent(datumIndex) {
const { id: seriesId, dataModel, processedData, axes, properties, colorScale, ctx } = this;
const { formatManager } = ctx;
const { xKey, xName, yKey, yName, colorKey, colorName, colorRange, title, legendItemName, tooltip } = properties;
const xAxis = axes[ChartAxisDirection19.X];
const yAxis = axes[ChartAxisDirection19.Y];
if (!dataModel || !processedData || !xAxis || !yAxis)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const xValue = dataModel.resolveColumnById(this, `xValue`, processedData)[datumIndex];
const yValue = dataModel.resolveColumnById(this, `yValue`, processedData)[datumIndex];
const colorValue = colorKey != null && this.isColorScaleValid() ? dataModel.resolveColumnById(this, `colorValue`, processedData)[datumIndex] : void 0;
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (xValue === void 0 && !allowNullKeys)
return;
const data = [];
let fill;
if (colorValue == null) {
fill = colorRange[0];
} else {
fill = colorScale.convert(colorValue);
const domain = dataModel.getDomain(this, `colorValue`, "value", processedData).domain;
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: colorValue,
datum,
seriesId,
legendItemName,
key: colorKey,
source: "tooltip",
property: "color",
domain,
boundSeries: this.getFormatterContext("color"),
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: colorName, fallbackLabel: colorKey, value: content ?? formatValue(colorValue) });
}
data.push(
{
label: xName,
fallbackLabel: xKey,
value: this.getAxisValueText(xAxis, "tooltip", xValue, datum, xKey, legendItemName)
},
{
label: yName,
fallbackLabel: yKey,
value: this.getAxisValueText(yAxis, "tooltip", yValue, datum, yKey, legendItemName)
}
);
const format = this.getItemStyle({ datumIndex, datum, colorValue }, false);
if (format.fill != null) {
fill = format.fill;
}
const symbol = fill == null ? void 0 : {
marker: {
shape: "square",
fill,
fillOpacity: 1,
stroke: void 0,
strokeWidth: 0,
strokeOpacity: 1,
lineDash: [0],
lineDashOffset: 0
}
};
return this.formatTooltipWithContext(
tooltip,
{ title: title ?? legendItemName, symbol, data },
{
seriesId,
datum,
title,
xKey,
xName,
yKey,
yName,
colorKey,
colorName,
...format
}
);
}
getLegendData(legendType) {
if (legendType !== "gradient" || !this.isColorScaleValid() || !this.dataModel) {
return [];
}
return [
{
legendType: "gradient",
enabled: this.visible,
seriesId: this.id,
series: this.getFormatterContext("color"),
colorDomain: this.colorScale.domain,
colorRange: this.colorScale.range
}
];
}
isLabelEnabled() {
return this.properties.label.enabled && Boolean(this.properties.colorKey);
}
getBandScalePadding() {
return { inner: 0, outer: 0 };
}
computeFocusBounds({ datumIndex }) {
const datum = this.contextNodeData?.nodeData[datumIndex];
if (datum === void 0)
return void 0;
const { width, height, midPoint } = datum;
const focusRect = { x: midPoint.x - width / 2, y: midPoint.y - height / 2, width, height };
return computeBarFocusBounds3(this, focusRect);
}
initQuadTree(quadtree) {
addHitTestersToQuadtree(quadtree, this.datumNodesIter());
}
pickNodesExactShape(point) {
const item = findQuadtreeMatch(this, point);
return item != null && item.distance <= 0 ? [item.datum] : [];
}
pickNodeClosestDatum(point) {
return findQuadtreeMatch(this, point);
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.label.itemStyler != null || this.isColorScaleValid();
}
};
HeatmapSeries.className = "HeatmapSeries";
HeatmapSeries.type = "heatmap";
// packages/ag-charts-enterprise/src/series/heatmap/heatmapSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport99 } from "ag-charts-community";
import {
arrayOf,
color as color2,
commonSeriesOptionsDefs as commonSeriesOptionsDefs3,
constant as constant3,
required as required3,
string as string3,
without
} from "ag-charts-core";
var { heatmapSeriesThemeableOptionsDef } = _ModuleSupport99;
var heatmapSeriesOptionsDef = {
...without(heatmapSeriesThemeableOptionsDef, ["showInLegend"]),
...without(commonSeriesOptionsDefs3, ["showInLegend"]),
type: required3(constant3("heatmap")),
xKey: required3(string3),
yKey: required3(string3),
xKeyAxis: string3,
yKeyAxis: string3,
colorKey: string3,
xName: string3,
yName: string3,
colorName: string3,
colorRange: arrayOf(color2)
};
// packages/ag-charts-enterprise/src/series/heatmap/heatmapThemes.ts
import { LABEL_BOXING_DEFAULTS, SAFE_RANGE2_OPERATION } from "ag-charts-core";
var HEATMAP_SERIES_THEME = {
series: {
stroke: {
$if: [
{ $eq: [{ $palette: "type" }, "inbuilt"] },
{ $ref: "chartBackgroundColor" },
{ $path: ["/0", { $palette: "stroke" }, { $palette: "strokes" }] }
]
},
strokeWidth: { $isUserOption: ["./stroke", 2, void 0] },
label: {
...LABEL_BOXING_DEFAULTS,
enabled: false,
color: { $ref: "textColor" },
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
wrapping: "on-space",
overflowStrategy: "ellipsis"
},
itemPadding: 3,
highlight: {
unhighlightedItem: {
opacity: 0.6
}
}
},
gradientLegend: {
enabled: true
}
};
HEATMAP_SERIES_THEME.series.colorRange = {
$if: [{ $eq: [{ $palette: "type" }, "inbuilt"] }, { $palette: "divergingColors" }, SAFE_RANGE2_OPERATION]
};
// packages/ag-charts-enterprise/src/series/heatmap/heatmapModule.ts
var HeatmapSeriesModule = {
type: "series",
name: "heatmap",
chartType: "cartesian",
enterprise: true,
version: VERSION17,
dependencies: [CartesianChartModule3],
options: heatmapSeriesOptionsDef,
defaultAxes: {
y: { type: CARTESIAN_AXIS_TYPE4.CATEGORY, position: CARTESIAN_POSITION2.LEFT },
x: { type: CARTESIAN_AXIS_TYPE4.CATEGORY, position: CARTESIAN_POSITION2.BOTTOM }
},
axisKeys: { [ChartAxisDirection20.X]: "xKeyAxis", [ChartAxisDirection20.Y]: "yKeyAxis" },
themeTemplate: HEATMAP_SERIES_THEME,
create: (ctx) => new HeatmapSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/ohlc/ohlcModule.ts
import { CartesianChartModule as CartesianChartModule4, VERSION as VERSION18, _ModuleSupport as _ModuleSupport102 } from "ag-charts-community";
import {
CARTESIAN_AXIS_TYPE as CARTESIAN_AXIS_TYPE5,
CARTESIAN_POSITION as CARTESIAN_POSITION3,
ChartAxisDirection as ChartAxisDirection21,
MULTI_SERIES_HIGHLIGHT_STYLE as MULTI_SERIES_HIGHLIGHT_STYLE2
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/ohlc/ohlcSeries.ts
import "ag-charts-community";
var OhlcSeries = class extends OhlcSeriesBase {
constructor() {
super(...arguments);
this.properties = new OhlcSeriesProperties();
}
nodeFactory() {
const node = new OhlcNode();
node.lineCap = "square";
return node;
}
updateDatumStyles({
datumSelection,
isHighlight
}) {
datumSelection.each((_, datum) => {
datum.style = this.getItemStyle(datum.datumIndex, isHighlight, void 0, datum.itemType);
});
}
updateDatumNodes({
datumSelection,
isHighlight
}) {
const { contextNodeData, properties } = this;
if (!contextNodeData) {
return;
}
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
const { up, down } = properties.item;
const series = this;
datumSelection.each(function updateOhlcNode(node, datum) {
const { centerX, width, y, height, yOpen, yClose, crisp } = datum;
const baseStyle = datum.isRising ? up : down;
node.setStaticProperties(centerX, width, y, height, yOpen, yClose, crisp);
const style = datum.style ?? contextNodeData.styles[datum.itemType][series.getHighlightState(highlightedDatum, isHighlight, datum.datumIndex)];
node.setStyleProperties(style);
node.strokeAlignment = baseStyle.strokeWidth;
});
}
getLegendData(legendType) {
const {
id,
data,
ctx: { legendManager },
visible
} = this;
const {
xKey,
yName,
item: { up, down },
showInLegend,
legendItemName
} = this.properties;
if (!data?.data.length || !xKey || legendType !== "category") {
return [];
}
const fill = {
type: "gradient",
gradient: "linear",
colorSpace: "rgb",
colorStops: [
{ color: up.stroke, stop: 0 },
{ color: up.stroke, stop: 0.5 },
{ color: down.stroke, stop: 0.5 }
],
rotation: 90
};
return [
{
legendType: "category",
id,
itemId: id,
seriesId: id,
enabled: visible && legendManager.getItemEnabled({ seriesId: id, itemId: id }),
label: {
text: legendItemName ?? yName ?? id
},
symbol: {
marker: {
fill,
fillOpacity: up.strokeOpacity,
stroke: void 0,
strokeWidth: 0,
strokeOpacity: 1,
lineDash: [0],
lineDashOffset: 0
}
},
legendItemName,
hideInLegend: !showInLegend
}
];
}
hasItemStylers() {
return this.properties.itemStyler != null;
}
};
OhlcSeries.className = "ohlc";
OhlcSeries.type = "ohlc";
// packages/ag-charts-enterprise/src/series/ohlc/ohlcSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport101 } from "ag-charts-community";
import {
boolean as boolean8,
commonSeriesOptionsDefs as commonSeriesOptionsDefs4,
constant as constant4,
number as number2,
required as required4,
string as string4,
undocumented as undocumented5
} from "ag-charts-core";
var { ohlcSeriesThemeableOptionsDef } = _ModuleSupport101;
var ohlcSeriesOptionsDef = {
...commonSeriesOptionsDefs4,
...ohlcSeriesThemeableOptionsDef,
type: required4(constant4("ohlc")),
xKey: required4(string4),
openKey: required4(string4),
highKey: required4(string4),
lowKey: required4(string4),
closeKey: required4(string4),
xKeyAxis: string4,
yKeyAxis: string4,
xName: string4,
yName: string4,
openName: string4,
highName: string4,
lowName: string4,
closeName: string4
};
ohlcSeriesOptionsDef.pickOutsideVisibleMinorAxis = undocumented5(boolean8);
ohlcSeriesOptionsDef.focusPriority = undocumented5(number2);
// packages/ag-charts-enterprise/src/series/ohlc/ohlcModule.ts
var { predictCartesianFinancialAxis: predictCartesianFinancialAxis2 } = _ModuleSupport102;
var themeTemplate = {
animation: { enabled: false },
series: {
item: {
up: {
stroke: {
$if: [
{ $eq: [{ $palette: "type" }, "user-indexed"] },
{ $palette: "stroke" },
{ $palette: "up.stroke" }
]
}
},
down: {
stroke: {
$if: [
{ $eq: [{ $palette: "type" }, "user-indexed"] },
{ $palette: "stroke" },
{ $palette: "down.stroke" }
]
}
}
},
tooltip: {
range: { $path: ["/tooltip/range", "nearest"] }
},
highlight: MULTI_SERIES_HIGHLIGHT_STYLE2
},
axes: {
[CARTESIAN_AXIS_TYPE5.NUMBER]: {
crosshair: {
snap: false
}
},
[CARTESIAN_AXIS_TYPE5.ORDINAL_TIME]: {
groupPaddingInner: 0,
crosshair: {
enabled: true
}
}
}
};
var OhlcSeriesModule = {
type: "series",
name: "ohlc",
chartType: "cartesian",
enterprise: true,
version: VERSION18,
dependencies: [CartesianChartModule4],
options: ohlcSeriesOptionsDef,
matchingKeys: ["xKey", "lowKey", "highKey", "openKey", "closeKey", "normalizedTo"],
predictAxis: predictCartesianFinancialAxis2,
defaultAxes: {
y: { type: CARTESIAN_AXIS_TYPE5.NUMBER, position: CARTESIAN_POSITION3.LEFT },
x: { type: CARTESIAN_AXIS_TYPE5.ORDINAL_TIME, position: CARTESIAN_POSITION3.BOTTOM }
},
axisKeys: { [ChartAxisDirection21.X]: "xKeyAxis", [ChartAxisDirection21.Y]: "yKeyAxis" },
themeTemplate,
create: (ctx) => new OhlcSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/range-area/rangeAreaModule.ts
import { CartesianChartModule as CartesianChartModule5, VERSION as VERSION19, _ModuleSupport as _ModuleSupport109 } from "ag-charts-community";
import {
CARTESIAN_AXIS_TYPE as CARTESIAN_AXIS_TYPE7,
CARTESIAN_POSITION as CARTESIAN_POSITION4,
ChartAxisDirection as ChartAxisDirection23
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/range-area/rangeArea.ts
import {
_ModuleSupport as _ModuleSupport107
} from "ag-charts-community";
import {
AGGREGATION_INDEX_UNSET,
AGGREGATION_INDEX_Y_MAX as AGGREGATION_INDEX_Y_MAX2,
AGGREGATION_INDEX_Y_MIN as AGGREGATION_INDEX_Y_MIN2,
AGGREGATION_SPAN as AGGREGATION_SPAN2,
ChartAxisDirection as ChartAxisDirection22,
DebugMetrics as DebugMetrics2,
extent as extent2,
findMinMax as findMinMax2,
mergeDefaults as mergeDefaults7
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/range-area/rangeAreaAggregation.ts
import "ag-charts-community";
import {
aggregationDomain as aggregationDomain2,
computeExtremesAggregation as computeExtremesAggregation2,
computeExtremesAggregationPartial as computeExtremesAggregationPartial2,
simpleMemorize2 as simpleMemorize22
} from "ag-charts-core";
function aggregateRangeAreaData(scale, xValues, highValues, lowValues, domainInput, smallestKeyInterval, xNeedsValueOf, yNeedsValueOf) {
const [d0, d1] = aggregationDomain2(scale, domainInput);
return computeExtremesAggregation2([d0, d1], xValues, highValues, lowValues, {
smallestKeyInterval,
xNeedsValueOf,
yNeedsValueOf
});
}
var memoizedAggregateRangeAreaData = simpleMemorize22(aggregateRangeAreaData);
function aggregateRangeAreaDataFromDataModel(scale, dataModel, processedData, series, existingFilters) {
const xValues = dataModel.resolveKeysById(series, "xValue", processedData);
const highValues = dataModel.resolveColumnById(series, "yHighValue", processedData);
const lowValues = dataModel.resolveColumnById(series, "yLowValue", processedData);
const domainInput = dataModel.getDomain(series, "xValue", "key", processedData);
const xNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "xValue", processedData);
const yNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "yHighValue", processedData) ?? dataModel.resolveColumnNeedsValueOf(series, "yLowValue", processedData);
if (existingFilters) {
const [d0, d1] = aggregationDomain2(scale, domainInput);
return computeExtremesAggregation2([d0, d1], xValues, highValues, lowValues, {
smallestKeyInterval: processedData.reduced?.smallestKeyInterval,
xNeedsValueOf,
yNeedsValueOf,
existingFilters
});
}
return memoizedAggregateRangeAreaData(
scale,
xValues,
highValues,
lowValues,
domainInput,
processedData.reduced?.smallestKeyInterval,
xNeedsValueOf,
yNeedsValueOf
);
}
function aggregateRangeAreaDataFromDataModelPartial(scale, dataModel, processedData, series, targetRange, existingFilters) {
const xValues = dataModel.resolveKeysById(series, "xValue", processedData);
const highValues = dataModel.resolveColumnById(series, "yHighValue", processedData);
const lowValues = dataModel.resolveColumnById(series, "yLowValue", processedData);
const domainInput = dataModel.getDomain(series, "xValue", "key", processedData);
const xNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "xValue", processedData);
const yNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "yHighValue", processedData) ?? dataModel.resolveColumnNeedsValueOf(series, "yLowValue", processedData);
const [d0, d1] = aggregationDomain2(scale, domainInput);
return computeExtremesAggregationPartial2([d0, d1], xValues, highValues, lowValues, {
smallestKeyInterval: processedData.reduced?.smallestKeyInterval,
targetRange,
xNeedsValueOf,
yNeedsValueOf,
existingFilters
});
}
// packages/ag-charts-enterprise/src/series/range-area/rangeAreaIntersection.ts
import "ag-charts-community";
import { spanRange } from "ag-charts-core";
function getYValueAtX({ span }, x) {
switch (span.type) {
case "linear":
case "step":
case "multi-line": {
const t = (x - span.x0) / (span.x1 - span.x0);
return span.y0 + t * (span.y1 - span.y0);
}
case "cubic": {
const { cp0x, cp0y, cp1x, cp1y, cp2x, cp2y, cp3x, cp3y } = span;
let t = 0.5;
const tolerance = 1e-6;
for (let i = 0; i < 10; i++) {
const mt2 = 1 - t;
const xt = mt2 * mt2 * mt2 * cp0x + 3 * mt2 * mt2 * t * cp1x + 3 * mt2 * t * t * cp2x + t * t * t * cp3x;
const fx = xt - x;
if (Math.abs(fx) < tolerance)
break;
const dxdt = 3 * mt2 * mt2 * (cp1x - cp0x) + 6 * mt2 * t * (cp2x - cp1x) + 3 * t * t * (cp3x - cp2x);
if (Math.abs(dxdt) < 1e-12)
break;
t = t - fx / dxdt;
t = Math.max(0, Math.min(1, t));
}
const mt = 1 - t;
return mt * mt * mt * cp0y + 3 * mt * mt * t * cp1y + 3 * mt * t * t * cp2y + t * t * t * cp3y;
}
}
}
function findSpanForX(spans, x, startIndex = 0) {
for (let i = startIndex; i < spans.length; i++) {
const span = spans[i];
const [start, end] = spanRange(span.span);
if (x >= start.x && x <= end.x) {
return { span, index: i };
}
if (x < start.x) {
break;
}
}
return { span: null, index: startIndex };
}
function checkForIntersection(highSpans, lowSpans, x, wasInverted, spanIndex) {
const high = findSpanForX(highSpans, x, spanIndex);
const low = findSpanForX(lowSpans, x, spanIndex);
if (!high.span || !low.span) {
return { intersection: null, spanIndex: high.index, isInverted: wasInverted };
}
const highY = getYValueAtX(high.span, x);
const lowY = getYValueAtX(low.span, x);
const isInverted = highY > lowY;
const intersection = wasInverted === isInverted ? null : { x, y: highY };
return { intersection, spanIndex: high.index, isInverted };
}
function findRangeAreaIntersections(highSpans, lowSpans, minX, maxX, initiallyInverted = false) {
if (highSpans.length === 0 || lowSpans.length === 0)
return [];
const intersections = [];
let wasInverted = initiallyInverted;
let spanIndex = 0;
for (let x = minX; x <= maxX; x += 0.5) {
const result = checkForIntersection(highSpans, lowSpans, x, wasInverted, spanIndex);
if (result.intersection) {
intersections.push(result.intersection.x);
}
spanIndex = result.spanIndex;
wasInverted = result.isInverted;
}
return intersections;
}
function calculateIntersectionSegments(intersections, seriesRect, chartSize, startsInverted, style = {}) {
const horizontalMargin = Math.max(seriesRect.x, chartSize.width - (seriesRect.x + seriesRect.width));
const verticalMargin = Math.max(seriesRect.y, chartSize.height - (seriesRect.y + seriesRect.height));
const result = [];
const createClipRect = (x0, x1) => ({
x0,
y0: -verticalMargin,
x1,
y1: seriesRect.height + verticalMargin
});
if (startsInverted) {
result.push({
clipRect: createClipRect(-horizontalMargin, intersections[0] ?? seriesRect.width + horizontalMargin),
...style
});
}
const startIndex = startsInverted ? 1 : 0;
for (let i = startIndex; i < intersections.length; i += 2) {
result.push({
clipRect: createClipRect(intersections[i], intersections[i + 1] ?? seriesRect.width + horizontalMargin),
...style
});
}
return result;
}
// packages/ag-charts-enterprise/src/series/range-area/rangeAreaProperties.ts
import { _ModuleSupport as _ModuleSupport105 } from "ag-charts-community";
import { BaseProperties as BaseProperties22, InterpolationProperties, Property as Property55 } from "ag-charts-core";
var { CartesianSeriesProperties: CartesianSeriesProperties2, SeriesMarker, makeSeriesTooltip: makeSeriesTooltip5, DropShadow, Label: Label2 } = _ModuleSupport105;
var RangeAreaSeriesLabel = class extends Label2 {
constructor() {
super(...arguments);
this.placement = "outside";
this.spacing = 0;
}
};
__decorateClass([
Property55
], RangeAreaSeriesLabel.prototype, "placement", 2);
__decorateClass([
Property55
], RangeAreaSeriesLabel.prototype, "spacing", 2);
var RangeAreaInvertedStyle = class {
constructor() {
this.enabled = false;
this.fillOpacity = 1;
}
};
__decorateClass([
Property55
], RangeAreaInvertedStyle.prototype, "enabled", 2);
__decorateClass([
Property55
], RangeAreaInvertedStyle.prototype, "fill", 2);
__decorateClass([
Property55
], RangeAreaInvertedStyle.prototype, "fillOpacity", 2);
var RangeAreaLineStyle = class extends BaseProperties22 {
constructor() {
super(...arguments);
this.stroke = "#99CCFF";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.marker = new SeriesMarker();
}
};
__decorateClass([
Property55
], RangeAreaLineStyle.prototype, "stroke", 2);
__decorateClass([
Property55
], RangeAreaLineStyle.prototype, "strokeWidth", 2);
__decorateClass([
Property55
], RangeAreaLineStyle.prototype, "strokeOpacity", 2);
__decorateClass([
Property55
], RangeAreaLineStyle.prototype, "lineDash", 2);
__decorateClass([
Property55
], RangeAreaLineStyle.prototype, "lineDashOffset", 2);
__decorateClass([
Property55
], RangeAreaLineStyle.prototype, "marker", 2);
var RangeAreaItemProperties = class extends BaseProperties22 {
constructor() {
super(...arguments);
this.low = new RangeAreaLineStyle();
this.high = new RangeAreaLineStyle();
}
};
__decorateClass([
Property55
], RangeAreaItemProperties.prototype, "low", 2);
__decorateClass([
Property55
], RangeAreaItemProperties.prototype, "high", 2);
var SharedRangeAreaMarker = class extends BaseProperties22 {
};
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "enabled", 2);
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "shape", 2);
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "size", 2);
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "fill", 2);
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "fillOpacity", 2);
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "stroke", 2);
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "strokeWidth", 2);
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "strokeOpacity", 2);
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "lineDash", 2);
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "lineDashOffset", 2);
__decorateClass([
Property55
], SharedRangeAreaMarker.prototype, "itemStyler", 2);
var RangeAreaProperties = class extends CartesianSeriesProperties2 {
constructor() {
super(...arguments);
this.fill = "#99CCFF";
this.fillOpacity = 1;
this.stroke = "#99CCFF";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.interpolation = new InterpolationProperties();
this.item = new RangeAreaItemProperties();
this.invertedStyle = new RangeAreaInvertedStyle();
this.shadow = new DropShadow().set({ enabled: false });
this.marker = new SharedRangeAreaMarker();
this.label = new RangeAreaSeriesLabel();
this.tooltip = makeSeriesTooltip5();
this.connectMissingData = false;
}
};
__decorateClass([
Property55
], RangeAreaProperties.prototype, "xKey", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "yLowKey", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "yHighKey", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "xName", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "yName", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "yLowName", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "yHighName", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "fill", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "stroke", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "lineDash", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "interpolation", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "styler", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "item", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "invertedStyle", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "shadow", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "marker", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "label", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "tooltip", 2);
__decorateClass([
Property55
], RangeAreaProperties.prototype, "connectMissingData", 2);
// packages/ag-charts-enterprise/src/series/range-area/rangeAreaUtil.ts
import {
_ModuleSupport as _ModuleSupport106
} from "ag-charts-community";
import { areScalingEqual, isScaleValid } from "ag-charts-core";
var {
CollapseMode,
pairUpSpans,
prepareAreaFillAnimationFns,
plotInterpolatedLinePathStroke,
prepareLinePathPropertyAnimation
} = _ModuleSupport106;
function prepareRangeAreaPathStrokeAnimationFns(status, highSpans, lowSpans, visibleToggleMode) {
const removePhaseFn = (ratio8, path) => {
plotInterpolatedLinePathStroke(ratio8, path, highSpans.removed);
plotInterpolatedLinePathStroke(ratio8, path, lowSpans.removed);
};
const updatePhaseFn = (ratio8, path) => {
plotInterpolatedLinePathStroke(ratio8, path, highSpans.moved);
plotInterpolatedLinePathStroke(ratio8, path, lowSpans.moved);
};
const addPhaseFn = (ratio8, path) => {
plotInterpolatedLinePathStroke(ratio8, path, highSpans.added);
plotInterpolatedLinePathStroke(ratio8, path, lowSpans.added);
};
const pathProperties = prepareLinePathPropertyAnimation(status, visibleToggleMode);
return { status, path: { addPhaseFn, updatePhaseFn, removePhaseFn }, pathProperties };
}
function prepareRangeAreaPathAnimation(newData, oldData, diff8) {
const isCategoryBased = newData.scales.x?.type === "category";
const wasCategoryBased = oldData.scales.x?.type === "category";
if (isCategoryBased !== wasCategoryBased || !isScaleValid(newData.scales.x) || !isScaleValid(oldData.scales.x)) {
return;
}
let status = "updated";
if (oldData.visible && !newData.visible) {
status = "removed";
} else if (!oldData.visible && newData.visible) {
status = "added";
}
const fillSpans = pairUpSpans(
{ scales: newData.scales, data: newData.fillData.spans },
{ scales: oldData.scales, data: oldData.fillData.spans },
CollapseMode.Split
);
if (fillSpans == null)
return;
const fillPhantomSpans = pairUpSpans(
{ scales: newData.scales, data: newData.fillData.phantomSpans },
{ scales: oldData.scales, data: oldData.fillData.phantomSpans },
CollapseMode.Split
);
if (fillPhantomSpans == null)
return;
const highStrokeSpans = pairUpSpans(
{ scales: newData.scales, data: newData.highStrokeData.spans },
{ scales: oldData.scales, data: oldData.highStrokeData.spans },
CollapseMode.Split
);
if (highStrokeSpans == null)
return;
const lowStrokeSpans = pairUpSpans(
{ scales: newData.scales, data: newData.lowStrokeData.spans },
{ scales: oldData.scales, data: oldData.lowStrokeData.spans },
CollapseMode.Split
);
if (lowStrokeSpans == null)
return;
const fadeMode = "fade";
const fill = prepareAreaFillAnimationFns(status, fillSpans, fillPhantomSpans, fadeMode);
const stroke3 = prepareRangeAreaPathStrokeAnimationFns(status, highStrokeSpans, lowStrokeSpans, fadeMode);
const hasMotion = (diff8?.changed ?? true) || !areScalingEqual(newData.scales.x, oldData.scales.x) || !areScalingEqual(newData.scales.y, oldData.scales.y) || status !== "updated";
return { status, fill, stroke: stroke3, hasMotion };
}
// packages/ag-charts-enterprise/src/series/range-area/rangeArea.ts
var HIGH2 = AGGREGATION_INDEX_Y_MAX2;
var LOW2 = AGGREGATION_INDEX_Y_MIN2;
var SPAN2 = AGGREGATION_SPAN2;
var {
valueProperty: valueProperty6,
keyProperty: keyProperty4,
updateLabelNode: updateLabelNode2,
fixNumericExtent: fixNumericExtent4,
buildResetPathFn,
resetLabelFn,
resetMarkerFn,
resetMarkerPositionFn,
pathSwipeInAnimation,
resetMotion,
markerSwipeScaleInAnimation,
seriesLabelFadeInAnimation,
animationValidation: animationValidation3,
diff: diff3,
updateClipPath,
computeMarkerFocusBounds,
plotAreaPathFill,
plotLinePathStroke,
interpolatePoints,
pathFadeInAnimation,
markerFadeInAnimation,
fromToMotion,
pathMotion,
PointerEvents: PointerEvents2,
Marker,
BBox: BBox13,
processedDataIsAnimatable: processedDataIsAnimatable3,
markerEnabled,
getMarkerStyles,
calculateSegments: calculateSegments2,
toHighlightString: toHighlightString2,
HighlightState: HighlightState2,
AggregationManager: AggregationManager2,
resetMarkerSelectionsDirect,
createDatumId: createDatumId4,
visibleRangeIndices: visibleRangeIndices2
} = _ModuleSupport107;
var RangeAreaSeriesNodeEvent = class extends _ModuleSupport107.SeriesNodeEvent {
constructor(type, nativeEvent, datum, series) {
super(type, nativeEvent, datum, series);
this.xKey = series.properties.xKey;
this.yLowKey = series.properties.yLowKey;
this.yHighKey = series.properties.yHighKey;
}
};
var RangeAreaSeries = class extends _ModuleSupport107.CartesianSeries {
constructor(moduleCtx) {
super({
moduleCtx,
pathsPerSeries: ["fill", "lowStroke", "highStroke"],
pickModes: [_ModuleSupport107.SeriesNodePickMode.AXIS_ALIGNED],
propertyKeys: {
[ChartAxisDirection22.X]: ["xKey"],
[ChartAxisDirection22.Y]: ["yLowKey", "yHighKey"]
},
propertyNames: {
[ChartAxisDirection22.X]: ["xName"],
[ChartAxisDirection22.Y]: ["yLowName", "yHighName", "yName"]
},
categoryKey: "xValue",
animationResetFns: {
path: buildResetPathFn({ getVisible: () => this.visible, getOpacity: () => this.getOpacity() }),
label: resetLabelFn,
datum: (node, datum) => ({ ...resetMarkerFn(node), ...resetMarkerPositionFn(node, datum) })
},
clipFocusBox: false
});
this.properties = new RangeAreaProperties();
this.NodeEvent = RangeAreaSeriesNodeEvent;
this.aggregationManager = new AggregationManager2();
}
renderToOffscreenCanvas() {
const hasMarkers = (this.contextNodeData?.nodeData?.length ?? 0) > 0;
return hasMarkers && this.getDrawingMode(false) === "cutout" || super.renderToOffscreenCanvas();
}
async processData(dataController) {
const { xKey, yLowKey, yHighKey } = this.properties;
const xScale = this.axes[ChartAxisDirection22.X]?.scale;
const yScale = this.axes[ChartAxisDirection22.Y]?.scale;
const { xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
const extraProps = [];
const animationEnabled = !this.ctx.animationManager.isSkipped();
if (this.needsDataModelDiff() && this.processedData) {
extraProps.push(diff3(this.id, this.processedData));
}
if (animationEnabled) {
extraProps.push(animationValidation3());
}
const allowNullKey = this.properties.allowNullKeys ?? false;
const { dataModel, processedData } = await this.requestDataModel(dataController, this.data, {
props: [
keyProperty4(xKey, xScaleType, { id: `xValue`, allowNullKey }),
valueProperty6(yLowKey, yScaleType, { id: `yLowValue` }),
valueProperty6(yHighKey, yScaleType, { id: `yHighValue` }),
...extraProps
]
});
this.aggregateData(dataModel, processedData);
this.animationState.transition("updateData");
}
aggregateData(dataModel, processedData) {
this.aggregationManager.markStale(processedData.input.count);
if (processedData.type !== "ungrouped")
return;
if (processedDataIsAnimatable3(processedData))
return;
const xAxis = this.axes[ChartAxisDirection22.X];
if (xAxis == null)
return;
const targetRange = this.estimateTargetRange();
this.aggregationManager.aggregate({
computePartial: (existingFilters) => aggregateRangeAreaDataFromDataModelPartial(
xAxis.scale.type,
dataModel,
processedData,
this,
targetRange,
existingFilters
),
computeFull: (existingFilters) => aggregateRangeAreaDataFromDataModel(xAxis.scale.type, dataModel, processedData, this, existingFilters),
targetRange
});
const filters = this.aggregationManager.filters;
if (filters && filters.length > 0) {
DebugMetrics2.record(
`${this.type}:aggregation`,
filters.map((f) => f.maxRange)
);
}
}
estimateTargetRange() {
const xAxis = this.axes[ChartAxisDirection22.X];
if (xAxis?.scale?.range) {
const [r0, r1] = xAxis.scale.range;
return Math.abs(r1 - r0);
}
return this.ctx.scene?.canvas?.width ?? 800;
}
/**
* Creates the context object for efficient node datum creation.
* Caches expensive-to-compute values that are reused across all datum iterations.
*/
createNodeDatumContext(xAxis, yAxis) {
const { dataModel, processedData } = this;
if (!dataModel || !processedData)
return void 0;
const rawData = processedData.dataSources.get(this.id)?.data ?? [];
const xScale = xAxis.scale;
const yScale = yAxis.scale;
const xAxisRange = xAxis.range;
const [r0, r1] = xScale.range;
const range2 = Math.abs(r1 - r0);
this.aggregationManager.ensureLevelForRange(range2);
const dataAggregationFilter = this.aggregationManager.getFilterForRange(range2);
const existingNodes = this.contextNodeData?.nodeData;
const animationEnabled = !this.ctx.animationManager.isSkipped();
const canIncrementallyUpdate = existingNodes != null && (processedData.changeDescription != null || !processedDataIsAnimatable3(processedData) || dataAggregationFilter != null);
return {
xAxis,
yAxis,
rawData,
xValues: dataModel.resolveKeysById(this, "xValue", processedData),
yHighValues: dataModel.resolveColumnById(this, "yHighValue", processedData),
yLowValues: dataModel.resolveColumnById(this, "yLowValue", processedData),
xScale,
yScale,
xAxisRange,
xOffset: (xScale.bandwidth ?? 0) / 2,
dataAggregationFilter,
range: range2,
labelsEnabled: this.properties.label.enabled,
animationEnabled,
canIncrementallyUpdate,
xKey: this.properties.xKey,
yLowKey: this.properties.yLowKey,
yHighKey: this.properties.yHighKey,
item: this.properties.item,
yDomain: this.getSeriesDomain(ChartAxisDirection22.Y).domain,
connectMissingData: this.properties.connectMissingData,
interpolation: this.properties.interpolation,
nodes: canIncrementallyUpdate ? existingNodes : [],
labelData: [],
spanPoints: [],
nodeIndex: 0
};
}
xCoordinateRange(xValue) {
const x = this.axes[ChartAxisDirection22.X].scale.convert(xValue);
return [x, x];
}
yCoordinateRange(yValues) {
const y = this.axes[ChartAxisDirection22.Y].scale.convert(yValues[0]);
return [y, y];
}
getSeriesDomain(direction) {
const { processedData, dataModel } = this;
if (!(processedData && dataModel))
return { domain: [] };
const {
domain: {
keys: [keys]
}
} = processedData;
if (direction === ChartAxisDirection22.X) {
const keyDef = dataModel.resolveProcessedDataDefById(this, `xValue`);
if (keyDef?.def.type === "key" && keyDef.def.valueType === "category") {
const sortMetadata = dataModel.getKeySortMetadata(this, "xValue", processedData);
return { domain: keys, sortMetadata };
}
return { domain: fixNumericExtent4(extent2(keys)) };
} else {
const yExtent = this.domainForClippedRange(ChartAxisDirection22.Y, ["yHighValue", "yLowValue"], "xValue");
const fixedYExtent = findMinMax2(yExtent);
return { domain: fixNumericExtent4(fixedYExtent) };
}
}
getSeriesRange(_direction, visibleRange) {
return this.domainForVisibleRange(ChartAxisDirection22.Y, ["yHighValue", "yLowValue"], "xValue", visibleRange);
}
/**
* Processes a single datum and updates the context's marker, label, and span arrays.
* Uses the scratch object to avoid per-iteration allocations.
*
* @param yHighValueOverride - Optional override for yHighValue, used in aggregation mode
* when the extreme values come from different data points
* @param yLowValueOverride - Optional override for yLowValue, used in aggregation mode
*/
handleDatumPoint(ctx, scratch, datumIndex, yHighValueOverride, yLowValueOverride) {
scratch.xValue = ctx.xValues[datumIndex];
if (scratch.xValue === void 0 && !this.properties.allowNullKeys)
return;
scratch.datum = ctx.rawData[datumIndex];
scratch.yHighValue = yHighValueOverride ?? ctx.yHighValues[datumIndex];
scratch.yLowValue = yLowValueOverride ?? ctx.yLowValues[datumIndex];
const currentSpanPoints = ctx.spanPoints.at(-1);
if (Number.isFinite(scratch.yHighValue) && Number.isFinite(scratch.yLowValue)) {
scratch.inverted = scratch.yLowValue > scratch.yHighValue;
scratch.x = ctx.xScale.convert(scratch.xValue) + ctx.xOffset;
if (!Number.isFinite(scratch.x))
return;
scratch.yHighCoordinate = ctx.yScale.convert(scratch.yHighValue);
scratch.yLowCoordinate = ctx.yScale.convert(scratch.yLowValue);
this.upsertMarkerDatum(ctx, scratch, datumIndex, "high", scratch.yHighValue, scratch.yHighCoordinate);
this.upsertMarkerDatum(ctx, scratch, datumIndex, "low", scratch.yLowValue, scratch.yLowCoordinate);
const spanPoint = {
high: {
point: { x: scratch.x, y: scratch.yHighCoordinate },
xDatum: scratch.xValue,
yDatum: scratch.yHighValue
},
low: {
point: { x: scratch.x, y: scratch.yLowCoordinate },
xDatum: scratch.xValue,
yDatum: scratch.yLowValue
}
};
if (Array.isArray(currentSpanPoints)) {
currentSpanPoints.push(spanPoint);
} else if (currentSpanPoints == null) {
ctx.spanPoints.push([spanPoint]);
} else {
currentSpanPoints.skip += 1;
ctx.spanPoints.push([spanPoint]);
}
} else if (!ctx.connectMissingData) {
if (Array.isArray(currentSpanPoints) || currentSpanPoints == null) {
ctx.spanPoints.push({ skip: 0 });
} else {
currentSpanPoints.skip += 1;
}
}
}
/**
* Creates or updates marker datum for a single boundary (high or low).
* Supports incremental updates by reusing existing marker data objects when possible.
*/
upsertMarkerDatum(ctx, scratch, datumIndex, itemType, yValue, y) {
const { size } = ctx.item[itemType].marker;
const canReuseNode = ctx.canIncrementallyUpdate && ctx.nodeIndex < ctx.nodes.length;
if (canReuseNode) {
const existingNode = ctx.nodes[ctx.nodeIndex];
existingNode.index = datumIndex;
existingNode.itemType = itemType;
existingNode.datum = scratch.datum;
existingNode.datumIndex = datumIndex;
existingNode.midPoint = { x: scratch.x, y };
existingNode.yHighValue = scratch.yHighValue;
existingNode.yLowValue = scratch.yLowValue;
existingNode.xValue = scratch.xValue;
existingNode.point = { x: scratch.x, y, size };
} else {
ctx.nodes.push({
index: datumIndex,
series: this,
itemType,
datum: scratch.datum,
datumIndex,
midPoint: { x: scratch.x, y },
yHighValue: scratch.yHighValue,
yLowValue: scratch.yLowValue,
xValue: scratch.xValue,
xKey: ctx.xKey,
yLowKey: ctx.yLowKey,
yHighKey: ctx.yHighKey,
point: { x: scratch.x, y, size },
enabled: true
});
}
ctx.nodeIndex++;
if (ctx.labelsEnabled) {
const labelDatum = this.createLabelData({
datumIndex,
point: { x: scratch.x, y },
value: yValue,
yLowValue: scratch.yLowValue,
yHighValue: scratch.yHighValue,
itemType,
inverted: scratch.inverted,
datum: scratch.datum,
series: this
});
ctx.labelData.push(labelDatum);
}
}
populateNodeData(ctx) {
const { processedData } = this;
if (!processedData)
return;
const scratch = {
datum: void 0,
xValue: void 0,
yHighValue: 0,
yLowValue: 0,
x: 0,
yHighCoordinate: 0,
yLowCoordinate: 0,
inverted: false
};
const xPosition = (index) => ctx.xScale.convert(ctx.xValues[index]) + ctx.xOffset;
if (processedData.input.count < 1e3 || ctx.dataAggregationFilter == null) {
let [start, end] = visibleRangeIndices2(1, ctx.xValues.length, ctx.xAxisRange, (index) => {
const x = xPosition(index);
return [x, x];
});
if (processedData.input.count < 1e3) {
start = 0;
end = processedData.input.count;
}
start = Math.max(start - 1, 0);
end = Math.min(end + 1, ctx.xValues.length);
for (let datumIndex = start; datumIndex < end; datumIndex += 1) {
this.handleDatumPoint(ctx, scratch, datumIndex);
}
} else {
const { maxRange, indexData, midpointIndices } = ctx.dataAggregationFilter;
const [start, end] = visibleRangeIndices2(1, maxRange, ctx.xAxisRange, (index) => {
const midDatumIndex = midpointIndices[index];
if (midDatumIndex === AGGREGATION_INDEX_UNSET)
return;
return [xPosition(midDatumIndex), xPosition(midDatumIndex)];
});
for (let bucketIndex = start; bucketIndex < end; bucketIndex += 1) {
const midIndex = midpointIndices[bucketIndex];
if (midIndex === AGGREGATION_INDEX_UNSET)
continue;
const aggIndex = bucketIndex * SPAN2;
const yHighDatumIndex = indexData[aggIndex + HIGH2];
const yLowDatumIndex = indexData[aggIndex + LOW2];
this.handleDatumPoint(
ctx,
scratch,
yHighDatumIndex,
ctx.yHighValues[yHighDatumIndex],
ctx.yLowValues[yLowDatumIndex]
);
}
}
}
finalizeNodeData(ctx) {
if (ctx.canIncrementallyUpdate && ctx.nodeIndex < ctx.nodes.length) {
ctx.nodes.length = ctx.nodeIndex;
}
}
initializeResult(ctx) {
return {
itemId: `${ctx.yLowKey}-${ctx.yHighKey}`,
labelData: ctx.labelData,
nodeData: ctx.nodes,
fillData: { itemType: "high", spans: [], phantomSpans: [] },
highStrokeData: { itemType: "high", spans: [] },
lowStrokeData: { itemType: "low", spans: [] },
scales: this.calculateScaling(),
visible: this.visible,
styles: {
low: this.getLowOrHighMarkerStyles("low"),
high: this.getLowOrHighMarkerStyles("high")
},
segments: void 0,
intersectionSegments: void 0
};
}
assembleResult(ctx, result) {
const xAxis = this.axes[ChartAxisDirection22.X];
const yAxis = this.axes[ChartAxisDirection22.Y];
if (!xAxis || !yAxis || !this.chart?.seriesRect)
return result;
const highSpans = ctx.spanPoints.flatMap((p) => {
if (!Array.isArray(p))
return [];
const highPoints = p.map((d) => d.high);
return interpolatePoints(highPoints, ctx.interpolation);
});
const lowSpans = ctx.spanPoints.flatMap((p) => {
if (!Array.isArray(p))
return [];
const lowPoints = p.map((d) => d.low);
return interpolatePoints(lowPoints, ctx.interpolation);
});
const segments = calculateSegments2(
this.properties.segmentation,
xAxis,
yAxis,
this.chart.seriesRect,
this.ctx.scene,
false
);
let intersectionSegments = void 0;
if (this.properties.invertedStyle.enabled) {
const startsInverted = ctx.yHighValues[0] < ctx.yLowValues[0];
const intersectionXValues = findRangeAreaIntersections(
highSpans,
lowSpans,
ctx.xScale.range[0],
ctx.xScale.range[1],
startsInverted
);
intersectionSegments = calculateIntersectionSegments(
intersectionXValues,
this.chart.seriesRect,
this.ctx.scene,
startsInverted,
this.properties.invertedStyle
);
}
result.fillData = { itemType: "high", spans: highSpans, phantomSpans: lowSpans };
result.highStrokeData = { itemType: "high", spans: highSpans };
result.lowStrokeData = { itemType: "low", spans: lowSpans };
result.segments = segments;
result.intersectionSegments = intersectionSegments;
return result;
}
getLowOrHighMarkerStyles(lowOrHigh) {
const { fill, fillOpacity, item } = this.properties;
const line = item[lowOrHigh];
const { stroke: stroke3, strokeWidth, strokeOpacity } = line;
const inheritedStyles = { fill, fillOpacity, stroke: stroke3, strokeWidth, strokeOpacity };
return getMarkerStyles(this, line, line.marker, inheritedStyles);
}
createLabelData({
datumIndex,
point,
value,
itemType,
inverted,
datum,
series
}) {
const { xKey, yLowKey, yHighKey, xName, yName, yLowName, yHighName, legendItemName, label } = this.properties;
const { placement } = label;
const spacing = label.spacing + (typeof label.padding === "number" ? label.padding : 0);
let actualItemId = itemType;
if (inverted) {
actualItemId = itemType === "low" ? "high" : "low";
}
const direction = placement === "outside" && actualItemId === "high" || placement === "inside" && actualItemId === "low" ? -1 : 1;
const yDomain = this.getSeriesDomain(ChartAxisDirection22.Y).domain;
return {
x: point.x,
y: point.y + spacing * direction,
series,
itemType,
datum,
datumIndex,
text: this.getLabelText(
value,
datum,
itemType === "high" ? yHighKey : yLowKey,
"y",
yDomain,
label,
{ value, datum, itemType, xKey, yLowKey, yHighKey, xName, yLowName, yHighName, yName, legendItemName }
),
textAlign: "center",
textBaseline: direction === -1 ? "bottom" : "top"
};
}
isPathOrSelectionDirty() {
const { low, high } = this.properties.item;
return low.marker.isDirty() || high.marker.isDirty();
}
strokewidthChange() {
const itemStrokeWidthChange = (lowOrHigh) => {
const unhighlightedStrokeWidth = this.properties.item[lowOrHigh].strokeWidth ?? 0;
const highlightedSeriesStrokeWidth = this.properties.highlight.highlightedSeries.item?.[lowOrHigh]?.strokeWidth ?? unhighlightedStrokeWidth;
const highlightedItemStrokeWidth = this.properties.highlight.highlightedItem.item?.[lowOrHigh]?.strokeWidth ?? unhighlightedStrokeWidth;
return unhighlightedStrokeWidth > highlightedItemStrokeWidth || highlightedSeriesStrokeWidth > highlightedItemStrokeWidth;
};
return itemStrokeWidthChange("low") || itemStrokeWidthChange("high");
}
updatePathNodes(opts) {
const { visible } = opts;
const [fillPath, lowStrokePath, highStrokePath] = opts.paths;
const segments = this.contextNodeData?.segments;
const highlightDatum = this.ctx.highlightManager?.getActiveHighlight();
const highlightState = this.getHighlightState(highlightDatum, false);
const highlightStyle = this.getHighlightStyle();
const { item, fill, fillOpacity, opacity } = mergeDefaults7(highlightStyle, this.getStyle(highlightState));
lowStrokePath.setProperties({
datum: segments,
segments,
fill: void 0,
lineCap: "round",
lineJoin: "round",
pointerEvents: PointerEvents2.None,
stroke: item.low.stroke,
strokeWidth: item.low.strokeWidth,
strokeOpacity: item.low.strokeOpacity,
lineDash: item.low.lineDash,
lineDashOffset: item.low.lineDashOffset,
opacity,
visible
});
highStrokePath.setProperties({
segments,
fill: void 0,
lineCap: "round",
lineJoin: "round",
pointerEvents: PointerEvents2.None,
stroke: item.high.stroke,
strokeWidth: item.high.strokeWidth,
strokeOpacity: item.high.strokeOpacity,
lineDash: item.high.lineDash,
lineDashOffset: item.high.lineDashOffset,
opacity,
visible
});
const fillBBox = this.getShapeFillBBox();
fillPath.setFillProperties(fill, fillBBox);
fillPath.setStyleProperties({ stroke: void 0, fill, fillOpacity, opacity }, fillBBox);
const fillSegments = this.contextNodeData?.intersectionSegments ?? segments;
fillPath.setProperties({
segments: fillSegments,
pointerEvents: PointerEvents2.None,
lineJoin: "round",
fillShadow: this.properties.shadow,
opacity,
visible
});
fillPath.datum = fillSegments;
updateClipPath(this, fillPath);
updateClipPath(this, lowStrokePath);
updateClipPath(this, highStrokePath);
}
updatePaths(opts) {
this.updateAreaPaths(opts.paths, opts.contextData);
}
updateAreaPaths(paths, contextData) {
for (const path of paths) {
path.visible = contextData.visible;
}
if (contextData.visible) {
this.updateFillPath(paths, contextData);
this.updateStrokePath(paths, contextData);
} else {
for (const path of paths) {
path.path.clear();
path.markDirty("RangeArea");
}
}
}
updateFillPath(paths, contextData) {
const [fill] = paths;
fill.path.clear();
plotAreaPathFill(fill, contextData.fillData);
fill.markDirty("RangeArea");
}
updateStrokePath(paths, contextData) {
const [, lowStroke, highStroke] = paths;
lowStroke.path.clear();
highStroke.path.clear();
plotLinePathStroke(lowStroke, contextData.lowStrokeData.spans);
plotLinePathStroke(highStroke, contextData.highStrokeData.spans);
lowStroke.markDirty("RangeArea");
highStroke.markDirty("RangeArea");
}
resetDatumAnimation(data) {
resetMarkerSelectionsDirect([data.datumSelection]);
}
updateDatumSelection(opts) {
const { nodeData, datumSelection } = opts;
const { processedData, axes, properties } = this;
const rules = properties.styler ? this.getStylerMarkerOptions().item : properties.item;
const { low, high } = rules;
const markersEnabled = markerEnabled(processedData.input.count, axes[ChartAxisDirection22.X].scale, {
enabled: low.marker.enabled || high.marker.enabled
});
if (properties.item.low.marker.isDirty() || properties.item.high.marker.isDirty()) {
datumSelection.clear();
datumSelection.cleanup();
}
let resolvedNodeData;
if (markersEnabled) {
if (low.marker.enabled && high.marker.enabled) {
resolvedNodeData = nodeData;
} else {
resolvedNodeData = [];
for (const datum of nodeData) {
if (rules[datum.itemType].marker.enabled) {
resolvedNodeData.push(datum);
}
}
}
} else {
resolvedNodeData = [];
}
if (!processedDataIsAnimatable3(this.processedData)) {
return datumSelection.update(resolvedNodeData);
}
return datumSelection.update(
resolvedNodeData,
void 0,
(datum) => createDatumId4(datum.xValue, datum.itemType)
);
}
updateDatumStyles({
datumSelection,
isHighlight
}) {
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
datumSelection.each((_, datum) => {
const highlightState = this.getHighlightState(highlightedDatum, isHighlight, datum.datumIndex);
const stylerStyle = this.getStyle(highlightState);
const { fill, fillOpacity, item } = stylerStyle;
const { stroke: stroke3, strokeWidth, strokeOpacity } = item[datum.itemType];
const { marker } = this.properties.item[datum.itemType];
const params = this.makeItemStylerParams(datum.itemType);
datum.style = this.getMarkerStyle(
marker,
datum,
params,
{ isHighlight, highlightState, resolveMarkerSubPath: ["item", datum.itemType, "marker"] },
stylerStyle.item[datum.itemType].marker,
{
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity
}
);
});
}
updateDatumNodes(opts) {
const { contextNodeData } = this;
if (!contextNodeData) {
return;
}
const { datumSelection, isHighlight } = opts;
const fillBBox = this.getShapeFillBBox();
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
const drawingMode = this.getDrawingMode(isHighlight, opts.drawingMode);
datumSelection.each((node, datum) => {
const { itemType } = datum;
const style = datum.style ?? contextNodeData.styles[itemType][this.getHighlightState(highlightedDatum, isHighlight, datum.datumIndex)];
this.applyMarkerStyle(style, node, datum.point, fillBBox);
node.drawingMode = drawingMode;
});
if (!isHighlight) {
this.properties.item.low.marker.markClean();
this.properties.item.high.marker.markClean();
}
}
updateLabelSelection(opts) {
const { labelData, labelSelection } = opts;
return labelSelection.update(labelData, (text2) => {
text2.pointerEvents = PointerEvents2.None;
});
}
updateLabelNodes(opts) {
const params = {
xKey: this.properties.xKey,
xName: this.properties.xName ?? this.properties.xKey,
yName: this.properties.yName,
yLowKey: this.properties.yLowKey,
yLowName: this.properties.yLowName ?? this.properties.yLowKey,
yHighKey: this.properties.yHighKey,
yHighName: this.properties.yHighName ?? this.properties.yHighKey,
legendItemName: this.properties.legendItemName
};
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const { isHighlight = false, labelSelection } = opts;
labelSelection.each((textNode, datum) => {
textNode.fillOpacity = this.getHighlightStyle(isHighlight, datum.datumIndex).opacity ?? 1;
updateLabelNode2(this, textNode, params, this.properties.label, datum, isHighlight, activeHighlight);
});
}
getHighlightLabelData(labelData, highlightedItem) {
if (!labelData?.length)
return [];
return labelData.filter((labelDatum) => labelDatum.datum === highlightedItem.datum);
}
getHighlightData(nodeData, highlightedItem) {
const highlightItems = nodeData.filter((nodeDatum) => nodeDatum.datum === highlightedItem.datum).map((nodeDatum) => ({ ...nodeDatum }));
return highlightItems.length > 0 ? highlightItems : void 0;
}
getStyle(highlightState) {
return this.getStylerCouple(highlightState)[0];
}
getStylerMarkerOptions() {
return this.getStylerCouple()[1];
}
getStylerCouple(highlightState) {
const { fill, fillOpacity, item, styler } = this.properties;
let stylerResult = {};
if (styler) {
const stylerParams = this.makeStylerParams(highlightState);
stylerResult = this.ctx.optionsGraphService.resolvePartial(
["series", `${this.declarationOrder}`],
this.cachedCallWithContext(styler, stylerParams) ?? {},
{ pick: false }
) ?? {};
}
const markerOpts = {
item: { low: { marker: { enabled: false } }, high: { marker: { enabled: false } } }
};
const makeItemResult = (lowOrHigh) => {
const stylerItem = stylerResult.item?.[lowOrHigh];
const { lineDash, lineDashOffset, marker, stroke: stroke3, strokeOpacity, strokeWidth } = item[lowOrHigh];
markerOpts.item[lowOrHigh].marker.enabled = stylerItem?.marker?.enabled ?? marker.enabled;
return {
marker: {
fill: stylerItem?.marker?.fill ?? marker.fill ?? fill,
fillOpacity: stylerItem?.marker?.fillOpacity ?? marker.fillOpacity,
shape: stylerItem?.marker?.shape ?? marker.shape,
size: stylerItem?.marker?.size ?? marker.size,
lineDash: stylerItem?.marker?.lineDash ?? marker.lineDash,
lineDashOffset: stylerItem?.marker?.lineDashOffset ?? marker.lineDashOffset,
stroke: stylerItem?.marker?.stroke ?? marker.stroke ?? stroke3,
strokeOpacity: stylerItem?.marker?.strokeOpacity ?? marker.strokeOpacity,
strokeWidth: stylerItem?.marker?.strokeWidth ?? marker.strokeWidth
},
lineDash: stylerItem?.lineDash ?? lineDash,
lineDashOffset: stylerItem?.lineDashOffset ?? lineDashOffset,
stroke: stylerItem?.stroke ?? stroke3,
strokeOpacity: stylerItem?.strokeOpacity ?? strokeOpacity,
strokeWidth: stylerItem?.strokeWidth ?? strokeWidth
};
};
const style = {
fill: stylerResult.fill ?? fill,
fillOpacity: stylerResult.fillOpacity ?? fillOpacity,
opacity: 1,
topLevel: {
lineDash: this.properties.lineDash,
lineDashOffset: this.properties.lineDashOffset,
marker: this.properties.marker,
stroke: this.properties.stroke,
strokeOpacity: this.properties.strokeOpacity,
strokeWidth: this.properties.strokeWidth
},
item: {
low: makeItemResult("low"),
high: makeItemResult("high")
}
};
return [style, markerOpts];
}
makeStylerParams(highlightStateEnum) {
const { id: seriesId } = this;
const { fill, fillOpacity, item, xKey, yHighKey, yLowKey } = this.properties;
const highlightState = toHighlightString2(highlightStateEnum ?? HighlightState2.None);
const makeItemParam = (lowOrHigh) => {
const { lineDash, lineDashOffset, marker, stroke: stroke3, strokeOpacity, strokeWidth } = item[lowOrHigh];
return {
marker: {
fill: marker.fill ?? fill,
fillOpacity: marker.fillOpacity,
size: marker.size,
shape: marker.shape,
stroke: marker.stroke ?? stroke3,
strokeOpacity: marker.strokeOpacity,
strokeWidth: marker.strokeWidth,
lineDash: marker.lineDash,
lineDashOffset: marker.lineDashOffset
},
lineDash,
lineDashOffset,
stroke: stroke3,
strokeOpacity,
strokeWidth
};
};
return {
item: {
low: makeItemParam("low"),
high: makeItemParam("high")
},
fill,
fillOpacity,
highlightState,
seriesId,
xKey,
yLowKey,
yHighKey
};
}
makeItemStylerParams(itemType) {
const { xKey, yLowKey, yHighKey } = this.properties;
return { xKey, yLowKey, yHighKey, itemType };
}
getTooltipContent(datumIndex, removeThisDatum) {
const itemType = removeThisDatum?.itemType ?? "high";
const { id: seriesId, dataModel, processedData, axes, properties } = this;
const { xName, yName, yLowKey, yLowName, xKey, yHighKey, yHighName, tooltip, legendItemName } = properties;
const xAxis = axes[ChartAxisDirection22.X];
const yAxis = axes[ChartAxisDirection22.Y];
if (!dataModel || !processedData || !xAxis || !yAxis)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const xValue = dataModel.resolveKeysById(this, `xValue`, processedData)[datumIndex];
const yHighValue = dataModel.resolveColumnById(this, `yHighValue`, processedData)[datumIndex];
const yLowValue = dataModel.resolveColumnById(this, `yLowValue`, processedData)[datumIndex];
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (xValue === void 0 && !allowNullKeys)
return;
const stylerStyle = this.getStyle();
const params = this.makeItemStylerParams(itemType);
const format = this.getMarkerStyle(
this.properties.item[itemType].marker,
{ datumIndex, datum },
params,
{ isHighlight: false, resolveMarkerSubPath: ["item", itemType, "marker"] },
stylerStyle.item[itemType].marker
);
const value = `${this.getAxisValueText(yAxis, "tooltip", yLowValue, datum, yLowKey, legendItemName)} - ${this.getAxisValueText(yAxis, "tooltip", yHighValue, datum, yHighKey, legendItemName)}`;
return this.formatTooltipWithContext(
tooltip,
{
heading: this.getAxisValueText(xAxis, "tooltip", xValue, datum, xKey, legendItemName),
symbol: this.legendItemSymbol(),
data: [
{
label: yName,
fallbackLabel: `${yLowName ?? yLowKey} - ${yHighName ?? yHighKey}`,
value,
missing: _ModuleSupport107.isTooltipValueMissing(yHighValue) && _ModuleSupport107.isTooltipValueMissing(yLowValue)
}
]
},
{
seriesId,
datum,
title: yName,
itemType,
xName,
yName,
yLowKey,
yLowName,
xKey,
yHighKey,
yHighName,
legendItemName,
...format
}
);
}
legendItemSymbol() {
const { fill, topLevel } = this.getStyle();
const { stroke: stroke3, strokeWidth, strokeOpacity, lineDash, marker } = topLevel;
const markerStyle = {
shape: marker.shape,
fill: marker.fill ?? fill,
stroke: marker.stroke ?? stroke3,
fillOpacity: marker.fillOpacity,
strokeOpacity: marker.strokeOpacity,
strokeWidth: marker.strokeWidth,
lineDash: marker.lineDash,
lineDashOffset: marker.lineDashOffset
};
return {
marker: markerStyle,
line: {
enabled: true,
stroke: stroke3,
strokeOpacity,
strokeWidth,
lineDash
}
};
}
getLegendData(legendType) {
if (legendType !== "category") {
return [];
}
const { id: seriesId, visible } = this;
const { yLowKey, yHighKey, yName, yLowName, yHighName, legendItemName, showInLegend } = this.properties;
const legendItemText = legendItemName ?? yName ?? `${yLowName ?? yLowKey} - ${yHighName ?? yHighKey}`;
const itemId = `${yLowKey}-${yHighKey}`;
return [
{
legendType: "category",
id: seriesId,
itemId,
seriesId,
enabled: visible,
label: { text: `${legendItemText}` },
symbol: this.legendItemSymbol(),
legendItemName,
hideInLegend: !showInLegend
}
];
}
isLabelEnabled() {
return this.properties.label.enabled;
}
nodeFactory() {
return new Marker();
}
animateEmptyUpdateReady(animationData) {
const { datumSelection, labelSelection, contextData, paths } = animationData;
const { animationManager } = this.ctx;
this.updateAreaPaths(paths, contextData);
pathSwipeInAnimation(this, animationManager, ...paths);
resetMotion([datumSelection], resetMarkerPositionFn);
markerSwipeScaleInAnimation(
this,
animationManager,
{ ...this.getAnimationDrawingModes(), phase: "initial" },
datumSelection
);
seriesLabelFadeInAnimation(this, "labels", animationManager, labelSelection, this.highlightLabelSelection);
}
animateReadyResize(animationData) {
const { contextData, paths } = animationData;
this.updateAreaPaths(paths, contextData);
super.animateReadyResize(animationData);
}
animateWaitingUpdateReady(animationData) {
const { animationManager } = this.ctx;
const { datumSelection, labelSelection, contextData, paths, previousContextData } = animationData;
const [fill, lowStroke, highStroke] = paths;
if (fill == null && lowStroke == null && highStroke == null)
return;
this.resetDatumAnimation(animationData);
this.resetLabelAnimation(animationData);
const update = () => {
this.resetPathAnimation(animationData);
this.updateAreaPaths(paths, contextData);
};
const skip = () => {
animationManager.skipCurrentBatch();
update();
};
if (contextData == null || previousContextData == null) {
update();
markerFadeInAnimation(this, animationManager, "added", this.getAnimationDrawingModes(), datumSelection);
pathFadeInAnimation(this, "fill_path_properties", animationManager, "add", fill);
pathFadeInAnimation(this, "low_stroke_path_properties", animationManager, "add", lowStroke);
pathFadeInAnimation(this, "high_stroke_path_properties", animationManager, "add", highStroke);
seriesLabelFadeInAnimation(this, "labels", animationManager, labelSelection, this.highlightLabelSelection);
return;
}
const fns = prepareRangeAreaPathAnimation(
contextData,
previousContextData,
this.processedData?.reduced?.diff?.[this.id]
);
if (fns === void 0) {
skip();
return;
} else if (fns.status === "no-op") {
return;
}
fromToMotion(this.id, "fill_path_properties", animationManager, [fill], fns.fill.pathProperties);
fromToMotion(this.id, "low_stroke_path_properties", animationManager, [lowStroke], fns.stroke.pathProperties);
fromToMotion(this.id, "high_stroke_path_properties", animationManager, [highStroke], fns.stroke.pathProperties);
if (fns.status === "added") {
this.updateAreaPaths(paths, contextData);
} else if (fns.status === "removed") {
this.updateAreaPaths(paths, previousContextData);
} else {
pathMotion(this.id, "fill_path_update", animationManager, [fill], fns.fill.path);
pathMotion(this.id, "low_stroke_path_update", animationManager, [lowStroke], fns.stroke.path);
pathMotion(this.id, "high_stroke_path_update", animationManager, [highStroke], fns.stroke.path);
}
if (fns.hasMotion) {
markerFadeInAnimation(this, animationManager, void 0, this.getAnimationDrawingModes(), datumSelection);
seriesLabelFadeInAnimation(this, "labels", animationManager, labelSelection, this.highlightLabelSelection);
}
this.ctx.animationManager.animate({
id: this.id,
groupId: "reset_after_animation",
phase: "trailing",
from: {},
to: {},
onComplete: () => this.updateAreaPaths(paths, contextData)
});
}
getFormattedMarkerStyle(datum) {
const stylerStyle = this.getStyle();
const params = this.makeItemStylerParams(datum.itemType);
return this.getMarkerStyle(
this.properties.item[datum.itemType].marker,
datum,
params,
{ isHighlight: true, resolveMarkerSubPath: ["item", datum.itemType, "marker"] },
void 0,
stylerStyle
);
}
getMarkerStyle(marker, datum, params, opts, defaultOverrideStyle, inheritedStyle) {
true;
marker.itemStyler = this.properties.marker.itemStyler;
return super.getMarkerStyle(marker, datum, params, opts, defaultOverrideStyle, inheritedStyle);
}
computeFocusBounds(opts) {
const hiBox = computeMarkerFocusBounds(this, opts);
const loBox = computeMarkerFocusBounds(this, { ...opts, datumIndex: opts.datumIndex + 1 });
if (hiBox && loBox) {
return BBox13.merge([hiBox, loBox]);
}
return void 0;
}
isDatumEnabled(nodeData, datumIndex) {
return datumIndex % 2 === 0 && super.isDatumEnabled(nodeData, datumIndex);
}
hasItemStylers() {
return this.properties.styler != null || this.properties.marker.itemStyler != null || this.properties.label.itemStyler != null;
}
};
RangeAreaSeries.className = "RangeAreaSeries";
RangeAreaSeries.type = "range-area";
// packages/ag-charts-enterprise/src/series/range-area/rangeAreaSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport108 } from "ag-charts-community";
import {
boolean as boolean9,
commonSeriesOptionsDefs as commonSeriesOptionsDefs5,
constant as constant5,
fillOptionsDef,
number as number3,
required as required5,
shapeSegmentation as shapeSegmentation2,
string as string5,
undocumented as undocumented6
} from "ag-charts-core";
var { rangeAreaSeriesThemeableOptionsDef } = _ModuleSupport108;
var rangeAreaSeriesOptionsDef = {
...commonSeriesOptionsDefs5,
...rangeAreaSeriesThemeableOptionsDef,
type: required5(constant5("range-area")),
xKey: required5(string5),
yLowKey: required5(string5),
yHighKey: required5(string5),
xKeyAxis: string5,
yKeyAxis: string5,
xName: string5,
yName: string5,
yLowName: string5,
yHighName: string5,
legendItemName: string5,
segmentation: shapeSegmentation2,
invertedStyle: {
enabled: boolean9,
...fillOptionsDef
}
};
rangeAreaSeriesOptionsDef.pickOutsideVisibleMinorAxis = undocumented6(boolean9);
rangeAreaSeriesOptionsDef.focusPriority = undocumented6(number3);
// packages/ag-charts-enterprise/src/series/range-area/rangeAreaThemes.ts
import "ag-charts-community";
import {
CARTESIAN_AXIS_TYPE as CARTESIAN_AXIS_TYPE6,
FILL_GRADIENT_LINEAR_DEFAULTS as FILL_GRADIENT_LINEAR_DEFAULTS2,
FILL_GRADIENT_RADIAL_REVERSED_DEFAULTS,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS3,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS2,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS2,
MARKER_SERIES_HIGHLIGHT_STYLE,
SEGMENTATION_DEFAULTS as SEGMENTATION_DEFAULTS2
} from "ag-charts-core";
var RANGE_AREA_ITEM = {
lineDash: {
$path: "/series/$index/lineDash"
},
lineDashOffset: {
$path: "/series/$index/lineDashOffset"
},
stroke: {
$path: ["/series/$index/stroke", { $palette: "stroke" }]
},
strokeOpacity: {
$path: "/series/$index/strokeOpacity"
},
strokeWidth: {
$path: ["/series/$index/strokeWidth", 1]
},
marker: {
enabled: {
$path: "/series/$index/marker/enabled"
},
fill: {
$isUserOption: [
"/series/$index/marker/fill",
{
$if: [
{
$or: [
{ $isGradient: { $path: "/series/$index/marker/fill" } },
{ $isImage: { $path: "/series/$index/marker/fill" } },
{ $isPattern: { $path: "/series/$index/marker/fill" } }
]
},
{
$merge: [
{ $path: "/series/$index/marker/fill" },
{
$applySwitch: [
{ $path: "type" },
void 0,
// default case shouldn't be hit because of $if
["gradient", FILL_GRADIENT_RADIAL_REVERSED_DEFAULTS],
["image", FILL_IMAGE_DEFAULTS3],
["pattern", FILL_PATTERN_DEFAULTS2]
]
}
]
},
{
$isUserOption: [
"/series/$index/marker/fill",
{ $path: "/series/$index/marker/fill" },
{ $palette: "fill" }
]
}
]
},
{
$applySwitch: [
{ $path: "type" },
{ $palette: "fill" },
["gradient", FILL_GRADIENT_RADIAL_REVERSED_DEFAULTS],
["image", FILL_IMAGE_DEFAULTS3],
["pattern", FILL_PATTERN_DEFAULTS2]
]
}
]
},
fillOpacity: {
$path: "/series/$index/marker/fillOpacity"
},
lineDash: {
$path: "/series/$index/marker/lineDash"
},
lineDashOffset: {
$path: "/series/$index/marker/lineDashOffset"
},
shape: {
$path: "/series/$index/marker/shape"
},
size: {
$path: ["/series/$index/marker/size", 6]
},
stroke: {
$path: ["/series/$index/marker/stroke", { $palette: "stroke" }]
},
strokeOpacity: {
$path: "/series/$index/marker/strokeOpacity"
},
strokeWidth: {
$path: ["/series/$index/marker/strokeWidth", 2]
}
}
};
var RANGE_AREA_SERIES_THEME = {
series: {
fill: {
$applySwitch: [
{ $path: "type" },
{ $palette: "fill" },
["gradient", FILL_GRADIENT_LINEAR_DEFAULTS2],
["pattern", FILL_PATTERN_DEFAULTS2]
]
},
fillOpacity: 0.7,
stroke: { $palette: "stroke" },
strokeWidth: 1,
marker: {
enabled: false,
fill: {
$applySwitch: [
{ $path: "type" },
{ $palette: "fill" },
["gradient", FILL_GRADIENT_RADIAL_REVERSED_DEFAULTS],
["image", FILL_IMAGE_DEFAULTS3],
["pattern", FILL_PATTERN_DEFAULTS2]
]
},
shape: "circle",
stroke: { $palette: "stroke" },
size: 6,
strokeWidth: 2
},
nodeClickRange: "nearest",
item: {
low: RANGE_AREA_ITEM,
high: RANGE_AREA_ITEM
},
label: {
...LABEL_BOXING_DEFAULTS2,
enabled: false,
placement: "outside",
padding: { $isUserOption: ["./spacing", 0, 10] },
// compatibility with old `padding` property (now named `spacing`).
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "textColor" }
},
interpolation: {
type: "linear"
},
tooltip: {
range: { $path: ["/tooltip/range", "nearest"] }
},
highlight: MARKER_SERIES_HIGHLIGHT_STYLE,
segmentation: SEGMENTATION_DEFAULTS2,
invertedStyle: {
enabled: false,
fill: {
$applySwitch: [
{ $path: "type" },
{ $palette: "fill" },
// @todo(AG-14792) should be { $path: '../fill' } to inherit from series.fill
["gradient", FILL_GRADIENT_LINEAR_DEFAULTS2],
["image", FILL_IMAGE_DEFAULTS3],
["pattern", FILL_PATTERN_DEFAULTS2]
]
},
fillOpacity: { $path: "../fillOpacity" }
}
},
axes: {
[CARTESIAN_AXIS_TYPE6.NUMBER]: {
crosshair: { enabled: true }
}
}
};
// packages/ag-charts-enterprise/src/series/range-area/rangeAreaModule.ts
var { predictCartesianNonPrimitiveAxis: predictCartesianNonPrimitiveAxis2 } = _ModuleSupport109;
var RangeAreaSeriesModule = {
type: "series",
name: "range-area",
chartType: "cartesian",
enterprise: true,
version: VERSION19,
dependencies: [CartesianChartModule5],
options: rangeAreaSeriesOptionsDef,
matchingKeys: ["xKey", "yLowKey", "yHighKey", "normalizedTo"],
predictAxis: predictCartesianNonPrimitiveAxis2,
defaultAxes: {
y: { type: CARTESIAN_AXIS_TYPE7.NUMBER, position: CARTESIAN_POSITION4.LEFT },
x: { type: CARTESIAN_AXIS_TYPE7.CATEGORY, position: CARTESIAN_POSITION4.BOTTOM }
},
axisKeys: { [ChartAxisDirection23.X]: "xKeyAxis", [ChartAxisDirection23.Y]: "yKeyAxis" },
themeTemplate: RANGE_AREA_SERIES_THEME,
create: (ctx) => new RangeAreaSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/range-bar/rangeBarModule.ts
import { CartesianChartModule as CartesianChartModule6, VERSION as VERSION20, _ModuleSupport as _ModuleSupport114 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection25, DIRECTION_SWAP_AXES as DIRECTION_SWAP_AXES2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/range-bar/rangeBarSeries.ts
import {
_ModuleSupport as _ModuleSupport112
} from "ag-charts-community";
import {
AGGREGATION_INDEX_X_MAX as AGGREGATION_INDEX_X_MAX2,
AGGREGATION_INDEX_X_MIN as AGGREGATION_INDEX_X_MIN2,
AGGREGATION_INDEX_Y_MAX as AGGREGATION_INDEX_Y_MAX3,
AGGREGATION_INDEX_Y_MIN as AGGREGATION_INDEX_Y_MIN3,
AGGREGATION_SPAN as AGGREGATION_SPAN3,
ChartAxisDirection as ChartAxisDirection24,
DebugMetrics as DebugMetrics3,
areScalingEqual as areScalingEqual2,
findMinMax as findMinMax3,
mergeDefaults as mergeDefaults8
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/range-bar/rangeBarAggregation.ts
import "ag-charts-community";
import {
aggregationDomain as aggregationDomain3,
computeExtremesAggregation as computeExtremesAggregation3,
computeExtremesAggregationPartial as computeExtremesAggregationPartial3,
simpleMemorize2 as simpleMemorize23
} from "ag-charts-core";
function aggregateRangeBarData(scale, xValues, highValues, lowValues, domainInput, smallestKeyInterval, xNeedsValueOf, yNeedsValueOf) {
const [d0, d1] = aggregationDomain3(scale, domainInput);
return computeExtremesAggregation3([d0, d1], xValues, highValues, lowValues, {
smallestKeyInterval,
xNeedsValueOf,
yNeedsValueOf
});
}
var memoizedAggregateRangeBarData = simpleMemorize23(aggregateRangeBarData);
function aggregateRangeBarDataFromDataModel(scale, dataModel, processedData, series, existingFilters) {
const xValues = dataModel.resolveKeysById(series, "xValue", processedData);
const highValues = dataModel.resolveColumnById(series, "yHighValue", processedData);
const lowValues = dataModel.resolveColumnById(series, "yLowValue", processedData);
const domainInput = dataModel.getDomain(series, "xValue", "key", processedData);
const xNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "xValue", processedData);
const yNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "yHighValue", processedData) ?? dataModel.resolveColumnNeedsValueOf(series, "yLowValue", processedData);
if (existingFilters) {
const [d0, d1] = aggregationDomain3(scale, domainInput);
return computeExtremesAggregation3([d0, d1], xValues, highValues, lowValues, {
smallestKeyInterval: processedData.reduced?.smallestKeyInterval,
xNeedsValueOf,
yNeedsValueOf,
existingFilters
});
}
return memoizedAggregateRangeBarData(
scale,
xValues,
highValues,
lowValues,
domainInput,
processedData.reduced?.smallestKeyInterval,
xNeedsValueOf,
yNeedsValueOf
);
}
function aggregateRangeBarDataFromDataModelPartial(scale, dataModel, processedData, series, targetRange, existingFilters) {
const xValues = dataModel.resolveKeysById(series, "xValue", processedData);
const highValues = dataModel.resolveColumnById(series, "yHighValue", processedData);
const lowValues = dataModel.resolveColumnById(series, "yLowValue", processedData);
const domainInput = dataModel.getDomain(series, "xValue", "key", processedData);
const xNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "xValue", processedData);
const yNeedsValueOf = dataModel.resolveColumnNeedsValueOf(series, "yHighValue", processedData) ?? dataModel.resolveColumnNeedsValueOf(series, "yLowValue", processedData);
const [d0, d1] = aggregationDomain3(scale, domainInput);
return computeExtremesAggregationPartial3([d0, d1], xValues, highValues, lowValues, {
smallestKeyInterval: processedData.reduced?.smallestKeyInterval,
targetRange,
xNeedsValueOf,
yNeedsValueOf,
existingFilters
});
}
// packages/ag-charts-enterprise/src/series/range-bar/rangeBarProperties.ts
import { _ModuleSupport as _ModuleSupport111 } from "ag-charts-community";
import { Property as Property56 } from "ag-charts-core";
var { AbstractBarSeriesProperties: AbstractBarSeriesProperties3, makeSeriesTooltip: makeSeriesTooltip6, DropShadow: DropShadow2, Label: Label3 } = _ModuleSupport111;
var RangeBarSeriesLabel = class extends Label3 {
constructor() {
super(...arguments);
this.placement = "inside";
this.spacing = 0;
}
};
__decorateClass([
Property56
], RangeBarSeriesLabel.prototype, "placement", 2);
__decorateClass([
Property56
], RangeBarSeriesLabel.prototype, "spacing", 2);
var RangeBarProperties = class extends AbstractBarSeriesProperties3 {
constructor() {
super(...arguments);
this.fill = "#99CCFF";
this.fillOpacity = 1;
this.stroke = "#99CCFF";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.cornerRadius = 0;
this.shadow = new DropShadow2().set({ enabled: false });
this.label = new RangeBarSeriesLabel();
this.tooltip = makeSeriesTooltip6();
}
};
__decorateClass([
Property56
], RangeBarProperties.prototype, "xKey", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "yLowKey", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "yHighKey", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "xName", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "yName", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "yLowName", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "yHighName", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "fill", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "stroke", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "lineDash", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "cornerRadius", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "styler", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "itemStyler", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "shadow", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "label", 2);
__decorateClass([
Property56
], RangeBarProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/range-bar/rangeBarSeries.ts
var {
SeriesNodePickMode: SeriesNodePickMode4,
valueProperty: valueProperty7,
keyProperty: keyProperty5,
checkCrisp,
updateLabelNode: updateLabelNode3,
SMALLEST_KEY_INTERVAL: SMALLEST_KEY_INTERVAL3,
LARGEST_KEY_INTERVAL,
diff: diff4,
prepareBarAnimationFunctions,
midpointStartingBarPosition,
resetBarSelectionsFn,
resetBarSelectionsDirect,
fixNumericExtent: fixNumericExtent5,
seriesLabelFadeInAnimation: seriesLabelFadeInAnimation2,
resetLabelFn: resetLabelFn2,
animationValidation: animationValidation4,
computeBarFocusBounds: computeBarFocusBounds4,
visibleRangeIndices: visibleRangeIndices3,
createDatumId: createDatumId5,
Rect: Rect2,
PointerEvents: PointerEvents3,
motion: motion2,
processedDataIsAnimatable: processedDataIsAnimatable4,
getItemStyles: getItemStyles2,
calculateSegments: calculateSegments3,
toHighlightString: toHighlightString3,
HighlightState: HighlightState3,
AggregationManager: AggregationManager3,
upsertNodeDatum: upsertNodeDatum3
} = _ModuleSupport112;
var RangeBarSeriesNodeEvent = class extends _ModuleSupport112.SeriesNodeEvent {
constructor(type, nativeEvent, datum, series) {
super(type, nativeEvent, datum, series);
this.xKey = series.properties.xKey;
this.yLowKey = series.properties.yLowKey;
this.yHighKey = series.properties.yHighKey;
}
};
var RangeBarSeries = class extends _ModuleSupport112.AbstractBarSeries {
constructor(moduleCtx) {
super({
moduleCtx,
pickModes: [SeriesNodePickMode4.AXIS_ALIGNED, SeriesNodePickMode4.EXACT_SHAPE_MATCH],
propertyKeys: {
x: ["xKey"],
y: ["yLowKey", "yHighKey"]
},
propertyNames: {
x: ["xName"],
y: ["yLowName", "yHighName", "yName"]
},
categoryKey: "xValue",
datumSelectionGarbageCollection: false,
animationResetFns: {
datum: resetBarSelectionsFn,
label: resetLabelFn2
}
});
this.properties = new RangeBarProperties();
this.aggregationManager = new AggregationManager3();
this.NodeEvent = RangeBarSeriesNodeEvent;
}
async processData(dataController) {
const { xKey, yLowKey, yHighKey } = this.properties;
const xScale = this.getCategoryAxis()?.scale;
const yScale = this.getValueAxis()?.scale;
const { isContinuousX, xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
const extraProps = [];
if (this.needsDataModelDiff() && this.processedData) {
extraProps.push(diff4(this.id, this.processedData));
}
if (!this.ctx.animationManager.isSkipped()) {
extraProps.push(animationValidation4());
}
const visibleProps = this.visible ? {} : { forceValue: 0 };
const allowNullKey = this.properties.allowNullKeys ?? false;
const { dataModel, processedData } = await this.requestDataModel(dataController, this.data, {
props: [
keyProperty5(xKey, xScaleType, { id: "xValue", allowNullKey }),
valueProperty7(yLowKey, yScaleType, { id: `yLowValue`, invalidValue: null, ...visibleProps }),
valueProperty7(yHighKey, yScaleType, { id: `yHighValue`, invalidValue: null, ...visibleProps }),
...isContinuousX ? [SMALLEST_KEY_INTERVAL3, LARGEST_KEY_INTERVAL] : [],
...extraProps
],
groupByKeys: false
});
this.smallestDataInterval = processedData.reduced?.smallestKeyInterval;
this.largestDataInterval = processedData.reduced?.largestKeyInterval;
this.aggregateData(dataModel, processedData);
this.animationState.transition("updateData");
}
aggregateData(dataModel, processedData) {
this.aggregationManager.markStale(processedData.input.count);
if (processedData.type !== "ungrouped")
return;
if (processedDataIsAnimatable4(processedData))
return;
const xAxis = this.axes[ChartAxisDirection24.X];
if (xAxis == null)
return;
const targetRange = this.estimateTargetRange();
this.aggregationManager.aggregate({
computePartial: (existingFilters) => aggregateRangeBarDataFromDataModelPartial(
xAxis.scale.type,
dataModel,
processedData,
this,
targetRange,
existingFilters
),
computeFull: (existingFilters) => aggregateRangeBarDataFromDataModel(xAxis.scale.type, dataModel, processedData, this, existingFilters),
targetRange
});
const filters = this.aggregationManager.filters;
if (filters && filters.length > 0) {
DebugMetrics3.record(
`${this.type}:aggregation`,
filters.map((f) => f.maxRange)
);
}
}
estimateTargetRange() {
const xAxis = this.axes[ChartAxisDirection24.X];
if (xAxis?.scale == null)
return 0;
const [r0, r1] = xAxis.scale.range;
return Math.abs(r1 - r0);
}
getSeriesDomain(direction) {
const { processedData, dataModel } = this;
if (!processedData || !dataModel)
return { domain: [] };
const {
keys: [keys]
} = processedData.domain;
if (direction === this.getCategoryDirection()) {
const keyDef = dataModel.resolveProcessedDataDefById(this, `xValue`);
if (keyDef?.def.type === "key" && keyDef?.def.valueType === "category") {
const sortMetadata = dataModel.getKeySortMetadata(this, "xValue", processedData);
return { domain: keys, sortMetadata };
}
return { domain: this.padBandExtent(keys) };
} else {
const yExtent = this.domainForClippedRange(direction, ["yHighValue", "yLowValue"], "xValue");
const fixedYExtent = findMinMax3(yExtent);
return { domain: fixNumericExtent5(fixedYExtent) };
}
}
getSeriesRange(_direction, visibleRange) {
return this.domainForVisibleRange(ChartAxisDirection24.Y, ["yHighValue", "yLowValue"], "xValue", visibleRange);
}
/**
* Creates shared context for node datum creation/update operations.
* This context is instantiated once and reused across all datum operations
* to minimize memory allocations. Only caches values that are expensive to
* compute - cheap property lookups use `this` directly.
*/
createNodeDatumContext(xAxis, yAxis) {
const { dataModel, processedData } = this;
if (!dataModel || !processedData)
return void 0;
const rawData = processedData.dataSources?.get(this.id)?.data;
if (rawData == null)
return void 0;
const xScale = xAxis.scale;
const yScale = yAxis.scale;
const barAlongX = this.getBarDirection() === ChartAxisDirection24.X;
const crisp = checkCrisp(
xAxis?.scale,
xAxis?.visibleRange,
this.smallestDataInterval,
this.largestDataInterval
);
const [r0, r1] = xScale.range;
const range2 = Math.abs(r1 - r0);
this.aggregationManager.ensureLevelForRange(range2);
const dataAggregationFilter = this.aggregationManager.getFilterForRange(range2);
const animationEnabled = !this.ctx.animationManager.isSkipped();
const canIncrementallyUpdate = this.contextNodeData?.nodeData != null && (processedData.changeDescription != null || !processedDataIsAnimatable4(processedData) || dataAggregationFilter != null);
const { groupOffset, barOffset, barWidth } = this.getBarDimensions();
return {
xAxis,
yAxis,
rawData,
xValues: dataModel.resolveKeysById(this, `xValue`, processedData),
yLowValues: dataModel.resolveColumnById(this, `yLowValue`, processedData),
yHighValues: dataModel.resolveColumnById(this, `yHighValue`, processedData),
xScale,
yScale,
groupOffset,
barOffset,
barWidth,
barAlongX,
crisp,
dataAggregationFilter,
animationEnabled,
xKey: this.properties.xKey,
yLowKey: this.properties.yLowKey,
yHighKey: this.properties.yHighKey,
labelEnabled: this.properties.label.enabled,
labelPlacement: this.properties.label.placement,
labelPadding: (this.properties.label.spacing + (typeof this.properties.label.padding === "number" ? this.properties.label.padding : 0)) * (this.properties.label.placement === "outside" ? 1 : -1),
canIncrementallyUpdate,
nodes: canIncrementallyUpdate ? this.contextNodeData.nodeData : [],
nodeIndex: 0
};
}
/**
* Validates and prepares state needed for node creation/update.
* Returns undefined if datum should be skipped.
*/
prepareNodeDatumState(ctx, scratch, datumIndex) {
const datum = ctx.rawData[datumIndex];
const xValue = ctx.xValues[datumIndex];
if (xValue === void 0 && !this.properties.allowNullKeys)
return void 0;
const rawLowValue = ctx.yLowValues[datumIndex];
const rawHighValue = ctx.yHighValues[datumIndex];
if (!Number.isFinite(rawLowValue?.valueOf()) || !Number.isFinite(rawHighValue?.valueOf()))
return void 0;
const [yLowValue, yHighValue] = rawLowValue < rawHighValue ? [rawLowValue, rawHighValue] : [rawHighValue, rawLowValue];
scratch.datum = datum;
scratch.xValue = xValue;
scratch.yLowValue = yLowValue;
scratch.yHighValue = yHighValue;
scratch.rawLowValue = rawLowValue;
scratch.rawHighValue = rawHighValue;
return scratch;
}
/**
* Creates a minimal skeleton node - actual values set by updateNodeDatum.
*/
createSkeletonNodeDatum(ctx, params) {
const scratch = params.nodeDatumScratch;
return {
index: params.groupedDataIndex,
series: this,
datum: scratch.datum,
datumIndex: params.datumIndex,
xValue: scratch.xValue,
yLowValue: 0,
// Will be updated by updateNodeDatum
yHighValue: 0,
// Will be updated by updateNodeDatum
yLowKey: ctx.yLowKey,
yHighKey: ctx.yHighKey,
xKey: ctx.xKey,
x: 0,
// Will be updated by updateNodeDatum
y: 0,
// Will be updated by updateNodeDatum
width: 0,
// Will be updated by updateNodeDatum
height: 0,
// Will be updated by updateNodeDatum
midPoint: { x: 0, y: 0 },
// Will be updated by updateNodeDatum
crisp: params.crisp,
labels: []
// Will be updated by updateNodeDatum
};
}
/**
* Creates a new node: skeleton + update.
*/
createNodeDatum(ctx, params, _itemId, strokeWidth) {
const prepared = this.prepareNodeDatumState(ctx, params.nodeDatumScratch, params.datumIndex);
if (!prepared)
return void 0;
const nodeData = this.createSkeletonNodeDatum(ctx, params);
this.updateNodeDatum(ctx, nodeData, params, strokeWidth, prepared);
return nodeData;
}
/**
* Updates node properties in-place.
* Shared by both create (skeleton + update) and incremental update paths.
*/
updateNodeDatum(ctx, node, params, strokeWidth, prepared) {
prepared ?? (prepared = this.prepareNodeDatumState(ctx, params.nodeDatumScratch, params.datumIndex));
if (!prepared)
return;
const mutableNode = node;
mutableNode.index = params.groupedDataIndex;
mutableNode.datum = prepared.datum;
mutableNode.datumIndex = params.datumIndex;
mutableNode.xValue = prepared.xValue;
mutableNode.yLowValue = prepared.rawLowValue;
mutableNode.yHighValue = prepared.rawHighValue;
mutableNode.crisp = params.crisp;
const y = Math.round(ctx.yScale.convert(params.yHigh));
const bottomY = Math.round(ctx.yScale.convert(params.yLow));
const height = Math.max(strokeWidth, Math.abs(bottomY - y));
const rect = {
x: ctx.barAlongX ? Math.min(y, bottomY) : params.x,
y: ctx.barAlongX ? params.x : Math.min(y, bottomY),
width: ctx.barAlongX ? height : params.width,
height: ctx.barAlongX ? params.width : height
};
mutableNode.x = rect.x;
mutableNode.y = rect.y;
mutableNode.width = rect.width;
mutableNode.height = rect.height;
const mutableMidPoint = mutableNode.midPoint;
mutableMidPoint.x = rect.x + rect.width / 2;
mutableMidPoint.y = rect.y + rect.height / 2;
const existingClipBBox = mutableNode.clipBBox;
if (existingClipBBox) {
existingClipBBox.x = rect.x;
existingClipBBox.y = rect.y;
existingClipBBox.width = rect.width;
existingClipBBox.height = rect.height;
}
const labelParams = params.labelParamsScratch;
labelParams.labels = mutableNode.labels;
labelParams.datumIndex = params.datumIndex;
labelParams.rectX = rect.x;
labelParams.rectY = rect.y;
labelParams.rectWidth = rect.width;
labelParams.rectHeight = rect.height;
labelParams.yLowValue = prepared.yLowValue;
labelParams.yHighValue = prepared.yHighValue;
labelParams.datum = prepared.datum;
this.updateLabelData(ctx, labelParams);
}
/**
* Creates node data using aggregation filters for large datasets.
*/
createNodeDataWithAggregation(ctx, xPosition, nodeDatumParamsScratch, itemId, strokeWidth, dataAggregationFilter) {
const { maxRange, indexData, midpointIndices } = dataAggregationFilter;
const [start, end] = visibleRangeIndices3(1, maxRange, ctx.xAxis.range, (index) => {
const aggIndex = index * AGGREGATION_SPAN3;
const xMaxIndex = indexData[aggIndex + AGGREGATION_INDEX_X_MAX2];
const midDatumIndex = midpointIndices[index];
if (midDatumIndex === -1)
return;
return [xPosition(midDatumIndex), xPosition(xMaxIndex) + ctx.barWidth];
});
for (let i = start; i < end; i += 1) {
const aggIndex = i * AGGREGATION_SPAN3;
const xMinIndex = indexData[aggIndex + AGGREGATION_INDEX_X_MIN2];
const xMaxIndex = indexData[aggIndex + AGGREGATION_INDEX_X_MAX2];
const yMinIndex = indexData[aggIndex + AGGREGATION_INDEX_Y_MIN3];
const yMaxIndex = indexData[aggIndex + AGGREGATION_INDEX_Y_MAX3];
const midDatumIndex = midpointIndices[i];
if (midDatumIndex === -1)
continue;
const xValue = ctx.xValues[midDatumIndex];
if (xValue === void 0 && !this.properties.allowNullKeys)
continue;
nodeDatumParamsScratch.datumIndex = midDatumIndex;
nodeDatumParamsScratch.groupedDataIndex = 0;
nodeDatumParamsScratch.x = xPosition(midDatumIndex);
nodeDatumParamsScratch.width = Math.abs(xPosition(xMinIndex) - xPosition(xMaxIndex)) + ctx.barWidth;
nodeDatumParamsScratch.yLow = ctx.yLowValues[yMinIndex];
nodeDatumParamsScratch.yHigh = ctx.yHighValues[yMaxIndex];
nodeDatumParamsScratch.crisp = false;
upsertNodeDatum3(
ctx,
nodeDatumParamsScratch,
(c, p) => this.createNodeDatum(c, p, itemId, strokeWidth),
(c, n, p) => this.updateNodeDatum(c, n, p, strokeWidth)
);
}
}
/**
* Creates node data for simple (ungrouped) data processing.
*/
createNodeDataSimple(ctx, xPosition, nodeDatumParamsScratch, itemId, strokeWidth, processedData) {
const invalidData = processedData.invalidData?.get(this.id);
let [start, end] = this.visibleRangeIndices("xValue", ctx.xAxis.range);
if (processedData.input.count < 1e3) {
start = 0;
end = processedData.input.count;
}
for (let datumIndex = start; datumIndex < end; datumIndex += 1) {
if (invalidData?.[datumIndex] === true)
continue;
nodeDatumParamsScratch.datumIndex = datumIndex;
nodeDatumParamsScratch.groupedDataIndex = 0;
nodeDatumParamsScratch.x = xPosition(datumIndex);
nodeDatumParamsScratch.width = ctx.barWidth;
nodeDatumParamsScratch.yLow = ctx.yLowValues[datumIndex];
nodeDatumParamsScratch.yHigh = ctx.yHighValues[datumIndex];
nodeDatumParamsScratch.crisp = ctx.crisp;
upsertNodeDatum3(
ctx,
nodeDatumParamsScratch,
(c, p) => this.createNodeDatum(c, p, itemId, strokeWidth),
(c, n, p) => this.updateNodeDatum(c, n, p, strokeWidth)
);
}
}
/**
* Creates node data for grouped data processing.
*/
createNodeDataGrouped(ctx, xPosition, nodeDatumParamsScratch, itemId, strokeWidth) {
const processedData = this.processedData;
for (const { datumIndex, groupIndex: groupDataIndex } of this.dataModel.forEachGroupDatum(
this,
processedData
)) {
nodeDatumParamsScratch.datumIndex = datumIndex;
nodeDatumParamsScratch.groupedDataIndex = groupDataIndex;
nodeDatumParamsScratch.x = xPosition(datumIndex);
nodeDatumParamsScratch.width = ctx.barWidth;
nodeDatumParamsScratch.yLow = ctx.yLowValues[datumIndex];
nodeDatumParamsScratch.yHigh = ctx.yHighValues[datumIndex];
nodeDatumParamsScratch.crisp = ctx.crisp;
upsertNodeDatum3(
ctx,
nodeDatumParamsScratch,
(c, p) => this.createNodeDatum(c, p, itemId, strokeWidth),
(c, n, p) => this.updateNodeDatum(c, n, p, strokeWidth)
);
}
}
populateNodeData(ctx) {
const { processedData } = this;
if (!processedData)
return;
const { yLowKey, yHighKey, strokeWidth } = this.properties;
const itemId = `${yLowKey}-${yHighKey}`;
const xPosition = (datumIndex) => {
const x = ctx.xScale.convert(ctx.xValues[datumIndex]);
if (!Number.isFinite(x))
return Number.NaN;
return Math.round(x) + ctx.groupOffset + ctx.barOffset;
};
const nodeDatumParamsScratch = {
nodeDatumScratch: {
datum: void 0,
xValue: void 0,
yLowValue: 0,
yHighValue: 0,
rawLowValue: void 0,
rawHighValue: void 0
},
labelParamsScratch: {
labels: [],
datumIndex: 0,
rectX: 0,
rectY: 0,
rectWidth: 0,
rectHeight: 0,
yLowValue: 0,
yHighValue: 0,
datum: void 0
},
datumIndex: 0,
groupedDataIndex: 0,
x: 0,
width: 0,
yLow: 0,
yHigh: 0,
crisp: false
};
if (ctx.dataAggregationFilter != null) {
this.createNodeDataWithAggregation(
ctx,
xPosition,
nodeDatumParamsScratch,
itemId,
strokeWidth,
ctx.dataAggregationFilter
);
} else if (processedData.type === "ungrouped") {
this.createNodeDataSimple(ctx, xPosition, nodeDatumParamsScratch, itemId, strokeWidth, processedData);
} else {
this.createNodeDataGrouped(ctx, xPosition, nodeDatumParamsScratch, itemId, strokeWidth);
}
}
finalizeNodeData(ctx) {
if (ctx.canIncrementallyUpdate && ctx.nodeIndex < ctx.nodes.length) {
ctx.nodes.length = ctx.nodeIndex;
}
}
initializeResult(ctx) {
const { yLowKey, yHighKey } = this.properties;
const itemId = `${yLowKey}-${yHighKey}`;
const xAxis = this.getCategoryAxis();
const yAxis = this.getValueAxis();
const segments = xAxis && yAxis && this.chart?.seriesRect ? calculateSegments3(this.properties.segmentation, xAxis, yAxis, this.chart.seriesRect, this.ctx.scene) : void 0;
return {
itemId,
nodeData: ctx.nodes,
labelData: [],
scales: this.calculateScaling(),
groupScale: this.getScaling(this.ctx.seriesStateManager.getGroupScale(this)),
visible: this.visible,
styles: getItemStyles2(this.getItemStyle.bind(this)),
segments
};
}
assembleResult(ctx, result) {
for (const node of ctx.nodes) {
result.labelData.push(...node.labels);
}
return result;
}
/**
* Updates existing label data in place or creates new labels if needed.
* This avoids array allocations during incremental updates.
* Uses positional params (no destructuring) for performance in hot path.
*/
updateLabelData(ctx, params) {
const labels = params.labels;
if (!ctx.labelEnabled) {
if (labels.length > 0) {
labels.length = 0;
}
return;
}
const { xKey, yLowKey, yHighKey, xName, yLowName, yHighName, yName, legendItemName, label } = this.properties;
const barAlongX = ctx.barAlongX;
const placement = ctx.labelPlacement;
const labelPadding = ctx.labelPadding;
const rectX = params.rectX;
const rectY = params.rectY;
const rectWidth = params.rectWidth;
const rectHeight = params.rectHeight;
const yLowX = rectX + (barAlongX ? -labelPadding : rectWidth / 2);
const yLowY = rectY + (barAlongX ? rectHeight / 2 : rectHeight + labelPadding);
let yLowTextAlign;
if (placement === "outside") {
yLowTextAlign = barAlongX ? "right" : "center";
} else {
yLowTextAlign = barAlongX ? "left" : "center";
}
let yLowTextBaseline;
if (placement === "outside") {
yLowTextBaseline = barAlongX ? "middle" : "top";
} else {
yLowTextBaseline = barAlongX ? "middle" : "bottom";
}
const yHighX = rectX + (barAlongX ? rectWidth + labelPadding : rectWidth / 2);
const yHighY = rectY + (barAlongX ? rectHeight / 2 : -labelPadding);
let yHighTextAlign;
if (placement === "outside") {
yHighTextAlign = barAlongX ? "left" : "center";
} else {
yHighTextAlign = barAlongX ? "right" : "center";
}
let yHighTextBaseline;
if (placement === "outside") {
yHighTextBaseline = barAlongX ? "middle" : "bottom";
} else {
yHighTextBaseline = barAlongX ? "middle" : "top";
}
const datum = params.datum;
const yLowValue = params.yLowValue;
const yHighValue = params.yHighValue;
const datumIndex = params.datumIndex;
const labelTextParams = { datum, xKey, yLowKey, yHighKey, xName, yLowName, yHighName, yName, legendItemName };
const yDomain = this.getSeriesDomain(ChartAxisDirection24.Y).domain;
const yLowText = this.getLabelText(
yLowValue,
datum,
yLowKey,
"y",
yDomain,
label,
{ itemType: "low", value: yLowValue, ...labelTextParams }
);
const yHighText = this.getLabelText(
yHighValue,
datum,
yHighKey,
"y",
yDomain,
label,
{ itemType: "high", value: yHighValue, ...labelTextParams }
);
if (labels.length > 0 && labels[0].itemType === "low") {
const yLowLabel = labels[0];
yLowLabel.datumIndex = datumIndex;
yLowLabel.x = yLowX;
yLowLabel.y = yLowY;
yLowLabel.textAlign = yLowTextAlign;
yLowLabel.textBaseline = yLowTextBaseline;
yLowLabel.text = yLowText;
yLowLabel.datum = datum;
} else {
labels[0] = {
datumIndex,
x: yLowX,
y: yLowY,
textAlign: yLowTextAlign,
textBaseline: yLowTextBaseline,
text: yLowText,
itemType: "low",
datum,
series: this
};
}
if (labels.length > 1 && labels[1].itemType === "high") {
const yHighLabel = labels[1];
yHighLabel.datumIndex = datumIndex;
yHighLabel.x = yHighX;
yHighLabel.y = yHighY;
yHighLabel.textAlign = yHighTextAlign;
yHighLabel.textBaseline = yHighTextBaseline;
yHighLabel.text = yHighText;
yHighLabel.datum = datum;
} else {
labels[1] = {
datumIndex,
x: yHighX,
y: yHighY,
textAlign: yHighTextAlign,
textBaseline: yHighTextBaseline,
text: yHighText,
itemType: "high",
datum,
series: this
};
}
labels.length = 2;
}
nodeFactory() {
return new Rect2();
}
getStyle(ignoreStylerCallback, highlightState) {
const {
cornerRadius,
fill,
fillOpacity,
lineDash,
lineDashOffset,
stroke: stroke3,
strokeOpacity,
strokeWidth,
styler
} = this.properties;
let stylerResult = {};
if (!ignoreStylerCallback && styler) {
const stylerParams = this.makeStylerParams(highlightState);
stylerResult = this.ctx.optionsGraphService.resolvePartial(
["series", `${this.declarationOrder}`],
this.cachedCallWithContext(styler, stylerParams) ?? {},
{ pick: false }
) ?? {};
}
return {
cornerRadius: stylerResult.cornerRadius ?? cornerRadius,
fill: stylerResult.fill ?? fill,
fillOpacity: stylerResult.fillOpacity ?? fillOpacity,
lineDash: stylerResult.lineDash ?? lineDash,
lineDashOffset: stylerResult.lineDashOffset ?? lineDashOffset,
opacity: 1,
stroke: stylerResult.stroke ?? stroke3,
strokeOpacity: stylerResult.strokeOpacity ?? strokeOpacity,
strokeWidth: stylerResult.strokeWidth ?? strokeWidth
};
}
makeStylerParams(highlightStateEnum) {
const { id: seriesId } = this;
const {
cornerRadius,
fill,
fillOpacity,
lineDash,
lineDashOffset,
stroke: stroke3,
strokeOpacity,
strokeWidth,
xKey,
yLowKey,
yHighKey
} = this.properties;
const highlightState = toHighlightString3(highlightStateEnum ?? HighlightState3.None);
return {
cornerRadius,
fill,
fillOpacity,
highlightState,
lineDash,
lineDashOffset,
seriesId,
stroke: stroke3,
strokeOpacity,
strokeWidth,
xKey,
yLowKey,
yHighKey
};
}
updateDatumSelection(opts) {
const { nodeData, datumSelection } = opts;
const data = nodeData ?? [];
if (!processedDataIsAnimatable4(this.processedData)) {
return datumSelection.update(data);
}
return datumSelection.update(data, void 0, (datum) => this.getDatumId(datum));
}
getItemStyle(datumIndex, isHighlight, highlightState) {
const { properties, dataModel, processedData } = this;
const { itemStyler } = properties;
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex, highlightState);
let style = mergeDefaults8(highlightStyle, this.getStyle(datumIndex === void 0, highlightState));
if (itemStyler && dataModel != null && processedData != null && datumIndex != null) {
const xValue = dataModel.resolveKeysById(this, `xValue`, processedData)[datumIndex];
const overrides = this.cachedDatumCallback(
createDatumId5(this.getDatumId({ xValue }), isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(datumIndex, isHighlight, style);
return this.callWithContext(itemStyler, params);
}
);
if (overrides) {
style = mergeDefaults8(overrides, style);
}
}
return style;
}
makeItemStylerParams(datumIndex, isHighlight, style) {
const { id: seriesId, properties, processedData } = this;
const { xKey, yHighKey, yLowKey } = properties;
const datum = processedData.dataSources.get(seriesId)?.data[datumIndex];
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightStateString = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum,
xKey,
yHighKey,
yLowKey,
highlightState: highlightStateString,
...style,
fill
};
}
updateDatumStyles(opts) {
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
opts.datumSelection.each((node, datum) => {
if (!opts.datumSelection.isGarbage(node)) {
const highlightState = this.getHighlightState(highlightedDatum, opts.isHighlight, datum.datumIndex);
datum.style = this.getItemStyle(datum.datumIndex, opts.isHighlight, highlightState);
}
});
}
updateDatumNodes({
datumSelection,
isHighlight
}) {
const { contextNodeData } = this;
if (!contextNodeData) {
return;
}
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
const categoryAlongX = this.getCategoryDirection() === ChartAxisDirection24.X;
const fillBBox = this.getShapeFillBBox();
const series = this;
datumSelection.each(function updateRangeBarNode(rect, datum) {
const style = datum.style ?? contextNodeData.styles[series.getHighlightState(highlightedDatum, isHighlight, datum.datumIndex)];
rect.setStyleProperties(style, fillBBox);
rect.setStaticProperties(
"overlay",
style.cornerRadius ?? 0,
style.cornerRadius ?? 0,
style.cornerRadius ?? 0,
style.cornerRadius ?? 0,
categoryAlongX ? datum.width > 0 : datum.height > 0,
datum.crisp,
void 0
);
});
}
updateLabelSelection(opts) {
const labelData = this.properties.label.enabled ? opts.labelData : [];
return opts.labelSelection.update(labelData, (text2) => {
text2.pointerEvents = PointerEvents3.None;
});
}
updateLabelNodes(opts) {
const { isHighlight = false } = opts;
const params = {
xKey: this.properties.xKey,
xName: this.properties.xName ?? this.properties.xKey,
yName: this.properties.yName,
yLowKey: this.properties.yLowKey,
yLowName: this.properties.yLowName ?? this.properties.yLowKey,
yHighKey: this.properties.yHighKey,
yHighName: this.properties.yHighName ?? this.properties.yHighKey,
legendItemName: this.properties.legendItemName
};
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
opts.labelSelection.each((textNode, datum) => {
textNode.fillOpacity = this.getHighlightStyle(isHighlight, datum?.datumIndex).opacity ?? 1;
updateLabelNode3(this, textNode, params, this.properties.label, datum, isHighlight, activeHighlight);
});
}
getHighlightLabelData(labelData, highlightedItem) {
if (highlightedItem.labels?.length) {
return highlightedItem.labels;
}
return super.getHighlightLabelData(labelData, highlightedItem);
}
getTooltipContent(datumIndex) {
const { id: seriesId, dataModel, processedData, properties } = this;
const { xKey, xName, yName, yLowKey, yHighKey, yLowName, yHighName, tooltip, legendItemName } = properties;
const xAxis = this.getCategoryAxis();
const yAxis = this.getValueAxis();
if (!dataModel || !processedData || !xAxis || !yAxis)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const xValue = dataModel.resolveKeysById(this, `xValue`, processedData)[datumIndex];
const yHighValue = dataModel.resolveColumnById(this, `yHighValue`, processedData)[datumIndex];
const yLowValue = dataModel.resolveColumnById(this, `yLowValue`, processedData)[datumIndex];
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (xValue === void 0 && !allowNullKeys)
return;
const format = this.getItemStyle(datumIndex, false);
const value = `${this.getAxisValueText(yAxis, "tooltip", yLowValue, datum, yLowKey, legendItemName)} - ${this.getAxisValueText(yAxis, "tooltip", yHighValue, datum, yHighKey, legendItemName)}`;
return this.formatTooltipWithContext(
tooltip,
{
heading: this.getAxisValueText(xAxis, "tooltip", xValue, datum, xKey, legendItemName),
symbol: this.legendItemSymbol(),
data: [
{
label: yName,
fallbackLabel: `${yLowName ?? yLowKey} - ${yHighName ?? yHighKey}`,
value,
missing: _ModuleSupport112.isTooltipValueMissing(yHighValue) && _ModuleSupport112.isTooltipValueMissing(yLowValue)
}
]
},
{
seriesId,
datum,
title: yName,
xKey,
xName,
yName,
yLowKey,
yHighKey,
yLowName,
yHighName,
legendItemName,
...format
}
);
}
legendItemSymbol() {
const { fill, stroke: stroke3, strokeWidth, fillOpacity, strokeOpacity, lineDash, lineDashOffset } = this.getStyle(
false,
HighlightState3.None
);
return {
marker: {
fill,
stroke: stroke3,
fillOpacity,
strokeOpacity,
strokeWidth,
lineDash,
lineDashOffset
}
};
}
getLegendData(legendType) {
if (legendType !== "category") {
return [];
}
const { id: seriesId, visible } = this;
const { yName, yLowName, yHighName, yLowKey, yHighKey, legendItemName, showInLegend } = this.properties;
const legendItemText = legendItemName ?? yName ?? `${yLowName ?? yLowKey} - ${yHighName ?? yHighKey}`;
const itemId = `${yLowKey}-${yHighKey}`;
return [
{
legendType: "category",
id: seriesId,
itemId,
seriesId,
enabled: visible,
label: { text: `${legendItemText}` },
symbol: this.legendItemSymbol(),
legendItemName,
hideInLegend: !showInLegend
}
];
}
resetDatumAnimation(data) {
resetBarSelectionsDirect([data.datumSelection]);
}
animateEmptyUpdateReady({ datumSelection, labelSelection }) {
const fns = prepareBarAnimationFunctions(midpointStartingBarPosition(this.isVertical(), "normal"), "unknown");
motion2.fromToMotion(this.id, "datums", this.ctx.animationManager, [datumSelection], fns);
seriesLabelFadeInAnimation2(
this,
"labels",
this.ctx.animationManager,
labelSelection,
this.highlightLabelSelection
);
}
animateWaitingUpdateReady(data) {
const { datumSelection: datumSelections, labelSelection, contextData, previousContextData } = data;
const dataDiff = _ModuleSupport112.calculateDataDiff(
this.id,
datumSelections,
this.getDatumId.bind(this),
contextData,
previousContextData,
this.processedData,
this.processedDataUpdated
);
this.ctx.animationManager.stopByAnimationGroupId(this.id);
const mode = previousContextData == null ? "fade" : "normal";
const fns = prepareBarAnimationFunctions(midpointStartingBarPosition(this.isVertical(), mode), "added");
motion2.fromToMotion(
this.id,
"datums",
this.ctx.animationManager,
[datumSelections],
fns,
(_, datum) => this.getDatumId(datum),
dataDiff
);
if (dataDiff?.changed || !areScalingEqual2(contextData.groupScale, previousContextData?.groupScale)) {
seriesLabelFadeInAnimation2(
this,
"labels",
this.ctx.animationManager,
labelSelection,
this.highlightLabelSelection
);
}
}
getDatumId(datum) {
return `${datum.xValue}`;
}
isLabelEnabled() {
return this.properties.label.enabled;
}
computeFocusBounds({ datumIndex }) {
return computeBarFocusBounds4(this, this.contextNodeData?.nodeData[datumIndex]);
}
hasItemStylers() {
return this.properties.styler != null || this.properties.itemStyler != null || this.properties.label.itemStyler != null;
}
};
RangeBarSeries.className = "RangeBarSeries";
RangeBarSeries.type = "range-bar";
// packages/ag-charts-enterprise/src/series/range-bar/rangeBarSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport113 } from "ag-charts-community";
import {
boolean as boolean10,
commonSeriesOptionsDefs as commonSeriesOptionsDefs6,
constant as constant6,
number as number4,
positiveNumberNonZero as positiveNumberNonZero2,
ratio as ratio3,
required as required6,
shapeSegmentation as shapeSegmentation3,
string as string6,
undocumented as undocumented7
} from "ag-charts-core";
var { rangeBarSeriesThemeableOptionsDef } = _ModuleSupport113;
var rangeBarSeriesOptionsDef = {
...commonSeriesOptionsDefs6,
...rangeBarSeriesThemeableOptionsDef,
type: required6(constant6("range-bar")),
xKey: required6(string6),
yLowKey: required6(string6),
yHighKey: required6(string6),
xKeyAxis: string6,
yKeyAxis: string6,
xName: string6,
yName: string6,
yLowName: string6,
yHighName: string6,
legendItemName: string6,
segmentation: shapeSegmentation3,
width: positiveNumberNonZero2,
widthRatio: ratio3
};
rangeBarSeriesOptionsDef.pickOutsideVisibleMinorAxis = undocumented7(boolean10);
rangeBarSeriesOptionsDef.focusPriority = undocumented7(number4);
// packages/ag-charts-enterprise/src/series/range-bar/rangeBarThemes.ts
import "ag-charts-community";
import {
CARTESIAN_AXIS_TYPE as CARTESIAN_AXIS_TYPE8,
FILL_GRADIENT_LINEAR_DEFAULTS as FILL_GRADIENT_LINEAR_DEFAULTS3,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS4,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS3,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS3,
MULTI_SERIES_HIGHLIGHT_STYLE as MULTI_SERIES_HIGHLIGHT_STYLE3,
SEGMENTATION_DEFAULTS as SEGMENTATION_DEFAULTS3
} from "ag-charts-core";
var RANGE_BAR_SERIES_THEME = {
series: {
direction: "vertical",
fill: {
$applySwitch: [
{ $path: "type" },
{ $palette: "fill" },
["gradient", FILL_GRADIENT_LINEAR_DEFAULTS3],
["image", FILL_IMAGE_DEFAULTS4],
["pattern", FILL_PATTERN_DEFAULTS3]
]
},
stroke: { $palette: "stroke" },
strokeWidth: { $isUserOption: ["./stroke", 2, 0] },
label: {
...LABEL_BOXING_DEFAULTS3,
enabled: false,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "chartBackgroundColor" },
placement: "inside",
padding: { $isUserOption: ["./spacing", 0, 6] }
// compatibility with old `padding` property (now named `spacing`).
},
highlight: MULTI_SERIES_HIGHLIGHT_STYLE3,
segmentation: SEGMENTATION_DEFAULTS3
},
axes: {
[CARTESIAN_AXIS_TYPE8.NUMBER]: {
crosshair: { enabled: true }
}
}
};
// packages/ag-charts-enterprise/src/series/range-bar/rangeBarModule.ts
var { predictCartesianNonPrimitiveAxis: predictCartesianNonPrimitiveAxis3 } = _ModuleSupport114;
var RangeBarSeriesModule = {
type: "series",
name: "range-bar",
chartType: "cartesian",
enterprise: true,
groupable: true,
version: VERSION20,
dependencies: [CartesianChartModule6],
options: rangeBarSeriesOptionsDef,
matchingKeys: ["xKey", "yLowKey", "yHighKey", "normalizedTo"],
predictAxis: predictCartesianNonPrimitiveAxis3,
defaultAxes: DIRECTION_SWAP_AXES2,
axisKeys: { [ChartAxisDirection25.X]: "xKeyAxis", [ChartAxisDirection25.Y]: "yKeyAxis" },
axisKeysFlipped: { [ChartAxisDirection25.X]: "yKeyAxis", [ChartAxisDirection25.Y]: "xKeyAxis" },
themeTemplate: RANGE_BAR_SERIES_THEME,
create: (ctx) => new RangeBarSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/waterfall/waterfallModule.ts
import { CartesianChartModule as CartesianChartModule7, VERSION as VERSION21 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection27, DIRECTION_SWAP_AXES as DIRECTION_SWAP_AXES3 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/waterfall/waterfallSeries.ts
import { _ModuleSupport as _ModuleSupport116 } from "ag-charts-community";
import {
ChartAxisDirection as ChartAxisDirection26,
easeOut,
isContinuous,
mergeDefaults as mergeDefaults9
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/waterfall/waterfallSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport115 } from "ag-charts-community";
import { BaseProperties as BaseProperties23, PropertiesArray as PropertiesArray4, Property as Property57 } from "ag-charts-core";
var { AbstractBarSeriesProperties: AbstractBarSeriesProperties4, makeSeriesTooltip: makeSeriesTooltip7, DropShadow: DropShadow3, Label: Label4 } = _ModuleSupport115;
var WaterfallSeriesTotal = class extends BaseProperties23 {
};
__decorateClass([
Property57
], WaterfallSeriesTotal.prototype, "totalType", 2);
__decorateClass([
Property57
], WaterfallSeriesTotal.prototype, "index", 2);
__decorateClass([
Property57
], WaterfallSeriesTotal.prototype, "axisLabel", 2);
var WaterfallSeriesItemTooltip = class extends BaseProperties23 {
};
__decorateClass([
Property57
], WaterfallSeriesItemTooltip.prototype, "renderer", 2);
var WaterfallSeriesLabel = class extends Label4 {
constructor() {
super(...arguments);
this.placement = "outside-end";
this.spacing = 0;
}
};
__decorateClass([
Property57
], WaterfallSeriesLabel.prototype, "placement", 2);
__decorateClass([
Property57
], WaterfallSeriesLabel.prototype, "spacing", 2);
var WaterfallSeriesItem = class extends BaseProperties23 {
constructor() {
super(...arguments);
this.fill = "#c16068";
this.stroke = "#c16068";
this.fillOpacity = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.strokeWidth = 1;
this.cornerRadius = 0;
this.shadow = new DropShadow3().set({ enabled: false });
this.label = new WaterfallSeriesLabel();
this.tooltip = new WaterfallSeriesItemTooltip();
}
};
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "name", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "fill", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "stroke", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "fillOpacity", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "strokeOpacity", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "lineDash", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "lineDashOffset", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "strokeWidth", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "cornerRadius", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "itemStyler", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "shadow", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "label", 2);
__decorateClass([
Property57
], WaterfallSeriesItem.prototype, "tooltip", 2);
var WaterfallSeriesConnectorLine = class extends BaseProperties23 {
constructor() {
super(...arguments);
this.enabled = true;
this.stroke = "black";
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.strokeWidth = 2;
}
};
__decorateClass([
Property57
], WaterfallSeriesConnectorLine.prototype, "enabled", 2);
__decorateClass([
Property57
], WaterfallSeriesConnectorLine.prototype, "stroke", 2);
__decorateClass([
Property57
], WaterfallSeriesConnectorLine.prototype, "strokeOpacity", 2);
__decorateClass([
Property57
], WaterfallSeriesConnectorLine.prototype, "lineDash", 2);
__decorateClass([
Property57
], WaterfallSeriesConnectorLine.prototype, "lineDashOffset", 2);
__decorateClass([
Property57
], WaterfallSeriesConnectorLine.prototype, "strokeWidth", 2);
var WaterfallSeriesItems = class extends BaseProperties23 {
constructor() {
super(...arguments);
this.positive = new WaterfallSeriesItem();
this.negative = new WaterfallSeriesItem();
this.total = new WaterfallSeriesItem();
}
};
__decorateClass([
Property57
], WaterfallSeriesItems.prototype, "positive", 2);
__decorateClass([
Property57
], WaterfallSeriesItems.prototype, "negative", 2);
__decorateClass([
Property57
], WaterfallSeriesItems.prototype, "total", 2);
var WaterfallSeriesProperties = class extends AbstractBarSeriesProperties4 {
constructor() {
super(...arguments);
this.item = new WaterfallSeriesItems();
this.totals = new PropertiesArray4(WaterfallSeriesTotal);
this.line = new WaterfallSeriesConnectorLine();
this.tooltip = makeSeriesTooltip7();
}
getStyle(itemType) {
const { fillOpacity, strokeWidth, strokeOpacity, fill, stroke: stroke3, lineDash, lineDashOffset, cornerRadius } = this.item[itemType === "subtotal" ? "total" : itemType];
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
cornerRadius,
opacity: 1
};
}
};
__decorateClass([
Property57
], WaterfallSeriesProperties.prototype, "xKey", 2);
__decorateClass([
Property57
], WaterfallSeriesProperties.prototype, "yKey", 2);
__decorateClass([
Property57
], WaterfallSeriesProperties.prototype, "xName", 2);
__decorateClass([
Property57
], WaterfallSeriesProperties.prototype, "yName", 2);
__decorateClass([
Property57
], WaterfallSeriesProperties.prototype, "item", 2);
__decorateClass([
Property57
], WaterfallSeriesProperties.prototype, "totals", 2);
__decorateClass([
Property57
], WaterfallSeriesProperties.prototype, "line", 2);
__decorateClass([
Property57
], WaterfallSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/waterfall/waterfallSeries.ts
var {
adjustLabelPlacement,
SeriesNodePickMode: SeriesNodePickMode5,
fixNumericExtent: fixNumericExtent6,
valueProperty: valueProperty8,
keyProperty: keyProperty6,
accumulativeValueProperty,
trailingAccumulatedValueProperty,
createDatumId: createDatumId6,
checkCrisp: checkCrisp2,
updateLabelNode: updateLabelNode4,
prepareBarAnimationFunctions: prepareBarAnimationFunctions2,
collapsedStartingBarPosition,
resetBarSelectionsDirect: resetBarSelectionsDirect2,
resetBarSelectionsFn: resetBarSelectionsFn2,
seriesLabelFadeInAnimation: seriesLabelFadeInAnimation3,
resetLabelFn: resetLabelFn3,
animationValidation: animationValidation5,
DEFAULT_CARTESIAN_DIRECTION_KEYS: DEFAULT_CARTESIAN_DIRECTION_KEYS2,
DEFAULT_CARTESIAN_DIRECTION_NAMES: DEFAULT_CARTESIAN_DIRECTION_NAMES2,
computeBarFocusBounds: computeBarFocusBounds5,
Rect: Rect3,
motion: motion3,
getItemStylesPerItemId: getItemStylesPerItemId2,
DataSet,
processedDataIsAnimatable: processedDataIsAnimatable5,
upsertNodeDatum: upsertNodeDatum4
} = _ModuleSupport116;
var WaterfallSeries = class extends _ModuleSupport116.AbstractBarSeries {
constructor(moduleCtx) {
super({
moduleCtx,
propertyKeys: DEFAULT_CARTESIAN_DIRECTION_KEYS2,
propertyNames: DEFAULT_CARTESIAN_DIRECTION_NAMES2,
categoryKey: void 0,
pickModes: [SeriesNodePickMode5.NEAREST_NODE, SeriesNodePickMode5.EXACT_SHAPE_MATCH],
pathsPerSeries: ["connector"],
pathsZIndexSubOrderOffset: [-1, -1],
animationResetFns: {
datum: resetBarSelectionsFn2,
label: resetLabelFn3
}
});
this.properties = new WaterfallSeriesProperties();
this.seriesItemTypes = /* @__PURE__ */ new Set(["positive", "negative", "total"]);
}
async processData(dataController) {
const { xKey, yKey, totals } = this.properties;
const { data } = this;
if (!this.visible)
return;
const positiveNumber11 = (v) => isContinuous(v) && Number(v) >= 0;
const negativeNumber = (v) => isContinuous(v) && Number(v) >= 0;
const totalTypeValue = (v) => v === "total" || v === "subtotal";
const propertyDefinition = { missingValue: void 0, invalidValue: void 0 };
const dataWithTotals = [];
const totalsMap = totals.reduce((result, total) => {
const totalsAtIndex = result.get(total.index);
if (totalsAtIndex) {
totalsAtIndex.push(total);
} else {
result.set(total.index, [total]);
}
return result;
}, /* @__PURE__ */ new Map());
for (const [i, datum] of data?.data.entries() ?? []) {
dataWithTotals.push(datum);
const totalsAtIndex = totalsMap.get(i);
if (totalsAtIndex) {
for (const total of totalsAtIndex) {
dataWithTotals.push({ ...total.toJson(), [xKey]: total.axisLabel });
}
}
}
const extraProps = [];
if (!this.ctx.animationManager.isSkipped()) {
extraProps.push(animationValidation5());
}
const xScale = this.getCategoryAxis()?.scale;
const yScale = this.getValueAxis()?.scale;
const { isContinuousX, xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
const allowNullKey = this.properties.allowNullKeys ?? false;
const { processedData } = await this.requestDataModel(
dataController,
DataSet.wrap(dataWithTotals),
{
props: [
keyProperty6(xKey, xScaleType, { id: `xValue`, allowNullKey }),
accumulativeValueProperty(yKey, yScaleType, {
...propertyDefinition,
id: `yCurrent`
}),
accumulativeValueProperty(yKey, yScaleType, {
...propertyDefinition,
missingValue: 0,
id: `yCurrentTotal`
}),
accumulativeValueProperty(yKey, yScaleType, {
...propertyDefinition,
id: `yCurrentPositive`,
validation: positiveNumber11
}),
accumulativeValueProperty(yKey, yScaleType, {
...propertyDefinition,
id: `yCurrentNegative`,
validation: negativeNumber
}),
trailingAccumulatedValueProperty(yKey, yScaleType, {
...propertyDefinition,
id: `yPrevious`
}),
valueProperty8(yKey, yScaleType, { id: `yRaw` }),
// Raw value pass-through.
valueProperty8("totalType", "category", {
id: `totalTypeValue`,
missingValue: void 0,
validation: totalTypeValue
}),
...isContinuousX ? [_ModuleSupport116.SMALLEST_KEY_INTERVAL, _ModuleSupport116.LARGEST_KEY_INTERVAL] : [],
...extraProps
]
}
);
this.smallestDataInterval = processedData.reduced?.smallestKeyInterval;
this.largestDataInterval = processedData.reduced?.largestKeyInterval;
this.updateSeriesItemTypes();
this.animationState.transition("updateData");
}
getSeriesDomain(direction) {
const { processedData, dataModel } = this;
if (!processedData || !dataModel)
return { domain: [] };
const {
keys: [keys],
values
} = processedData.domain;
if (direction === this.getCategoryDirection()) {
const keyDef = dataModel.resolveProcessedDataDefById(this, `xValue`);
if (keyDef?.def.type === "key" && keyDef?.def.valueType === "category") {
const sortMetadata = dataModel.getKeySortMetadata(this, "xValue", processedData);
return { domain: keys, sortMetadata };
}
const isDirectionY = direction === ChartAxisDirection26.Y;
const isReversed = this.getCategoryAxis().isReversed();
return { domain: this.padBandExtent(keys, isReversed !== isDirectionY) };
} else {
const yCurrIndex = dataModel.resolveProcessedDataIndexById(this, "yCurrent");
const yExtent = values[yCurrIndex];
const fixedYExtent = [Math.min(0, yExtent[0]), Math.max(0, yExtent[1])];
return { domain: fixNumericExtent6(fixedYExtent) };
}
}
getSeriesRange() {
return [Number.NaN, Number.NaN];
}
populateNodeData(ctx) {
let trailingSubtotal = 0;
const paramsScratch = {
datumIndex: 0,
datum: void 0,
xDatum: void 0,
value: void 0,
cumulativeValue: void 0,
trailingValue: void 0,
datumType: void 0
};
for (const [datumIndex, datum] of ctx.rawData.entries()) {
const datumType = ctx.totalTypeValues[datumIndex];
const isSubtotal = this.isSubtotal(datumType);
const isTotal = this.isTotal(datumType);
const isTotalOrSubtotal = isTotal || isSubtotal;
const xDatum = ctx.xValues[datumIndex];
if (xDatum === void 0 && !this.properties.allowNullKeys)
continue;
const rawValue = ctx.yRawValues[datumIndex];
const { cumulativeValue, trailingValue } = this.computeWaterfallValues(
ctx,
datumIndex,
isTotal,
isSubtotal,
trailingSubtotal
);
if (isTotalOrSubtotal) {
trailingSubtotal = cumulativeValue ?? 0;
}
const value = this.computeDisplayValue(isTotal, isSubtotal, rawValue, cumulativeValue, trailingValue);
paramsScratch.datumIndex = datumIndex;
paramsScratch.datum = datum;
paramsScratch.xDatum = xDatum;
paramsScratch.value = value;
paramsScratch.cumulativeValue = cumulativeValue;
paramsScratch.trailingValue = trailingValue;
paramsScratch.datumType = datumType;
const nodeDatum = upsertNodeDatum4(
ctx,
paramsScratch,
(c, p) => this.createNodeDatum(c, p),
(c, n, p) => this.updateNodeDatum(c, n, p)
);
if (nodeDatum) {
const pathPoint = this.createPointDatum(
ctx,
nodeDatum,
cumulativeValue,
trailingValue,
isTotalOrSubtotal
);
ctx.pointData.push(pathPoint);
}
}
}
finalizeNodeData(ctx) {
if (ctx.nodeIndex < ctx.nodes.length) {
ctx.nodes.length = ctx.nodeIndex;
}
}
initializeResult(ctx) {
return {
itemId: this.properties.yKey,
nodeData: ctx.nodes,
labelData: ctx.nodes,
pointData: [],
scales: this.calculateScaling(),
groupScale: this.getScaling(this.ctx.seriesStateManager.getGroupScale(this)),
visible: this.visible,
styles: getItemStylesPerItemId2(this.getItemStyle.bind(this), "total", "subtotal", "positive", "negative")
};
}
assembleResult(ctx, result) {
const connectorLinesEnabled = this.properties.line.enabled;
if (ctx.yCurrValues != null && connectorLinesEnabled) {
result.pointData = ctx.pointData;
}
return result;
}
createNodeDatumContext(xAxis, yAxis) {
const { dataModel, processedData } = this;
if (!dataModel || !processedData || processedData.type !== "ungrouped")
return void 0;
const categoryAxis = this.getCategoryAxis();
const valueAxis = this.getValueAxis();
if (!categoryAxis || !valueAxis)
return void 0;
const xScale = xAxis.scale;
const yScale = yAxis.scale;
const xValues = dataModel.resolveKeysById(this, `xValue`, processedData);
const yRawValues = dataModel.resolveColumnById(this, `yRaw`, processedData);
const totalTypeValues = dataModel.resolveColumnById(
this,
`totalTypeValue`,
processedData
);
const yCurrValues = dataModel.resolveColumnById(this, "yCurrent", processedData);
const yPrevValues = dataModel.resolveColumnById(this, "yPrevious", processedData);
const yCurrTotalValues = dataModel.resolveColumnById(this, "yCurrentTotal", processedData);
const rawData = processedData.dataSources.get(this.id)?.data ?? [];
const { xKey, yKey, xName, yName, line } = this.properties;
const { contextNodeData } = this;
const animationEnabled = !this.ctx.animationManager.isSkipped();
const canIncrementallyUpdate = contextNodeData?.nodeData != null && processedData.changeDescription != null;
const { barWidth } = this.getBarDimensions();
return {
xAxis,
yAxis,
xScale,
yScale,
categoryAxis,
valueAxis,
barAlongX: this.getBarDirection() === ChartAxisDirection26.X,
barWidth,
categoryAxisReversed: categoryAxis.isReversed(),
valueAxisReversed: valueAxis.isReversed(),
crisp: checkCrisp2(
categoryAxis.scale,
categoryAxis.visibleRange,
this.smallestDataInterval,
this.largestDataInterval
),
animationEnabled,
xKey,
yKey,
xName,
yName,
lineStrokeWidth: line.strokeWidth,
yDomain: this.getSeriesDomain(ChartAxisDirection26.Y).domain,
xValues,
rawData,
yRawValues,
totalTypeValues,
yCurrValues,
yPrevValues,
yCurrTotalValues,
canIncrementallyUpdate,
nodes: canIncrementallyUpdate ? contextNodeData.nodeData : [],
nodeIndex: 0,
pointData: []
};
}
computeWaterfallValues(ctx, datumIndex, isTotal, isSubtotal, trailingSubtotal) {
if (isTotal || isSubtotal) {
return {
cumulativeValue: ctx.yCurrTotalValues[datumIndex],
trailingValue: isSubtotal ? trailingSubtotal : 0
};
}
return {
cumulativeValue: ctx.yCurrValues[datumIndex],
trailingValue: ctx.yPrevValues[datumIndex]
};
}
computeDisplayValue(isTotal, isSubtotal, rawValue, cumulativeValue, trailingValue) {
if (isTotal) {
return cumulativeValue;
}
if (isSubtotal) {
return (cumulativeValue ?? 0) - (trailingValue ?? 0);
}
return rawValue;
}
/**
* Creates a skeleton WaterfallNodeDatum with minimal required fields.
* The node will be populated by updateNodeDatum.
*/
createSkeletonNodeDatum(ctx, params) {
const { xKey, yKey, crisp } = ctx;
const { datumIndex, datum, xDatum, value, cumulativeValue, datumType } = params;
const isPositive = (value ?? 0) >= 0;
const seriesItemType = this.getSeriesItemType(isPositive, datumType);
return {
index: datumIndex,
series: this,
itemType: seriesItemType,
datum,
datumIndex,
cumulativeValue: cumulativeValue ?? 0,
xValue: xDatum,
yValue: value,
yKey,
xKey,
x: 0,
y: 0,
width: 0,
height: 0,
midPoint: { x: 0, y: 0 },
crisp,
label: { text: "", x: 0, y: 0, textAlign: "center", textBaseline: "middle" }
};
}
/**
* Updates an existing WaterfallNodeDatum in-place.
* This is more efficient than recreating the entire node when only data values change.
*/
updateNodeDatum(ctx, node, params) {
const { xScale, yScale, barAlongX, barWidth, valueAxisReversed, xKey, yKey, xName, yName, yDomain, crisp } = ctx;
const { datumIndex, datum, xDatum, value, cumulativeValue, trailingValue, datumType } = params;
const mutableNode = node;
const x = Math.round(xScale.convert(xDatum));
if (!Number.isFinite(x))
return;
const isPositive = (value ?? 0) >= 0;
const seriesItemType = this.getSeriesItemType(isPositive, datumType);
const { strokeWidth, label } = this.getItemConfig(seriesItemType);
const currY = Math.round(yScale.convert(cumulativeValue));
const trailY = Math.round(yScale.convert(trailingValue));
const y = isPositive ? currY : trailY;
const bottomY = isPositive ? trailY : currY;
const barHeight = Math.max(strokeWidth, Math.abs(bottomY - y));
const rectX = barAlongX ? Math.min(y, bottomY) : x;
const rectY = barAlongX ? x : Math.min(y, bottomY);
const rectWidth = barAlongX ? barHeight : barWidth;
const rectHeight = barAlongX ? barWidth : barHeight;
mutableNode.index = datumIndex;
mutableNode.itemType = seriesItemType;
mutableNode.datum = datum;
mutableNode.datumIndex = datumIndex;
mutableNode.cumulativeValue = cumulativeValue ?? 0;
mutableNode.xValue = xDatum;
mutableNode.yValue = value;
mutableNode.x = rectX;
mutableNode.y = rectY;
mutableNode.width = rectWidth;
mutableNode.height = rectHeight;
mutableNode.crisp = crisp;
if (mutableNode.midPoint) {
mutableNode.midPoint.x = rectX + rectWidth / 2;
mutableNode.midPoint.y = rectY + rectHeight / 2;
} else {
mutableNode.midPoint = { x: rectX + rectWidth / 2, y: rectY + rectHeight / 2 };
}
if (label.enabled) {
const itemType = seriesItemType === "subtotal" ? "total" : seriesItemType;
const labelText = this.getLabelText(
value,
datum,
yKey,
"y",
yDomain,
label,
{
itemType,
value,
datum,
xKey,
yKey,
xName,
yName
}
);
const spacing = label.spacing + (typeof label.padding === "number" ? label.padding : 0);
const labelPlacement = adjustLabelPlacement({
isUpward: (value ?? -1) >= 0 !== valueAxisReversed,
isVertical: !barAlongX,
placement: label.placement,
spacing,
rect: { x: rectX, y: rectY, width: rectWidth, height: rectHeight }
});
mutableNode.label.text = labelText;
mutableNode.label.x = labelPlacement.x;
mutableNode.label.y = labelPlacement.y;
mutableNode.label.textAlign = labelPlacement.textAlign;
mutableNode.label.textBaseline = labelPlacement.textBaseline;
} else {
mutableNode.label.text = "";
}
}
/**
* Creates a WaterfallNodeDatum for a single data point.
* Creates a skeleton node and uses updateNodeDatum to populate it.
*/
createNodeDatum(ctx, params) {
const node = this.createSkeletonNodeDatum(ctx, params);
this.updateNodeDatum(ctx, node, params);
return node;
}
createPointDatum(ctx, nodeDatum, cumulativeValue, trailingValue, isTotalOrSubtotal) {
const { yScale, barAlongX, categoryAxisReversed, lineStrokeWidth } = ctx;
const currY = Math.round(yScale.convert(cumulativeValue));
const trailY = Math.round(yScale.convert(trailingValue));
const pointY = isTotalOrSubtotal ? currY : trailY;
const pixelAlignmentOffset = Math.floor(lineStrokeWidth) % 2 / 2;
const startY = categoryAxisReversed ? currY : pointY;
const stopY = categoryAxisReversed ? pointY : currY;
const rect = { x: nodeDatum.x, y: nodeDatum.y, width: nodeDatum.width, height: nodeDatum.height };
let startCoordinates;
let stopCoordinates;
if (barAlongX) {
startCoordinates = {
x: startY + pixelAlignmentOffset,
y: rect.y
};
stopCoordinates = {
x: stopY + pixelAlignmentOffset,
y: rect.y + rect.height
};
} else {
startCoordinates = {
x: rect.x,
y: startY + pixelAlignmentOffset
};
stopCoordinates = {
x: rect.x + rect.width,
y: stopY + pixelAlignmentOffset
};
}
return {
// lineTo
x: categoryAxisReversed ? stopCoordinates.x : startCoordinates.x,
y: categoryAxisReversed ? stopCoordinates.y : startCoordinates.y,
// moveTo
x2: categoryAxisReversed ? startCoordinates.x : stopCoordinates.x,
y2: categoryAxisReversed ? startCoordinates.y : stopCoordinates.y,
size: 0
};
}
updateSeriesItemTypes() {
const { dataModel, seriesItemTypes, processedData } = this;
if (!dataModel || !processedData) {
return;
}
seriesItemTypes.clear();
const yPositiveIndex = dataModel.resolveProcessedDataIndexById(this, "yCurrentPositive");
const yNegativeIndex = dataModel.resolveProcessedDataIndexById(this, "yCurrentNegative");
const totalTypeIndex = dataModel.resolveProcessedDataIndexById(this, `totalTypeValue`);
const positiveDomain = processedData.domain.values[yPositiveIndex] ?? [];
const negativeDomain = processedData.domain.values[yNegativeIndex] ?? [];
if (positiveDomain.length > 0) {
seriesItemTypes.add("positive");
}
if (negativeDomain.length > 0) {
seriesItemTypes.add("negative");
}
const itemTypes = processedData?.domain.values[totalTypeIndex];
if (!itemTypes) {
return;
}
for (const type of itemTypes) {
if (type === "total" || type === "subtotal") {
seriesItemTypes.add("total");
}
}
}
isSubtotal(datumType) {
return datumType === "subtotal";
}
isTotal(datumType) {
return datumType === "total";
}
nodeFactory() {
return new Rect3();
}
getSeriesItemType(isPositive, datumType) {
return datumType ?? (isPositive ? "positive" : "negative");
}
getItemConfig(seriesItemType) {
switch (seriesItemType) {
case "positive": {
return this.properties.item.positive;
}
case "negative": {
return this.properties.item.negative;
}
case "subtotal":
case "total": {
return this.properties.item.total;
}
}
}
updateDatumSelection(opts) {
const { nodeData, datumSelection } = opts;
const data = nodeData ?? [];
if (!processedDataIsAnimatable5(this.processedData)) {
return datumSelection.update(data);
}
return datumSelection.update(data, void 0, (datum) => createDatumId6(datum.datumIndex));
}
getItemStyle(nodeDatum, isHighlight, highlightState, itemType = "total") {
const { properties } = this;
const { datumIndex = 0, datum } = nodeDatum ?? {};
const propertyItemId = itemType === "subtotal" ? "total" : itemType;
const item = properties.item[propertyItemId];
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex, highlightState);
const baseStyle = mergeDefaults9(highlightStyle, properties.getStyle(itemType));
const { itemStyler } = item;
let style = baseStyle;
if (itemStyler != null && nodeDatum != null) {
const overrides = this.cachedDatumCallback(
createDatumId6(datumIndex, isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(itemType, datumIndex, datum, isHighlight, style);
return this.ctx.optionsGraphService.resolvePartial(
["series", `${this.declarationOrder}`, "item", propertyItemId],
this.callWithContext(itemStyler, params)
);
}
);
if (overrides) {
style = mergeDefaults9(overrides, style);
}
}
return style;
}
makeItemStylerParams(itemType, datumIndex, datum, isHighlight, style) {
const { id: seriesId, properties } = this;
const { xKey, yKey } = properties;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightStateString = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
itemType,
datum,
xKey,
yKey,
highlightState: highlightStateString,
...style,
fill
};
}
updateDatumStyles({
datumSelection,
isHighlight
}) {
datumSelection.each((_, datum) => {
datum.style = this.getItemStyle(datum, isHighlight, void 0, datum.itemType);
});
}
updateDatumNodes({
datumSelection,
isHighlight
}) {
const { contextNodeData } = this;
if (!contextNodeData) {
return;
}
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
const categoryAlongX = this.getCategoryDirection() === ChartAxisDirection26.X;
const fillBBox = this.getShapeFillBBox();
datumSelection.each((rect, datum) => {
const style = datum.style ?? contextNodeData.styles[datum.itemType][this.getHighlightState(highlightedDatum, isHighlight, datum.datumIndex)];
rect.setStyleProperties(style, fillBBox);
rect.cornerRadius = style.cornerRadius ?? 0;
rect.visible = categoryAlongX ? datum.width > 0 : datum.height > 0;
rect.crisp = datum.crisp;
});
}
updateLabelSelection(opts) {
const { labelData, labelSelection } = opts;
if (labelData.length === 0) {
return labelSelection.update([]);
}
const data = labelData.filter((labelDatum) => {
const { label } = this.getItemConfig(labelDatum.itemType);
return label.enabled;
});
return labelSelection.update(data);
}
updateLabelNodes({
labelSelection,
isHighlight
}) {
const params = {
itemType: "positive",
xKey: this.properties.xKey,
xName: this.properties.xName ?? this.properties.xName,
yKey: this.properties.yKey,
yName: this.properties.yName ?? this.properties.yName
};
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
labelSelection.each((textNode, datum) => {
params.itemType = datum.itemType;
const styleOpacity = this.getHighlightStyle(isHighlight, datum.datumIndex)?.opacity ?? 1;
textNode.visible = true;
textNode.fillOpacity = styleOpacity;
const label = this.getItemConfig(datum.itemType).label;
updateLabelNode4(this, textNode, params, label, datum.label, isHighlight, activeHighlight);
});
}
getTooltipContent(datumIndex) {
const { id: seriesId, dataModel, processedData, properties } = this;
const { xKey, xName, yKey, yName, tooltip, legendItemName } = properties;
const xAxis = this.getCategoryAxis();
const yAxis = this.getValueAxis();
if (!dataModel || !processedData || !xAxis || !yAxis)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const xValue = dataModel.resolveKeysById(this, `xValue`, processedData)[datumIndex];
const yValue = dataModel.resolveColumnById(this, `yRaw`, processedData)[datumIndex];
const yCurrTotalValues = dataModel.resolveColumnById(this, "yCurrentTotal", processedData);
const totalTypeValues = dataModel.resolveColumnById(
this,
`totalTypeValue`,
processedData
);
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (xValue === void 0 && !allowNullKeys)
return;
const datumType = totalTypeValues[datumIndex];
const isPositive = (yValue ?? 0) >= 0;
const seriesItemType = this.getSeriesItemType(isPositive, datumType);
let total;
if (this.isTotal(datumType)) {
total = yCurrTotalValues[datumIndex];
} else if (this.isSubtotal(datumType)) {
total = yCurrTotalValues[datumIndex];
for (let previousIndex = datumIndex - 1; previousIndex >= 0; previousIndex -= 1) {
if (this.isSubtotal(totalTypeValues[previousIndex])) {
total = total - yCurrTotalValues[previousIndex];
break;
}
}
} else {
total = yValue;
}
const nodeDatum = this.contextNodeData?.nodeData?.[datumIndex];
const format = this.getItemStyle(nodeDatum, false, void 0, nodeDatum?.itemType);
return this.formatTooltipWithContext(
tooltip,
{
heading: this.getAxisValueText(xAxis, "tooltip", xValue, datum, xKey, legendItemName),
symbol: this.legendItemSymbol(seriesItemType),
data: [
{
label: yName,
fallbackLabel: yKey,
value: this.getAxisValueText(yAxis, "tooltip", total, datum, yKey, legendItemName),
missing: _ModuleSupport116.isTooltipValueMissing(total)
}
]
},
{ seriesId, datum, title: yName, itemType: seriesItemType, xKey, xName, yKey, yName, ...format }
);
}
legendItemSymbol(item) {
const { fill, stroke: stroke3, fillOpacity, strokeOpacity, strokeWidth, lineDash, lineDashOffset } = this.getItemConfig(item);
return {
marker: {
fill,
stroke: stroke3,
fillOpacity,
strokeOpacity,
strokeWidth,
lineDash,
lineDashOffset
}
};
}
getLegendData(legendType) {
if (legendType !== "category") {
return [];
}
const { id, seriesItemTypes } = this;
const legendData = [];
const capitalise = (text2) => text2.charAt(0).toUpperCase() + text2.substring(1);
const { showInLegend } = this.properties;
for (const item of seriesItemTypes) {
const { name } = this.getItemConfig(item);
legendData.push({
legendType: "category",
id,
itemId: createDatumId6(item),
seriesId: id,
enabled: true,
label: { text: name ?? capitalise(item) },
symbol: this.legendItemSymbol(item),
hideInLegend: !showInLegend,
isFixed: true
});
}
return legendData;
}
toggleSeriesItem() {
}
resetDatumAnimation(data) {
resetBarSelectionsDirect2([data.datumSelection]);
}
animateEmptyUpdateReady(opts) {
const { datumSelection, labelSelection, contextData } = opts;
const fns = prepareBarAnimationFunctions2(
collapsedStartingBarPosition(this.isVertical(), this.axes, "normal"),
"unknown"
);
motion3.fromToMotion(this.id, "datums", this.ctx.animationManager, [datumSelection], fns);
seriesLabelFadeInAnimation3(this, "labels", this.ctx.animationManager, labelSelection);
const { pointData } = contextData;
if (!pointData)
return;
if (this.isVertical()) {
this.animateConnectorLinesVertical(opts);
} else {
this.animateConnectorLinesHorizontal(opts);
}
}
animateConnectorLinesHorizontal(opts) {
const { pointData = [] } = opts.contextData;
const [lineNode] = opts.paths;
const { path: linePath } = lineNode;
this.updateLineNode(lineNode);
const valueAxis = this.getValueAxis();
const valueAxisReversed = valueAxis?.isReversed();
const compare = valueAxisReversed ? (v, v2) => v < v2 : (v, v2) => v > v2;
const startX = valueAxis?.scale.convert(0);
const endX = pointData.reduce(
(end, point) => {
if (compare(point.x, end)) {
end = point.x;
}
return end;
},
valueAxisReversed ? Infinity : 0
);
const scale = (value, start1, end1, start2, end2) => {
return (value - start1) / (end1 - start1) * (end2 - start2) + start2;
};
this.ctx.animationManager.animate({
id: `${this.id}_connectors`,
groupId: this.id,
phase: "initial",
from: startX,
to: endX,
ease: easeOut,
collapsable: false,
onUpdate(pointX) {
linePath.clear(true);
for (const [index, point] of pointData.entries()) {
const x = scale(pointX, startX, endX, startX, point.x);
const x2 = scale(pointX, startX, endX, startX, point.x2);
if (index !== 0) {
linePath.lineTo(x, point.y);
}
linePath.moveTo(x2, point.y2);
}
lineNode.checkPathDirty();
},
onStop: () => this.resetConnectorLinesPath(opts)
});
}
animateConnectorLinesVertical(opts) {
const { pointData = [] } = opts.contextData;
const [lineNode] = opts.paths;
const { path: linePath } = lineNode;
this.updateLineNode(lineNode);
const valueAxis = this.getValueAxis();
const valueAxisReversed = valueAxis?.isReversed();
const compare = valueAxisReversed ? (v, v2) => v > v2 : (v, v2) => v < v2;
const startY = valueAxis?.scale.convert(0);
const endY = pointData.reduce(
(end, point) => {
if (compare(point.y, end)) {
end = point.y;
}
return end;
},
valueAxisReversed ? 0 : Infinity
);
const scale = (value, start1, end1, start2, end2) => {
return (value - start1) / (end1 - start1) * (end2 - start2) + start2;
};
this.ctx.animationManager.animate({
id: `${this.id}_connectors`,
groupId: this.id,
phase: "initial",
from: startY,
to: endY,
ease: easeOut,
collapsable: false,
onUpdate(pointY) {
linePath.clear(true);
for (const [index, point] of pointData.entries()) {
const y = scale(pointY, startY, endY, startY, point.y);
const y2 = scale(pointY, startY, endY, startY, point.y2);
if (index !== 0) {
linePath.lineTo(point.x, y);
}
linePath.moveTo(point.x2, y2);
}
lineNode.checkPathDirty();
},
onStop: () => this.resetConnectorLinesPath(opts)
});
}
animateReadyResize(data) {
super.animateReadyResize(data);
this.resetConnectorLinesPath(data);
}
updatePaths(opts) {
this.resetConnectorLinesPath({ contextData: opts.contextData, paths: opts.paths });
}
resetConnectorLinesPath({
contextData,
paths
}) {
if (paths.length === 0) {
return;
}
const [lineNode] = paths;
this.updateLineNode(lineNode);
const { path: linePath } = lineNode;
linePath.clear(true);
const { pointData } = contextData;
if (!pointData) {
return;
}
for (const [index, point] of pointData.entries()) {
if (index !== 0) {
linePath.lineTo(point.x, point.y);
}
linePath.moveTo(point.x2, point.y2);
}
lineNode.checkPathDirty();
}
updateLineNode(lineNode) {
const { stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = this.properties.line;
lineNode.setProperties({
fill: void 0,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
lineJoin: "round",
pointerEvents: _ModuleSupport116.PointerEvents.None
});
}
isLabelEnabled() {
const { positive, negative, total } = this.properties.item;
return positive.label.enabled || negative.label.enabled || total.label.enabled;
}
computeFocusBounds({ datumIndex }) {
return computeBarFocusBounds5(this, this.contextNodeData?.nodeData[datumIndex]);
}
hasItemStylers() {
const { positive, negative, total } = this.properties.item;
return positive.itemStyler != null || positive.label.itemStyler != null || negative.itemStyler != null || negative.label.itemStyler != null || total.itemStyler != null || total.label.itemStyler != null;
}
};
WaterfallSeries.className = "WaterfallSeries";
WaterfallSeries.type = "waterfall";
// packages/ag-charts-enterprise/src/series/waterfall/waterfallSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport117 } from "ag-charts-community";
import {
arrayOfDefs,
commonSeriesOptionsDefs as commonSeriesOptionsDefs7,
constant as constant7,
positiveNumber as positiveNumber4,
positiveNumberNonZero as positiveNumberNonZero3,
required as required7,
string as string7,
union
} from "ag-charts-core";
var { waterfallSeriesThemeableOptionsDef } = _ModuleSupport117;
var waterfallSeriesOptionsDef = {
...waterfallSeriesThemeableOptionsDef,
...commonSeriesOptionsDefs7,
type: required7(constant7("waterfall")),
xKey: required7(string7),
yKey: required7(string7),
xKeyAxis: string7,
yKeyAxis: string7,
xName: string7,
yName: string7,
totals: arrayOfDefs(
{
totalType: required7(union("total", "subtotal")),
index: required7(positiveNumber4),
axisLabel: required7(string7)
},
"a total definition options array"
),
width: positiveNumberNonZero3
};
// packages/ag-charts-enterprise/src/series/waterfall/waterfallThemes.ts
import "ag-charts-community";
import {
FILL_GRADIENT_LINEAR_KEYED_DEFAULTS as FILL_GRADIENT_LINEAR_KEYED_DEFAULTS2,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS5,
FILL_PATTERN_KEYED_DEFAULTS as FILL_PATTERN_KEYED_DEFAULTS2,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS4,
SINGLE_SERIES_HIGHLIGHT_STYLE
} from "ag-charts-core";
function itemTheme2(key, index) {
return {
fill: {
$applySwitch: [
{ $path: "type" },
{
$if: [
{ $eq: [{ $palette: "type" }, "user-indexed"] },
{ $path: [`/${index}`, { $palette: "fill" }, { $palette: "fills" }] },
{ $palette: `${key}.fill` }
]
},
["gradient", FILL_GRADIENT_LINEAR_KEYED_DEFAULTS2(key)],
["image", FILL_IMAGE_DEFAULTS5],
["pattern", FILL_PATTERN_KEYED_DEFAULTS2(key)]
]
},
stroke: { $palette: `${key}.stroke` },
strokeWidth: { $isUserOption: ["./stroke", 2, 0] },
label: {
...LABEL_BOXING_DEFAULTS4,
enabled: false,
fontStyle: void 0,
fontWeight: { $ref: "fontWeight" },
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
color: { $ref: "textColor" },
formatter: void 0,
placement: "outside-end",
padding: { $isUserOption: ["./spacing", 0, 6] }
// compatibility with old `padding` property (now named `spacing`).
}
};
}
var WATERFALL_SERIES_THEME = {
series: {
item: {
positive: itemTheme2("altUp", 0),
negative: itemTheme2("altDown", 1),
total: itemTheme2("neutral", 2)
},
line: {
stroke: { $palette: "neutral.stroke" },
strokeOpacity: 1,
lineDash: [0],
lineDashOffset: 0,
strokeWidth: 2
},
highlight: SINGLE_SERIES_HIGHLIGHT_STYLE
},
legend: {
enabled: true,
toggleSeries: false
}
};
// packages/ag-charts-enterprise/src/series/waterfall/waterfallModule.ts
var WaterfallSeriesModule = {
type: "series",
name: "waterfall",
chartType: "cartesian",
enterprise: true,
solo: true,
version: VERSION21,
dependencies: [CartesianChartModule7],
options: waterfallSeriesOptionsDef,
defaultAxes: DIRECTION_SWAP_AXES3,
axisKeys: { [ChartAxisDirection27.X]: "xKeyAxis", [ChartAxisDirection27.Y]: "yKeyAxis" },
axisKeysFlipped: { [ChartAxisDirection27.X]: "yKeyAxis", [ChartAxisDirection27.Y]: "xKeyAxis" },
themeTemplate: WATERFALL_SERIES_THEME,
create: (ctx) => new WaterfallSeries(ctx)
};
// packages/ag-charts-enterprise/src/features/navigator/navigatorOptionsDefs.ts
var navigatorHandleOptionsDef = {
width: positiveNumber5,
height: positiveNumber5,
grip: boolean11,
fill: color3,
stroke: color3,
strokeWidth: positiveNumber5,
cornerRadius: positiveNumber5
};
var commonIgnoredMiniChartProperties = [
"cursor",
"highlightStyle",
"listeners",
"nodeClickRange",
"showInLegend",
"showInMiniChart",
"tooltip",
"visible",
"xName",
"yName"
];
var barIgnoredMiniChartProperties = [
...commonIgnoredMiniChartProperties,
"errorBar",
"label",
"legendItemName"
];
var boxPlotIngnoredMiniChartProperties = [
...commonIgnoredMiniChartProperties,
"direction",
"legendItemName",
"minName",
"q1Name",
"medianName",
"q3Name",
"maxName"
];
var bubbleIgnoredMiniChartProperties = [
...commonIgnoredMiniChartProperties,
"title",
"label",
"labelKey",
"labelName",
"sizeName"
];
var heatmapIgnoredMiniChartProperties = [
...commonIgnoredMiniChartProperties,
"title",
"label",
"colorName",
"textAlign",
"verticalAlign",
"itemPadding",
"colorRange"
];
var histogramIgnoredMiniChartProperties = [
...commonIgnoredMiniChartProperties,
"label"
];
var lineIgnoredMiniChartProperties = [
...commonIgnoredMiniChartProperties,
"errorBar",
"title",
"label"
];
var rangeAreaIgnoredMiniChartProperties = [
...commonIgnoredMiniChartProperties,
"label",
"yLowName",
"yHighName"
];
var rangeBarIgnoredMiniChartProperties = [
...commonIgnoredMiniChartProperties,
"direction",
"label",
"yLowName",
"yHighName"
];
var scatterIgnoredMiniChartProperties = [
...commonIgnoredMiniChartProperties,
"errorBar",
"title",
"label",
"labelKey",
"labelName"
];
var waterfallIgnoredMiniChartProperties = [
...commonIgnoredMiniChartProperties,
"direction"
];
var navigatorOptionsDef = {
enabled: boolean11,
height: positiveNumber5,
spacing: positiveNumber5,
cornerRadius: number5,
mask: {
fill: color3,
fillOpacity: ratio4,
stroke: color3,
strokeWidth: positiveNumber5
},
minHandle: navigatorHandleOptionsDef,
maxHandle: navigatorHandleOptionsDef,
miniChart: {
enabled: boolean11,
padding: {
top: positiveNumber5,
bottom: positiveNumber5
},
label: {
enabled: boolean11,
avoidCollisions: boolean11,
spacing: positiveNumber5,
format: numberFormatValidator,
formatter: callbackOf2(textOrSegments),
interval: {
minSpacing: positiveNumber5,
maxSpacing: positiveNumber5,
values: array,
step: number5
},
...fontOptionsDef
},
series: arrayOfDefs2(
typeUnion(
{
area: without2(AreaSeriesModule.options, [...commonIgnoredMiniChartProperties, "type"]),
bar: without2(BarSeriesModule.options, [...barIgnoredMiniChartProperties, "type"]),
"box-plot": without2(BoxPlotSeriesModule.options, [...boxPlotIngnoredMiniChartProperties, "type"]),
bubble: without2(BubbleSeriesModule.options, [...bubbleIgnoredMiniChartProperties, "type"]),
candlestick: without2(CandlestickSeriesModule.options, [
...commonIgnoredMiniChartProperties,
"type"
]),
heatmap: without2(HeatmapSeriesModule.options, [...heatmapIgnoredMiniChartProperties, "type"]),
histogram: without2(HistogramSeriesModule.options, [...histogramIgnoredMiniChartProperties, "type"]),
line: without2(LineSeriesModule.options, [...lineIgnoredMiniChartProperties, "type"]),
ohlc: without2(OhlcSeriesModule.options, [...commonIgnoredMiniChartProperties, "type"]),
"range-area": without2(RangeAreaSeriesModule.options, [
...rangeAreaIgnoredMiniChartProperties,
"type"
]),
"range-bar": without2(RangeBarSeriesModule.options, [...rangeBarIgnoredMiniChartProperties, "type"]),
scatter: without2(ScatterSeriesModule.options, [...scatterIgnoredMiniChartProperties, "type"]),
waterfall: without2(WaterfallSeriesModule.options, [...waterfallIgnoredMiniChartProperties, "type"])
},
"miniChart series options"
)
)
}
};
// packages/ag-charts-enterprise/src/features/navigator/navigatorTheme.ts
import "ag-charts-community";
import { FONT_SIZE_RATIO as FONT_SIZE_RATIO2 } from "ag-charts-core";
var validMiniChartSeriesTypes = [
"area",
"bar",
"bubble",
"candlestick",
"heatmap",
"histogram",
"line",
"ohlc",
"range-area",
"range-bar",
"scatter",
"waterfall"
];
var priceVolumePresetIgnoredMiniChartProperties = [
"itemStyler",
"simpleItemStyler",
"direction",
"fill",
"fillGradientDefaults",
"fillPatternDefaults",
"fillImageDefaults",
"fillOpacity",
"shadow",
"focusPriority",
"highlight",
"lineDash",
"lineDashOffset",
"strokeWidth"
];
function miniChartSeriesTheme(seriesPath, typePath) {
return {
$merge: [
{
$switch: [
typePath,
{},
[
["area", "line", "range-area"],
{
marker: {
enabled: {
$isUserOption: [
"/series/$index/marker/enabled",
{ $path: ["/series/$index/marker/enabled", false] },
false
]
}
}
}
]
]
},
{
$omit: [
{
$switch: [
typePath,
commonIgnoredMiniChartProperties,
["bar", barIgnoredMiniChartProperties],
["box-plot", boxPlotIngnoredMiniChartProperties],
["bubble", bubbleIgnoredMiniChartProperties],
["heatmap", heatmapIgnoredMiniChartProperties],
["histogram", histogramIgnoredMiniChartProperties],
[
"line",
[...lineIgnoredMiniChartProperties, ...priceVolumePresetIgnoredMiniChartProperties]
],
["range-area", rangeAreaIgnoredMiniChartProperties],
["range-bar", rangeBarIgnoredMiniChartProperties],
["scatter", scatterIgnoredMiniChartProperties],
["waterfall", waterfallIgnoredMiniChartProperties]
]
},
seriesPath
]
}
]
};
}
var NAVIGATOR_THEME = {
enabled: false,
height: { $if: [{ $path: "./miniChart/enabled" }, 40, 18] },
cornerRadius: 4,
mask: {
fill: { $ref: "foregroundColor" },
fillOpacity: 0.1,
stroke: { $ref: "borderColor" },
strokeWidth: 1
},
minHandle: {
fill: { $ref: "chartBackgroundColor" },
stroke: { $ref: "borderColor" },
strokeWidth: 1,
width: 12,
height: 24,
cornerRadius: 4
},
maxHandle: {
fill: { $ref: "chartBackgroundColor" },
stroke: { $ref: "borderColor" },
strokeWidth: 1,
width: 12,
height: 24,
cornerRadius: 4
},
miniChart: {
enabled: false,
label: {
color: { $ref: "textColor" },
fontSize: { $rem: FONT_SIZE_RATIO2.SMALLER },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
spacing: 5
},
padding: {
top: 0,
bottom: 0
},
series: {
$apply: [
miniChartSeriesTheme(
{ $path: "/series/$index" },
{
$path: [
"/navigator/miniChart/series/$index/type",
{ $path: ["type", { $path: "/series/$index/type" }] }
]
}
),
{
// TODO: this should be a $switch but switches can not resolve the case value yet
$if: [
{
$or: validMiniChartSeriesTypes.map((type) => ({
$eq: [{ $path: "/series/0/type" }, type]
}))
},
{
$map: [
miniChartSeriesTheme({ $value: "$1" }, { $path: "/series/$index/type" }),
{ $path: "/series" }
]
},
void 0
]
}
]
}
}
};
// packages/ag-charts-enterprise/src/features/navigator/navigatorModule.ts
var NavigatorModule = {
type: "plugin",
name: "navigator",
chartType: "cartesian",
enterprise: true,
version: VERSION22,
// removable: false, // Toggling this module causes zoom state flakiness.
options: navigatorOptionsDef,
themeTemplate: NAVIGATOR_THEME,
create: (ctx) => new Navigator(ctx)
};
// packages/ag-charts-enterprise/src/features/scrollbar/scrollbarModule.ts
import { VERSION as VERSION23 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/features/scrollbar/scrollbar.ts
import { _ModuleSupport as _ModuleSupport119 } from "ag-charts-community";
import {
AbstractModuleInstance as AbstractModuleInstance13,
ChartAxisDirection as ChartAxisDirection28,
ChartUpdateType as ChartUpdateType6,
Property as Property59,
ZIndexMap as ZIndexMap9,
clamp as clamp9
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/scrollbar/scrollbarDOMProxy.ts
import { _ModuleSupport as _ModuleSupport118 } from "ag-charts-community";
import { clamp as clamp8 } from "ag-charts-core";
var { SliderWidget: SliderWidget2 } = _ModuleSupport118;
var STEP_REPEAT_DELAY_MS = 400;
var STEP_REPEAT_INTERVAL_MS = 50;
var StepRepeater = class {
constructor(applyStep) {
this.applyStep = applyStep;
}
start(target) {
this.setTarget(target);
this.run(STEP_REPEAT_DELAY_MS);
}
updateTarget(target) {
this.setTarget(target);
if (!this.isActive()) {
this.run(STEP_REPEAT_DELAY_MS);
}
}
stop(resetTarget = true) {
this.clearTimer();
if (resetTarget) {
this.target = void 0;
}
}
setTarget(target) {
this.target = clamp8(0, target, 1);
}
run(delay) {
if (this.target == null) {
this.stop();
return;
}
const finished = this.applyStep(this.target);
if (finished) {
this.stop();
return;
}
this.schedule(delay);
}
schedule(delay) {
if (this.isActive())
return;
this.timer = setTimeout(() => {
this.timer = void 0;
this.run(STEP_REPEAT_INTERVAL_MS);
}, delay);
}
clearTimer() {
if (this.timer != null) {
clearTimeout(this.timer);
this.timer = void 0;
}
}
isActive() {
return this.timer != null;
}
};
var ScrollbarState = class {
constructor() {
this.min = 0;
this.span = 1;
this.thumbSpan = 1;
}
update(min, max, thumbSpan = this.thumbSpan) {
const span = clamp8(0, max - min, 1);
this.span = span;
this.thumbSpan = clamp8(0, thumbSpan, 1);
this.min = this.clampMin(min, span);
}
clampMin(min, span = this.span) {
return clamp8(0, min, 1 - span);
}
getThumbBounds(min = this.min, span = this.thumbSpan) {
const start = this.clampMin(min, span);
return { start, end: start + span };
}
isWithinThumb(ratio8) {
const { start, end } = this.getThumbBounds();
return ratio8 >= start && ratio8 <= end;
}
getJumpRange(ratio8) {
if (!this.canScroll())
return;
let min = this.clampMin(ratio8 - this.thumbSpan / 2, this.thumbSpan);
min = this.clampMin(min);
return { min, max: min + this.span };
}
getStepRange(ratio8) {
if (!this.canScroll())
return;
const cursor = clamp8(0, ratio8, 1);
const { start, end } = this.getThumbBounds();
if (cursor >= start && cursor <= end)
return;
const movingLeft = cursor < start;
const distance = movingLeft ? start - cursor : cursor - end;
const step = Math.min(this.span, distance);
const nextMin = this.clampMin(this.min + (movingLeft ? -step : step));
return { min: nextMin, max: nextMin + this.span };
}
canScroll() {
return this.span > 0 && this.span < 1;
}
};
var ScrollbarDOMProxy = class {
constructor(ctx, orientation, onChange, onHoverChange) {
this.ctx = ctx;
this.orientation = orientation;
this.onChange = onChange;
this.onHoverChange = onHoverChange;
this.dragStartRatio = 0;
this.interactionMode = "none";
this.state = new ScrollbarState();
this.repeater = new StepRepeater((target) => this.applyStepToward(target));
this.container = ctx.proxyInteractionService.createProxyContainer({
type: "group",
domManagerId: `scrollbar-${orientation}`,
classList: ["ag-charts-proxy-scrollbar", `ag-charts-proxy-scrollbar-${orientation}`],
ariaLabel: void 0,
role: "presentation"
});
const ariaLabelId = orientation === "horizontal" ? "ariaLabelScrollbarHorizontal" : "ariaLabelScrollbarVertical";
this.slider = ctx.proxyInteractionService.createProxyElement({
type: "slider",
domIndex: 0,
tabIndex: 0,
ariaLabel: { id: ariaLabelId },
role: "slider",
parent: this.container,
classList: ["ag-charts-proxy-scrollbar-slider"]
});
const element = this.slider.getElement();
element.ariaValueMin = "0";
element.ariaValueMax = "100";
this.slider.step = SliderWidget2.STEP_HUNDRETH;
this.slider.keyboardStep = SliderWidget2.STEP_ONE;
this.slider.orientation = orientation;
this.slider.setPreventsDefault(false);
this.slider.addListener("change", () => this.onSliderChange());
this.slider.addListener("keydown", (ev) => this.onSliderKeyDown(ev));
this.slider.addListener("drag-start", (ev) => this.onDragStart(ev));
this.slider.addListener("drag-move", (ev) => this.onDragMove(ev));
this.slider.addListener("drag-end", (ev) => this.onDragEnd(ev));
this.slider.addListener("mouseenter", (event) => this.handleHoverEvent(event));
this.slider.addListener("mousemove", (event) => this.handleHoverEvent(event));
this.slider.addListener("mouseleave", () => this.onMouseLeave());
this.thumbFocus = ctx.proxyInteractionService.createProxyElement({
type: "region",
parent: this.container,
classList: ["ag-charts-proxy-scrollbar-thumb-focus"],
role: "presentation"
});
this.thumbFocus.setAriaHidden(true);
this.thumbFocus.setPointerEvents("none");
}
destroy() {
this.interactionBounds = void 0;
this.repeater.stop();
this.container.destroy();
}
updateBounds(bounds) {
this.interactionBounds = void 0;
this.container.setBounds(bounds);
this.slider.setBounds({ x: 0, y: 0, width: bounds.width, height: bounds.height });
}
updateVisibility(visible) {
this.container.setHidden(!visible);
}
updateMinMax(min, max, thumbSpan = this.state.thumbSpan, options) {
this.state.update(min, max, thumbSpan);
const aria = this.ctx.localeManager.t("ariaValuePanRange", {
min: Math.round(min * 100) / 100,
max: Math.round(max * 100) / 100
});
const element = this.slider.getElement();
element.ariaValueText = aria;
const shouldUpdateSlider = !options?.skipSliderUpdate || Math.abs(this.slider.getValueRatio() - min) > 1e-9;
if (shouldUpdateSlider) {
this.slider.setValueRatio(min, { ariaValueText: aria });
}
}
updateThumbBounds(thumb, track, cornerRadius) {
const radius = Math.max(0, cornerRadius ?? 0);
this.thumbFocus.getElement().style.borderRadius = `${radius}px`;
this.thumbFocus.setBounds({
x: thumb.x - track.x,
y: thumb.y - track.y,
width: thumb.width,
height: thumb.height
});
}
update(min, max, options) {
this.onChange(min, max);
this.updateMinMax(min, max, void 0, options);
}
onSliderChange() {
const min = this.state.clampMin(this.slider.getValueRatio());
const max = min + this.state.span;
this.update(min, max, { skipSliderUpdate: true });
}
onSliderKeyDown(event) {
const { code } = event.sourceEvent;
const isVertical = this.orientation === "vertical";
const decrement = isVertical && code === "ArrowUp" || !isVertical && code === "ArrowLeft";
const increment = isVertical && code === "ArrowDown" || !isVertical && code === "ArrowRight";
if (!decrement && !increment)
return;
event.sourceEvent.preventDefault();
const element = this.slider.getElement();
element.step = this.slider.keyboardStep?.attributeValue ?? "1";
if (decrement) {
element.stepDown();
} else if (increment) {
element.stepUp();
}
this.onSliderChange();
}
onDragMove(event) {
event.sourceEvent.preventDefault();
if (this.interactionMode === "drag") {
const { isHorizontal: isHorizontal2, size, start } = this.getInteractionBounds() ?? {};
if (start == null || size == null)
return;
const delta3 = (isHorizontal2 ? event.originDeltaX : event.originDeltaY) / size;
const min = this.state.clampMin(this.dragStartRatio + delta3);
const max = min + this.state.span;
this.update(min, max);
return;
}
if (this.interactionMode !== "step")
return;
const pointer = this.getPointerInfo(event);
if (pointer == null || !Number.isFinite(pointer.ratio))
return;
const { ratio: ratio8, inCrossBounds } = pointer;
if (!inCrossBounds) {
this.repeater.stop();
return;
}
this.repeater.updateTarget(ratio8);
}
onDragEnd(event) {
event.sourceEvent.preventDefault();
this.interactionBounds = void 0;
this.setInteraction("none");
this.onHoverChange(false);
}
onDragStart(event) {
event.sourceEvent.preventDefault();
this.interactionBounds = void 0;
const click = this.getClickInfo(event);
if (!click?.inBounds)
return;
if (click.inThumb) {
this.dragStartRatio = this.slider.getValueRatio();
this.setInteraction("drag");
return;
}
if (event.sourceEvent.shiftKey) {
this.jumpTo(click.ratio);
this.setInteraction("none");
return;
}
this.beginStepRepeat(click.ratio);
}
onMouseLeave() {
this.onHoverChange(false);
}
getClickInfo(event) {
const ratio8 = this.getPointerRatio(event);
if (ratio8 == null)
return;
const inBounds = ratio8 >= 0 && ratio8 <= 1;
if (!inBounds)
return { ratio: 0, inBounds: false, inThumb: false };
return { ratio: ratio8, inBounds: true, inThumb: this.isWithinThumb(ratio8) };
}
getPointerRatio(event) {
return this.getPointerInfo(event)?.ratio;
}
getPointerInfo(event) {
if (event.device === "keyboard")
return;
const { isHorizontal: isHorizontal2, size, start, crossStart, crossSize } = this.getInteractionBounds();
const pos = isHorizontal2 ? event.clientX : event.clientY;
const crossPos = isHorizontal2 ? event.clientY : event.clientX;
const ratio8 = (pos - start) / size;
const inCrossBounds = crossPos >= crossStart && crossPos <= crossStart + crossSize;
return { ratio: ratio8, inCrossBounds };
}
jumpTo(ratio8) {
const next = this.state.getJumpRange(ratio8);
if (!next)
return;
this.update(next.min, next.max);
}
applyStepToward(target) {
const next = this.state.getStepRange(target);
if (!next)
return true;
this.update(next.min, next.max);
return false;
}
beginStepRepeat(ratio8) {
this.setInteraction("step");
this.repeater.start(ratio8);
}
setInteraction(mode) {
this.interactionMode = mode;
if (mode !== "step") {
this.repeater.stop();
}
}
getInteractionBounds() {
if (this.interactionBounds) {
return this.interactionBounds;
}
const { width, height, left, top } = this.container.getBoundingClientRect();
const isHorizontal2 = this.orientation === "horizontal";
const size = isHorizontal2 ? width : height;
const start = isHorizontal2 ? left : top;
const crossStart = isHorizontal2 ? top : left;
const crossSize = isHorizontal2 ? height : width;
this.interactionBounds = { isHorizontal: isHorizontal2, size, start, crossStart, crossSize };
return this.interactionBounds;
}
isWithinThumb(ratio8) {
return this.state.isWithinThumb(ratio8);
}
handleHoverEvent(event) {
if (this.interactionMode === "drag")
return;
const pointer = this.getPointerInfo(event);
if (!pointer) {
this.onHoverChange(false);
return;
}
const hovered = this.isWithinThumb(pointer.ratio);
this.onHoverChange(hovered);
}
};
// packages/ag-charts-enterprise/src/features/scrollbar/scrollbarProperties.ts
import { ChangeDetectableProperties, Property as Property58, SceneChangeDetection as SceneChangeDetection5 } from "ag-charts-core";
var ScrollbarTrack = class extends ChangeDetectableProperties {
constructor() {
super(...arguments);
this.enabled = false;
this.fillOpacity = 1;
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.cornerRadius = 0;
this.opacity = 1;
}
};
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarTrack.prototype, "enabled", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarTrack.prototype, "fill", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarTrack.prototype, "fillOpacity", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarTrack.prototype, "stroke", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarTrack.prototype, "strokeWidth", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarTrack.prototype, "strokeOpacity", 2);
__decorateClass([
Property58
], ScrollbarTrack.prototype, "lineDash", 2);
__decorateClass([
Property58
], ScrollbarTrack.prototype, "lineDashOffset", 2);
__decorateClass([
Property58
], ScrollbarTrack.prototype, "cornerRadius", 2);
__decorateClass([
Property58
], ScrollbarTrack.prototype, "opacity", 2);
var ScrollbarThumbHoverStyle = class extends ChangeDetectableProperties {
};
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarThumbHoverStyle.prototype, "fill", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarThumbHoverStyle.prototype, "stroke", 2);
var ScrollbarThumb = class extends ScrollbarTrack {
constructor() {
super(...arguments);
this.minSize = 20;
this.hoverStyle = new ScrollbarThumbHoverStyle();
}
};
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarThumb.prototype, "minSize", 2);
__decorateClass([
Property58
], ScrollbarThumb.prototype, "hoverStyle", 2);
var ScrollbarProperties = class extends ChangeDetectableProperties {
constructor() {
super(...arguments);
this.enabled = false;
this.thickness = 12;
this.spacing = 4;
this.tickSpacing = 0;
this.placement = "outer";
this.visible = "auto";
this.track = new ScrollbarTrack();
this.thumb = new ScrollbarThumb();
}
};
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarProperties.prototype, "enabled", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarProperties.prototype, "thickness", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarProperties.prototype, "spacing", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarProperties.prototype, "tickSpacing", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarProperties.prototype, "placement", 2);
__decorateClass([
Property58,
SceneChangeDetection5()
], ScrollbarProperties.prototype, "visible", 2);
__decorateClass([
Property58
], ScrollbarProperties.prototype, "track", 2);
__decorateClass([
Property58
], ScrollbarProperties.prototype, "thumb", 2);
var HorizontalScrollbarProperties = class extends ScrollbarProperties {
};
__decorateClass([
Property58,
SceneChangeDetection5()
], HorizontalScrollbarProperties.prototype, "position", 2);
var VerticalScrollbarProperties = class extends ScrollbarProperties {
};
__decorateClass([
Property58,
SceneChangeDetection5()
], VerticalScrollbarProperties.prototype, "position", 2);
// packages/ag-charts-enterprise/src/features/scrollbar/scrollbar.ts
var { BBox: BBox14, Group: Group7, Rect: Rect4, LayoutElement: LayoutElement3, InteractionState: InteractionState5 } = _ModuleSupport119;
var Scrollbar = class extends AbstractModuleInstance13 {
constructor(ctx) {
super();
this.ctx = ctx;
this.track = new ScrollbarTrack();
this.thumb = new ScrollbarThumb();
this.horizontal = new HorizontalScrollbarProperties();
this.vertical = new VerticalScrollbarProperties();
this.state = {
horizontal: this.createOrientationState("horizontal"),
vertical: this.createOrientationState("vertical")
};
this.cleanup.register(
ctx.scene.attachNode(this.state.horizontal.group),
ctx.scene.attachNode(this.state.vertical.group),
ctx.layoutManager.registerElement(LayoutElement3.Scrollbar, (e) => this.onLayoutStart(e)),
ctx.eventsHub.on("layout:complete", (e) => this.onLayoutComplete(e)),
ctx.eventsHub.on("zoom:change-complete", () => this.updateThumbs())
);
}
createOrientationState(orientation) {
const group = new Group7({ name: `scrollbar-${orientation}`, zIndex: ZIndexMap9.NAVIGATOR });
const track = new Rect4();
const thumb = new Rect4();
group.append(track);
group.append(thumb);
const dom = new ScrollbarDOMProxy(
this.ctx,
orientation,
(min, max) => this.handleUserChange(orientation, min, max),
(hovered) => this.handleHoverChange(orientation, hovered)
);
const properties = this.resolveProperties(orientation);
return {
orientation,
group,
track,
thumb,
dom,
properties,
position: this.getDefaultPosition(orientation),
positionHasAxis: false,
hovered: false
};
}
resolveProperties(orientation) {
return orientation === "horizontal" ? this.horizontal : this.vertical;
}
getDefaultPosition(orientation) {
return orientation === "horizontal" ? "bottom" : "left";
}
resolveAxis(orientation, configuredPosition) {
const direction = orientation === "horizontal" ? ChartAxisDirection28.X : ChartAxisDirection28.Y;
const contexts = this.ctx.axisManager.getAxisContext(direction);
if (contexts.length === 0) {
return { position: this.getDefaultPosition(orientation), positionHasAxis: false };
}
if (configuredPosition == null) {
const axis2 = contexts[0];
return { axis: axis2, position: axis2.position ?? this.getDefaultPosition(orientation), positionHasAxis: true };
}
const axis = contexts.find((ctx) => ctx.position === configuredPosition);
if (axis) {
return { axis, position: configuredPosition, positionHasAxis: true };
}
return { axis: contexts[0], position: configuredPosition, positionHasAxis: false };
}
onLayoutStart({ scrollbars, layoutBox }) {
for (const orientation of ["horizontal", "vertical"]) {
const state = this.state[orientation];
const properties = this.resolveProperties(orientation);
const { min, max } = this.getZoomRange(state.orientation);
const span = clamp9(0, max - min, 1);
const {
axis: { axisId } = {},
position,
positionHasAxis
} = this.resolveAxis(orientation, properties.position);
state.properties = properties;
state.axisId = axisId;
state.position = position;
state.positionHasAxis = positionHasAxis;
const show = this.updateVisibility(state, span);
if (!show || axisId == null)
continue;
const { thickness, spacing, placement, tickSpacing } = properties;
if (positionHasAxis) {
scrollbars[axisId] = {
enabled: show,
thickness,
spacing,
tickSpacing,
placement
};
} else {
layoutBox.shrink(spacing + thickness, position);
}
this.updateStyles(state);
}
}
onLayoutComplete(event) {
this.seriesRect = event.series.rect;
for (const orientation of ["horizontal", "vertical"]) {
const state = this.state[orientation];
const {
properties: { enabled, visible }
} = state;
if (!enabled || visible === "never") {
continue;
}
const layoutRect = this.getLayoutRect(state, orientation, event);
state.layoutRect = layoutRect;
if (!layoutRect)
continue;
this.updateTrack(state, layoutRect);
this.updateThumb(state, layoutRect);
}
}
getLayoutRect(state, orientation, event) {
const {
properties: { thickness, spacing },
position,
positionHasAxis
} = state;
const axisLayout = state.axisId ? event.axes[state.axisId] : void 0;
if (!axisLayout)
return;
const { x, y, width, height } = event.series.rect;
const isHorizontal2 = orientation === "horizontal";
if (!positionHasAxis) {
if (isHorizontal2) {
const coord2 = position === "bottom" ? y + height + spacing : y - spacing - thickness;
return new BBox14(x, coord2, width, thickness);
} else {
const coord2 = position === "right" ? x + width + spacing : x - spacing - thickness;
return new BBox14(coord2, y, thickness, height);
}
}
const { scrollbar: scrollbarLayout, translation } = axisLayout;
if (!scrollbarLayout?.enabled)
return;
const coord = isHorizontal2 ? translation.y + scrollbarLayout.offset : translation.x + scrollbarLayout.offset;
return isHorizontal2 ? new BBox14(x, coord, width, thickness) : new BBox14(coord, y, thickness, height);
}
updateStyles({ track, thumb, properties, hovered }) {
track.setStyleProperties(properties.track);
track.cornerRadius = properties.track.cornerRadius ?? 0;
track.opacity = properties.track.opacity ?? 1;
thumb.setStyleProperties(properties.thumb);
thumb.cornerRadius = properties.thumb.cornerRadius ?? 0;
thumb.opacity = properties.thumb.opacity ?? 1;
const hoverStyle = properties.thumb.hoverStyle;
thumb.fill = hovered ? hoverStyle?.fill ?? properties.thumb.fill : properties.thumb.fill;
thumb.stroke = hovered ? hoverStyle?.stroke ?? properties.thumb.stroke : properties.thumb.stroke;
}
updateTrack(state, bounds) {
state.track.x = bounds.x;
state.track.y = bounds.y;
state.track.width = bounds.width;
state.track.height = bounds.height;
state.dom.updateBounds(bounds);
}
updateThumb(state, track) {
const { min, max } = this.getZoomRange(state.orientation);
const span = clamp9(0, max - min, 1);
const show = this.updateVisibility(state, span);
if (!show || track.width <= 0 || track.height <= 0) {
return;
}
const minSize = state.properties.thumb.minSize ?? 0;
let thumbSpan;
if (state.orientation === "horizontal") {
const thumbWidth = Math.min(Math.max(minSize, track.width * span), track.width);
const start = clamp9(track.x, track.x + track.width * min, track.x + track.width - thumbWidth);
state.thumb.x = start;
state.thumb.y = track.y;
state.thumb.width = thumbWidth;
state.thumb.height = track.height;
thumbSpan = clamp9(0, thumbWidth / track.width, 1);
} else {
const thumbHeight = Math.min(Math.max(minSize, track.height * span), track.height);
const start = clamp9(track.y, track.y + track.height * min, track.y + track.height - thumbHeight);
state.thumb.x = track.x;
state.thumb.y = start;
state.thumb.width = track.width;
state.thumb.height = thumbHeight;
thumbSpan = clamp9(0, thumbHeight / track.height, 1);
}
state.dom.updateThumbBounds(state.thumb, track, state.properties.thumb.cornerRadius);
state.dom.updateMinMax(min, max, thumbSpan);
}
updateThumbs() {
if (!this.seriesRect)
return;
for (const orientation of ["horizontal", "vertical"]) {
const state = this.state[orientation];
const layoutRect = state.layoutRect;
if (!layoutRect || !state.properties.enabled || state.properties.visible === "never")
continue;
const trackBounds = orientation === "horizontal" ? new BBox14(this.seriesRect.x, layoutRect.y, this.seriesRect.width, state.properties.thickness) : new BBox14(layoutRect.x, this.seriesRect.y, state.properties.thickness, this.seriesRect.height);
this.updateThumb(state, trackBounds);
}
}
updateVisibility(state, span) {
const show = state.properties.enabled && state.axisId != null && state.properties.visible !== "never" && (state.properties.visible === "always" || span < 1);
state.group.visible = show;
state.track.visible = show;
state.thumb.visible = show;
state.dom.updateVisibility(show);
return show;
}
getZoomRange(orientation) {
const zoom = this.ctx.zoomManager.getZoom();
const isHorizontal2 = orientation === "horizontal";
const range2 = isHorizontal2 ? zoom?.x : zoom?.y;
if (!isHorizontal2 && range2 != null) {
return {
min: 1 - (range2.max ?? 1),
max: 1 - (range2.min ?? 0)
};
}
return {
min: range2?.min ?? 0,
max: range2?.max ?? 1
};
}
handleUserChange(orientation, min, max) {
if (!this.ctx.interactionManager.isState(InteractionState5.ZoomDraggable))
return;
const isHorizontal2 = orientation === "horizontal";
if (!isHorizontal2) {
[min, max] = [1 - max, 1 - min];
}
const zoom = isHorizontal2 ? { x: { min, max } } : { y: { min, max } };
this.ctx.zoomManager.updateZoom(
{
source: "user-interaction",
sourceDetail: "scrollbar"
},
zoom
);
}
handleHoverChange(orientation, hovered) {
const state = this.state[orientation];
const nextHovered = hovered && state.group.visible;
if (state.hovered === nextHovered)
return;
state.hovered = nextHovered;
this.updateStyles(state);
this.ctx.updateService.update(ChartUpdateType6.SCENE_RENDER);
}
destroy() {
super.destroy();
this.state.horizontal.dom.destroy();
this.state.vertical.dom.destroy();
}
};
__decorateClass([
Property59
], Scrollbar.prototype, "enabled", 2);
__decorateClass([
Property59
], Scrollbar.prototype, "thickness", 2);
__decorateClass([
Property59
], Scrollbar.prototype, "spacing", 2);
__decorateClass([
Property59
], Scrollbar.prototype, "tickSpacing", 2);
__decorateClass([
Property59
], Scrollbar.prototype, "placement", 2);
__decorateClass([
Property59
], Scrollbar.prototype, "visible", 2);
__decorateClass([
Property59
], Scrollbar.prototype, "track", 2);
__decorateClass([
Property59
], Scrollbar.prototype, "thumb", 2);
__decorateClass([
Property59
], Scrollbar.prototype, "horizontal", 2);
__decorateClass([
Property59
], Scrollbar.prototype, "vertical", 2);
// packages/ag-charts-enterprise/src/features/scrollbar/scrollbarOptionsDefs.ts
import {
boolean as boolean12,
fillOptionsDef as fillOptionsDef2,
lineDashOptionsDef,
positiveNumber as positiveNumber6,
ratio as ratio5,
strokeOptionsDef,
union as union2
} from "ag-charts-core";
var scrollbarTrackOptionsDef = {
...fillOptionsDef2,
...strokeOptionsDef,
...lineDashOptionsDef,
cornerRadius: positiveNumber6,
opacity: ratio5
};
var scrollbarThumbOptionsDef = {
...scrollbarTrackOptionsDef,
minSize: positiveNumber6,
hoverStyle: {
fill: fillOptionsDef2.fill,
stroke: strokeOptionsDef.stroke
}
};
var scrollbarBaseOptionsDef = {
enabled: boolean12,
thickness: positiveNumber6,
spacing: positiveNumber6,
tickSpacing: positiveNumber6,
visible: union2("auto", "always", "never"),
placement: union2("outer", "inner"),
track: scrollbarTrackOptionsDef,
thumb: scrollbarThumbOptionsDef
};
var scrollbarHorizontalOrientationOptionsDef = {
...scrollbarBaseOptionsDef,
position: union2("top", "bottom")
};
var scrollbarVerticalOrientationOptionsDef = {
...scrollbarBaseOptionsDef,
position: union2("left", "right")
};
var scrollbarOptionsDef = {
enabled: boolean12,
thickness: positiveNumber6,
spacing: positiveNumber6,
tickSpacing: positiveNumber6,
visible: union2("auto", "always", "never"),
placement: union2("outer", "inner"),
track: scrollbarTrackOptionsDef,
thumb: scrollbarThumbOptionsDef,
horizontal: scrollbarHorizontalOrientationOptionsDef,
vertical: scrollbarVerticalOrientationOptionsDef
};
// packages/ag-charts-enterprise/src/features/scrollbar/scrollbarTheme.ts
var SCROLLBAR_ORIENTATION_THEME = {
enabled: { $path: "../enabled" },
thickness: { $path: "../thickness" },
spacing: { $path: "../spacing" },
tickSpacing: { $path: "../tickSpacing" },
placement: { $path: "../placement" },
visible: { $path: "../visible" },
track: {
fill: { $path: "../../track/fill" },
stroke: { $path: "../../track/stroke" },
fillOpacity: { $path: "../../track/fillOpacity" },
strokeWidth: { $path: "../../track/strokeWidth" },
lineDash: { $path: "../../track/lineDash" },
lineDashOffset: { $path: "../../track/lineDashOffset" },
opacity: { $path: "../../track/opacity" },
cornerRadius: { $path: "../../track/cornerRadius" }
},
thumb: {
fill: { $path: "../../thumb/fill" },
stroke: { $path: "../../thumb/stroke" },
fillOpacity: { $path: "../../thumb/fillOpacity" },
strokeWidth: { $path: "../../thumb/strokeWidth" },
lineDash: { $path: "../../thumb/lineDash" },
lineDashOffset: { $path: "../../thumb/lineDashOffset" },
opacity: { $path: "../../thumb/opacity" },
cornerRadius: { $path: "../../thumb/cornerRadius" },
minSize: { $path: "../../thumb/minSize" },
hoverStyle: {
fill: { $path: "../../../thumb/hoverStyle/fill" },
stroke: { $path: "../../../thumb/hoverStyle/stroke" }
}
}
};
var SCROLLBAR_THEME = {
enabled: false,
thickness: 12,
spacing: 16,
tickSpacing: 0,
placement: "outer",
visible: "auto",
track: {
fill: { $foregroundBackgroundMix: 0.03 },
stroke: { $foregroundBackgroundMix: 0.177 },
strokeWidth: 1,
lineDash: [0],
lineDashOffset: 0,
opacity: 1,
cornerRadius: 6
},
thumb: {
fill: { $foregroundBackgroundMix: 0.125 },
stroke: { $foregroundBackgroundMix: 0.364 },
strokeWidth: 1,
lineDash: [0],
lineDashOffset: 0,
opacity: 1,
cornerRadius: 6,
minSize: 20,
hoverStyle: {
fill: { $mix: [{ $path: "../fill" }, { $ref: "foregroundColor" }, 0.075] },
stroke: { $mix: [{ $path: "../stroke" }, { $ref: "foregroundColor" }, 0.075] }
}
},
vertical: SCROLLBAR_ORIENTATION_THEME,
horizontal: SCROLLBAR_ORIENTATION_THEME
};
// packages/ag-charts-enterprise/src/features/scrollbar/scrollbarModule.ts
var ScrollbarModule = {
type: "plugin",
name: "scrollbar",
chartType: "cartesian",
enterprise: true,
version: VERSION23,
options: scrollbarOptionsDef,
themeTemplate: SCROLLBAR_THEME,
create: (ctx) => new Scrollbar(ctx)
};
// packages/ag-charts-enterprise/src/features/ranges/rangesModule.ts
import { VERSION as VERSION24 } from "ag-charts-community";
import {
and,
arrayLength,
arrayOf as arrayOf2,
arrayOfDefs as arrayOfDefs3,
boolean as boolean13,
callback as callback2,
date,
number as number6,
or,
toolbarButtonOptionsDefs
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/ranges/ranges.ts
import { _ModuleSupport as _ModuleSupport120 } from "ag-charts-community";
import { AbstractModuleInstance as AbstractModuleInstance14, ChartAxisDirection as ChartAxisDirection29, PropertiesArray as PropertiesArray5, Property as Property61 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/ranges/rangesButtonProperties.ts
import { Property as Property60 } from "ag-charts-core";
var RangesButtonProperties = class extends ToolbarButtonProperties {
};
__decorateClass([
Property60
], RangesButtonProperties.prototype, "value", 2);
// packages/ag-charts-enterprise/src/features/ranges/ranges.ts
var { userInteraction, LayoutElement: LayoutElement4, Toolbar } = _ModuleSupport120;
var Ranges = class extends AbstractModuleInstance14 {
constructor(ctx) {
super();
this.ctx = ctx;
this.enabled = false;
this.buttons = new PropertiesArray5(RangesButtonProperties);
this.verticalSpacing = 10;
this.container = ctx.domManager.addChild("canvas-overlay", "range-buttons");
this.container.role = "presentation";
this.toolbar = new Toolbar(this.ctx, "ariaLabelRangesToolbar", "horizontal");
this.toolbar.addClass("ag-charts-range-buttons");
this.container.append(this.toolbar.getElement());
this.cleanup.register(
this.toolbar.addToolbarListener("button-pressed", this.onButtonPress.bind(this)),
ctx.layoutManager.registerElement(LayoutElement4.ToolbarBottom, this.onLayoutStart.bind(this)),
ctx.eventsHub.on("zoom:change-complete", this.onZoomChanged.bind(this)),
this.teardown.bind(this)
);
}
teardown() {
this.toolbar.getElement().remove();
this.toolbar.destroy();
}
onLayoutStart({ layoutBox }) {
const { buttons, ctx, enabled, toolbar: toolbar2, verticalSpacing } = this;
if (!enabled || !ctx.zoomManager.isZoomEnabled()) {
toolbar2.setHidden(true);
return;
}
toolbar2.setHidden(false);
toolbar2.updateButtons(buttons);
const height = toolbar2.getBounds().height;
toolbar2.setBounds({
x: layoutBox.x,
y: layoutBox.y + layoutBox.height - height,
width: layoutBox.width,
height
});
layoutBox.shrink({ bottom: height + verticalSpacing });
}
onZoomChanged() {
this.toolbar.clearActiveButton();
}
onButtonPress({ button: { index } }) {
const { zoomManager } = this.ctx;
const button = this.buttons.at(index);
if (!button)
return;
const { value } = button;
const sourcing = userInteraction(`zoom-range-button-${index}`);
if (value == null) {
zoomManager.resetZoom(sourcing);
} else if (typeof value === "number") {
zoomManager.extendToEnd(sourcing, ChartAxisDirection29.X, value);
} else if (Array.isArray(value)) {
zoomManager.updateWith(sourcing, ChartAxisDirection29.X, () => value);
} else if (typeof value === "function") {
zoomManager.updateWith(sourcing, ChartAxisDirection29.X, value);
}
this.toolbar.toggleActiveButtonByIndex(index);
}
};
__decorateClass([
Property61
], Ranges.prototype, "enabled", 2);
__decorateClass([
Property61
], Ranges.prototype, "buttons", 2);
// packages/ag-charts-enterprise/src/features/ranges/rangesModule.ts
var DAY = 1e3 * 60 * 60 * 24;
var MONTH = DAY * 30;
var YEAR = DAY * 365;
var RangesModule = {
type: "plugin",
name: "ranges",
chartType: "cartesian",
enterprise: true,
version: VERSION24,
options: {
enabled: boolean13,
buttons: arrayOfDefs3(
{
...toolbarButtonOptionsDefs,
value: or(number6, and(arrayOf2(or(number6, date)), arrayLength(2, 2)), callback2)
},
"range button options array"
)
},
themeTemplate: {
enabled: false,
buttons: {
$shallowSimple: [
{
label: "toolbarRange1Month",
ariaLabel: "toolbarRange1MonthAria",
value: MONTH
},
{
label: "toolbarRange3Months",
ariaLabel: "toolbarRange3MonthsAria",
value: 3 * MONTH
},
{
label: "toolbarRange6Months",
ariaLabel: "toolbarRange6MonthsAria",
value: 6 * MONTH
},
{
label: "toolbarRangeYearToDate",
ariaLabel: "toolbarRangeYearToDateAria",
value: (_start, end) => [
(/* @__PURE__ */ new Date(`${new Date(end).getFullYear()}-01-01`)).getTime(),
void 0
]
},
{
label: "toolbarRange1Year",
ariaLabel: "toolbarRange1YearAria",
value: YEAR
},
{
label: "toolbarRangeAll",
ariaLabel: "toolbarRangeAllAria",
value: void 0
// Reset zoom
}
]
}
},
create: (ctx) => new Ranges(ctx)
};
// packages/ag-charts-enterprise/src/features/status-bar/statusBarModule.ts
import { VERSION as VERSION25 } from "ag-charts-community";
import { DEFAULT_CAPTION_LAYOUT_STYLE } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/status-bar/statusBar.ts
import { _ModuleSupport as _ModuleSupport121 } from "ag-charts-community";
import {
AbstractModuleInstance as AbstractModuleInstance15,
BaseProperties as BaseProperties24,
ChartAxisDirection as ChartAxisDirection30,
Property as Property62,
ZIndexMap as ZIndexMap10,
cachedTextMeasurer as cachedTextMeasurer3,
calcLineHeight as calcLineHeight5
} from "ag-charts-core";
var { LayoutElement: LayoutElement5, Group: Group8, Label: Label5, Rect: Rect5, Text } = _ModuleSupport121;
var chartConfigurations = {
ohlc: 2 /* Open */ | 4 /* Close */ | 8 /* Low */ | 16 /* High */ | 32 /* Volume */,
candlestick: 2 /* Open */ | 4 /* Close */ | 8 /* Low */ | 16 /* High */ | 32 /* Volume */,
"hollow-candlestick": 2 /* Open */ | 4 /* Close */ | 8 /* Low */ | 16 /* High */ | 32 /* Volume */,
line: 64 /* UnlabelledClose */ | 32 /* Volume */,
"step-line": 64 /* UnlabelledClose */ | 32 /* Volume */,
hlc: 128 /* NeutralClose */ | 8 /* Low */ | 16 /* High */ | 32 /* Volume */,
"high-low": 512 /* NeutralLow */ | 256 /* NeutralHigh */ | 32 /* Volume */
};
var itemIdMap = {
up: "positive",
down: "negative"
};
var neutralColorMap = {
hlc: "altNeutral"
};
var StatusBarBackground = class extends BaseProperties24 {
constructor() {
super(...arguments);
this.fill = "black";
this.fillOpacity = 1;
}
};
__decorateClass([
Property62
], StatusBarBackground.prototype, "fill", 2);
__decorateClass([
Property62
], StatusBarBackground.prototype, "fillOpacity", 2);
var StatusBar = class extends AbstractModuleInstance15 {
constructor(ctx) {
super();
this.ctx = ctx;
this.enabled = false;
this.openKey = void 0;
this.highKey = void 0;
this.lowKey = void 0;
this.closeKey = void 0;
this.volumeKey = void 0;
this.title = new Label5();
this.positive = new Label5();
this.negative = new Label5();
this.neutral = new Label5();
this.altNeutral = new Label5();
this.background = new StatusBarBackground();
this.layoutStyle = "block";
this.id = "status-bar";
this.layer = new Group8({
name: "StatusBar",
zIndex: ZIndexMap10.STATUS_BAR
});
this.labelGroup = this.layer.appendChild(new _ModuleSupport121.TranslatableGroup());
this.backgroundNode = this.labelGroup.appendChild(new Rect5());
this.labels = [
{
label: "O",
configuration: 2 /* Open */,
title: this.labelGroup.appendChild(new Text()),
value: this.labelGroup.appendChild(new Text()),
id: "openValue",
key: "openKey",
domain: void 0,
formatter: new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
})
},
{
label: "H",
configuration: 16 /* High */,
title: this.labelGroup.appendChild(new Text()),
value: this.labelGroup.appendChild(new Text()),
id: "highValue",
key: "highKey",
domain: void 0,
formatter: new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
})
},
{
label: "H",
configuration: 256 /* NeutralHigh */,
title: this.labelGroup.appendChild(new Text()),
value: this.labelGroup.appendChild(new Text()),
style: "neutral",
id: "highValue",
key: "highKey",
domain: void 0,
formatter: new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
})
},
{
label: "L",
configuration: 8 /* Low */,
title: this.labelGroup.appendChild(new Text()),
value: this.labelGroup.appendChild(new Text()),
id: "lowValue",
key: "lowKey",
domain: void 0,
formatter: new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
})
},
{
label: "L",
configuration: 512 /* NeutralLow */,
title: this.labelGroup.appendChild(new Text()),
value: this.labelGroup.appendChild(new Text()),
style: "neutral",
id: "lowValue",
key: "lowKey",
domain: void 0,
formatter: new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
})
},
{
label: "C",
configuration: 4 /* Close */,
title: this.labelGroup.appendChild(new Text()),
value: this.labelGroup.appendChild(new Text()),
id: "closeValue",
key: "closeKey",
domain: void 0,
formatter: new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
})
},
{
label: "C",
configuration: 128 /* NeutralClose */,
title: this.labelGroup.appendChild(new Text()),
value: this.labelGroup.appendChild(new Text()),
id: "closeValue",
key: "closeKey",
style: "neutral",
domain: void 0,
formatter: new Intl.NumberFormat("en-US", {
minimumFractionDigits: 2,
maximumFractionDigits: 2
})
},
{
label: "",
configuration: 64 /* UnlabelledClose */,
title: this.labelGroup.appendChild(new Text()),
value: this.labelGroup.appendChild(new Text()),
style: "neutral",
id: "closeValue",
key: "closeKey",
domain: void 0,
formatter: new Intl.NumberFormat("en-US", {
notation: "compact",
minimumFractionDigits: 2,
maximumFractionDigits: 2
})
},
{
label: "Vol",
configuration: 32 /* Volume */,
title: this.labelGroup.appendChild(new Text()),
value: this.labelGroup.appendChild(new Text()),
id: "volumeValue",
key: "volumeKey",
domain: void 0,
formatter: new Intl.NumberFormat("en-US", {
notation: "compact",
minimumFractionDigits: 2,
maximumFractionDigits: 2
})
}
];
this.highlightManager = ctx.highlightManager;
this.labelGroup.visible = false;
this.cleanup.register(
ctx.scene.attachNode(this.layer),
ctx.layoutManager.registerElement(LayoutElement5.Overlay, (e) => this.startPerformLayout(e)),
ctx.eventsHub.on("layout:complete", (e) => this.onLayoutComplete(e)),
ctx.eventsHub.on("highlight:change", () => this.updateHighlight()),
ctx.eventsHub.on("data:update", (data) => {
this.chartData = data;
})
);
}
updateDomainsFromSeries() {
if (!this.enabled)
return;
const series = this.ctx.chartService.series;
if (series.length === 0)
return;
let priceDomain;
let volumeDomain;
for (const s of series) {
const domainResult = s.getDomain(ChartAxisDirection30.Y);
const yDomain = domainResult?.domain;
if (!Array.isArray(yDomain) || yDomain.length < 2)
continue;
if (s.type === "bar") {
volumeDomain = [yDomain[0], yDomain.at(-1)];
} else {
priceDomain = [yDomain[0], yDomain.at(-1)];
}
}
for (const label of this.labels) {
const key = this[label.key];
if (key == null) {
label.domain = void 0;
continue;
}
label.domain = label.key === "volumeKey" ? volumeDomain : priceDomain;
}
}
startPerformLayout({ layoutBox }) {
this.labelGroup.translationX = 0;
this.labelGroup.translationY = 0;
if (!this.enabled) {
this.labelGroup.visible = false;
return;
}
this.updateDomainsFromSeries();
const innerSpacing = 4;
const outerSpacing = 12;
const spacingAbove = 0;
const spacingBelow = 8;
this.labelGroup.translationY = layoutBox.y + spacingAbove;
const maxFontSize = Math.max(this.title.fontSize, this.positive.fontSize, this.negative.fontSize);
const lineHeight = calcLineHeight5(maxFontSize);
const labelConfigurations = chartConfigurations[this.getChartType()] ?? 0;
let left = 0;
let offsetTop;
let textVAlign = "alphabetic";
if (this.layoutStyle === "block") {
layoutBox.shrink(spacingAbove + lineHeight + spacingBelow, "top");
offsetTop = maxFontSize + (lineHeight - maxFontSize) / 2;
} else {
const { title } = this.ctx.chartService;
textVAlign = "top";
offsetTop = spacingAbove + title.padding;
if (title.enabled) {
const titleBox = title.node.getBBox();
left = titleBox.x + titleBox.width + outerSpacing;
} else {
left = title.padding;
}
}
for (const { label, configuration, title, value, domain, formatter } of this.labels) {
if (domain == null || (labelConfigurations & configuration) === 0) {
title.visible = false;
value.visible = false;
continue;
}
const positiveTextMeasurer = cachedTextMeasurer3(this.positive);
const negativeTextMeasurer = cachedTextMeasurer3(this.negative);
const maxValueWidth = Math.max(
positiveTextMeasurer.textWidth(formatter.format(domain[0])),
positiveTextMeasurer.textWidth(formatter.format(domain[1])),
negativeTextMeasurer.textWidth(formatter.format(domain[0])),
negativeTextMeasurer.textWidth(formatter.format(domain[1]))
);
title.visible = true;
value.visible = true;
const titleMetrics = cachedTextMeasurer3(this.title).measureLines(label);
title.setFont(this.title);
title.fill = this.title.color;
title.text = label;
title.textBaseline = textVAlign;
title.y = offsetTop;
title.x = left;
left += titleMetrics.width + innerSpacing;
value.textBaseline = textVAlign;
value.y = offsetTop;
value.x = left;
left += maxValueWidth + outerSpacing;
}
this.backgroundNode.x = 0;
this.backgroundNode.y = 0;
this.backgroundNode.width = left - outerSpacing;
this.backgroundNode.height = lineHeight + spacingAbove + spacingBelow;
this.backgroundNode.fill = this.background.fill;
this.backgroundNode.fillOpacity = this.background.fillOpacity;
}
onLayoutComplete(opts) {
this.labelGroup.translationX = opts.series.rect.x;
this.updateHighlight();
}
updateHighlight() {
if (!this.enabled)
return;
const activeHighlight = this.highlightManager.getActiveHighlight();
const datum = activeHighlight?.datum ?? this.chartData?.data?.at(-1);
if (datum == null) {
this.labelGroup.visible = false;
return;
}
this.labelGroup.visible = true;
const itemId = activeHighlight?.itemId;
let baseStyle = itemId == null ? void 0 : itemIdMap[itemId];
if (baseStyle == null && this.openKey != null && this.closeKey != null) {
if (datum[this.openKey] < datum[this.closeKey]) {
baseStyle = "positive";
} else {
baseStyle = "negative";
}
}
for (const { domain, value, key, formatter, style } of this.labels) {
if (domain == null)
continue;
let labelStyle = style ?? baseStyle ?? "neutral";
if (labelStyle === "neutral") {
labelStyle = neutralColorMap[this.getChartType()] ?? labelStyle;
}
const datumKey = this[key];
const datumValue = datumKey == null ? void 0 : datum?.[datumKey];
value.setFont(this[labelStyle]);
value.fill = this[labelStyle].color;
value.text = typeof datumValue === "number" ? formatter.format(datumValue) : "";
}
}
getChartType() {
let chartType = this.ctx.chartService.publicApi?.getOptions()?.chartType;
if (chartType == null || chartConfigurations[chartType] == null) {
chartType = "candlestick";
}
return chartType;
}
};
__decorateClass([
Property62
], StatusBar.prototype, "enabled", 2);
__decorateClass([
Property62
], StatusBar.prototype, "openKey", 2);
__decorateClass([
Property62
], StatusBar.prototype, "highKey", 2);
__decorateClass([
Property62
], StatusBar.prototype, "lowKey", 2);
__decorateClass([
Property62
], StatusBar.prototype, "closeKey", 2);
__decorateClass([
Property62
], StatusBar.prototype, "volumeKey", 2);
__decorateClass([
Property62
], StatusBar.prototype, "title", 2);
__decorateClass([
Property62
], StatusBar.prototype, "positive", 2);
__decorateClass([
Property62
], StatusBar.prototype, "negative", 2);
__decorateClass([
Property62
], StatusBar.prototype, "neutral", 2);
__decorateClass([
Property62
], StatusBar.prototype, "altNeutral", 2);
__decorateClass([
Property62
], StatusBar.prototype, "background", 2);
__decorateClass([
Property62
], StatusBar.prototype, "layoutStyle", 2);
// packages/ag-charts-enterprise/src/features/status-bar/statusBarModule.ts
var StatusBarModule = {
type: "plugin",
name: "statusBar",
chartType: "cartesian",
enterprise: true,
version: VERSION25,
themeTemplate: {
enabled: false,
layoutStyle: DEFAULT_CAPTION_LAYOUT_STYLE,
title: {
color: { $ref: "textColor" },
fontFamily: { $ref: "fontFamily" },
fontSize: { $ref: "fontSize" },
fontWeight: { $ref: "fontWeight" }
},
positive: {
color: { $palette: "up.stroke" },
fontFamily: { $ref: "fontFamily" },
fontSize: { $ref: "fontSize" },
fontWeight: { $ref: "fontWeight" }
},
negative: {
color: { $palette: "down.stroke" },
fontFamily: { $ref: "fontFamily" },
fontSize: { $ref: "fontSize" },
fontWeight: { $ref: "fontWeight" }
},
neutral: {
color: { $palette: "neutral.stroke" },
fontFamily: { $ref: "fontFamily" },
fontSize: { $ref: "fontSize" },
fontWeight: { $ref: "fontWeight" }
},
background: {
fill: { $ref: "chartBackgroundColor" },
fillOpacity: 0.5
},
altNeutral: {
color: "gray",
fontFamily: { $ref: "fontFamily" },
fontSize: { $ref: "fontSize" },
fontWeight: { $ref: "fontWeight" }
}
},
create: (ctx) => new StatusBar(ctx)
};
// packages/ag-charts-enterprise/src/features/sync/syncModule.ts
import { VERSION as VERSION26 } from "ag-charts-community";
import { boolean as boolean14, string as string8, union as union3 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/sync/chartSync.ts
import { _ModuleSupport as _ModuleSupport122 } from "ag-charts-community";
import {
AsyncAwaitQueue,
BaseProperties as BaseProperties25,
ChartAxisDirection as ChartAxisDirection31,
ChartUpdateType as ChartUpdateType7,
Debug as Debug12,
Logger as Logger12,
ObserveChanges as ObserveChanges5,
Property as Property63,
arraysEqual,
definedZoomState,
findMinMax as findMinMax4,
isDate as isDate3,
isDefined as isDefined2,
isFiniteNumber,
isObjectWithStringProperty,
unique
} from "ag-charts-core";
var { CartesianAxis, ContinuousScale: ContinuousScale4, TimeScale, UnitTimeScale, TooltipManager } = _ModuleSupport122;
var debug = Debug12.create("sync");
function getDirectionKeys(series, primary, secondary) {
const primaryKeys = series.getKeys(primary);
const secondaryKeys = series.getKeys(secondary);
if (series.shouldFlipXY?.()) {
return [secondaryKeys, primaryKeys];
}
return [primaryKeys, secondaryKeys];
}
function syncedDirections(axes = "x") {
switch (axes) {
case "x":
return [ChartAxisDirection31.X];
case "y":
return [ChartAxisDirection31.Y];
case "xy":
return [ChartAxisDirection31.X, ChartAxisDirection31.Y];
}
}
function domainChanged(scale, a, b) {
if (TimeScale.is(scale) || UnitTimeScale.is(scale)) {
return !arraysEqual(
a.map((x) => x?.valueOf()),
b.map((x) => x?.valueOf())
);
} else {
return !arraysEqual(a, b);
}
}
var ChartSync = class extends BaseProperties25 {
constructor(moduleContext) {
super();
this.moduleContext = moduleContext;
this.enabled = false;
this.axes = "x";
this.nodeInteraction = true;
this.zoom = true;
this.domainMode = "id";
this.domainSync = new AsyncAwaitQueue();
}
updateSiblings(groupId) {
const { syncManager } = this.moduleContext;
for (const chart of syncManager.getGroupSiblings(groupId ?? this.groupId)) {
debug("ChartSync.updateSiblings()", chart.id, chart);
this.updateChart(chart);
}
}
updateChart(chart, updateType = ChartUpdateType7.PROCESS_DOMAIN) {
debug("ChartSync.updateChart()", chart.id, ChartUpdateType7[updateType], chart);
if (updateType === ChartUpdateType7.PROCESS_DOMAIN) {
chart.ctx.updateService.update(updateType, { forceNodeDataRefresh: true });
} else {
chart.ctx.updateService.update(updateType);
}
}
enabledZoomSync() {
const { eventsHub } = this.moduleContext;
this.disableZoomSync?.();
this.disableZoomSync = eventsHub.on("zoom:change-complete", (e) => this.onZoom(e));
}
onZoom(e) {
const { syncManager } = this.moduleContext;
for (const chart of syncManager.getGroupSiblings(this.groupId)) {
const syncModule = chart.modulesManager.getModule("sync");
if (!syncModule?.zoom)
continue;
const zoomModule = chart.modulesManager.getModule("zoom");
if (!zoomModule)
continue;
const zoom = this.prepareZoomUpdate();
if (e.source !== "sync") {
debug("ChartsSyncManager.enabledZoomSync()", chart.id, zoom);
zoomModule.updateSyncZoom(zoom);
}
}
}
enabledNodeInteractionSync() {
this.disableNodeInteractionSync?.();
const offHighlightChange = this.moduleContext.eventsHub.on(
"highlight:change",
this.onHighlightChange.bind(this)
);
const offActiveChangeListener = this.moduleContext.eventsHub.on(
"active:load-memento",
this.onActiveLoadMemento.bind(this)
);
this.disableNodeInteractionSync = () => {
offHighlightChange();
offActiveChangeListener();
};
}
onHighlightChange(event) {
const { syncManager } = this.moduleContext;
if (event.callerId.endsWith("-sync"))
return;
debug("ChartSync.onHighlightChange()", event);
const series = event.currentHighlight?.series;
const [mainDirection] = syncedDirections(this.axes);
const secondaryDirection = mainDirection === ChartAxisDirection31.X ? ChartAxisDirection31.Y : ChartAxisDirection31.X;
const [primaryKeys, secondaryKeys] = series ? getDirectionKeys(series, mainDirection, secondaryDirection) : [];
const datum = readDatum(event.currentHighlight);
let eventValue = primaryKeys?.[0] ? datum?.[primaryKeys[0]] : void 0;
let valueIsDate = false;
if (isDate3(eventValue)) {
valueIsDate = true;
eventValue = eventValue.getTime();
}
if (!event.currentHighlight?.datum) {
for (const chart of syncManager.getGroupSiblings(this.groupId)) {
const syncModule = chart.modulesManager.getModule("sync");
if (!syncModule?.nodeInteraction)
continue;
chart.ctx.highlightManager.updateHighlight(`${chart.id}-sync`, void 0, true);
chart.ctx.tooltipManager.removeTooltip(`${chart.id}-sync`, void 0, true);
}
return;
}
const useSecondaryDirectionKey = syncManager.getGroupSyncMode(this.groupId) === "multi-series";
this.findMatchingHighlightNodes(
mainDirection,
secondaryDirection,
useSecondaryDirectionKey ? secondaryKeys : [],
valueIsDate,
eventValue,
event
);
}
onActiveLoadMemento(event) {
const { activeItem, chartId } = event;
if (activeItem === void 0) {
this.moduleContext.highlightManager.updateHighlight(`${chartId}-sync`, void 0, false);
this.moduleContext.tooltipManager.removeTooltip(`${chartId}-sync`, void 0, false);
for (const chart of this.moduleContext.syncManager.getGroupSiblings(this.groupId)) {
chart.onSyncActiveClear();
}
}
}
findMatchingHighlightNodes(primaryDirection, secondaryDirection, secondaryKeys, valueIsDate, eventValue, event) {
const { syncManager } = this.moduleContext;
debug("ChartSync.findMatchingHighlightNodes()", {
mainDirection: primaryDirection,
secondaryKeys
});
for (const chart of syncManager.getGroupSiblings(this.groupId)) {
const syncModule = chart.modulesManager.getModule("sync");
if (!syncModule?.nodeInteraction)
continue;
let dispatched = false;
for (const axis of chart.axes) {
if (!CartesianAxis.is(axis) || axis.direction !== primaryDirection)
continue;
const matchingNodes = chart.series.filter((s) => {
if (!s.visible)
return false;
if (secondaryKeys.length > 0) {
const [, seriesKeys] = getDirectionKeys(s, primaryDirection, secondaryDirection);
return secondaryKeys.every((key) => seriesKeys.includes(key));
}
return true;
}).map(this.findMatchingNodes(axis, primaryDirection, valueIsDate, eventValue)).filter(isDefined2);
if (matchingNodes.length === 1 && matchingNodes[0]?.nodeDatum !== chart.ctx.highlightManager.getActiveHighlight()) {
this.dispatchHighlightUpdate(chart, matchingNodes[0].nodeDatum);
dispatched = true;
break;
}
}
if (!dispatched) {
debug("ChartSync.findMatchingHighlightNodes() - no matching nodes", chart.id, event);
this.dispatchHighlightUpdate(chart);
}
}
}
findMatchingNodes(axis, mainDirection, valueIsDate, eventValue) {
return (series) => {
const seriesKeyAxis = series.getKeyAxis(axis.direction);
if (seriesKeyAxis !== axis.id)
return;
const nodeData = series.contextNodeData?.nodeData ?? [];
if (!nodeData?.length)
return;
const firstNode = nodeData[0];
const mainDirectionKey = `${mainDirection}Key`;
if (!isObjectWithStringProperty(firstNode, mainDirectionKey))
return;
const valueKey = firstNode[mainDirectionKey];
const nodeDatum = nodeData.find((datum) => {
const nodeValue = datum.datum[valueKey];
return valueIsDate ? nodeValue.getTime() === eventValue : nodeValue === eventValue;
});
return nodeDatum ? { series, nodeDatum } : null;
};
}
dispatchHighlightUpdate(chart, nodeDatum) {
debug("ChartSync.dispatchHighlightUpdate()", chart.id, nodeDatum);
const delayed = nodeDatum == null;
chart.ctx.highlightManager.updateHighlight(`${chart.id}-sync`, nodeDatum, delayed);
const tooltipEnabled = nodeDatum?.series.tooltipEnabled ?? chart.tooltip.enabled;
if (nodeDatum && tooltipEnabled) {
const bbox = chart.seriesAreaBoundingBox;
const canvasX = bbox.x + (nodeDatum.midPoint?.x ?? nodeDatum.point?.x ?? 0);
const canvasY = bbox.y + (nodeDatum.midPoint?.y ?? nodeDatum.point?.y ?? 0);
const tooltipMeta = TooltipManager.makeTooltipMeta(
{ type: "pointermove", canvasX, canvasY },
nodeDatum.series,
nodeDatum,
void 0
);
chart.ctx.tooltipManager.updateTooltip(
`${chart.id}-sync`,
tooltipMeta,
chart.getTooltipContent(nodeDatum.series, nodeDatum.datumIndex, nodeDatum, "tooltip")
);
} else {
chart.ctx.tooltipManager.removeTooltip(`${chart.id}-sync`, void 0, true);
}
this.updateChart(chart, ChartUpdateType7.SERIES_UPDATE);
}
async getSyncedDomain(axis) {
if (!CartesianAxis.is(axis) || this.axes !== "xy" && this.axes !== axis.direction) {
return;
}
const { groupState, directionDomains, idDomains, positionDomains } = this.updateDomainState(axis);
this.validateAxis(axis, groupState);
await this.waitForDomainsToBeReady();
if (this.domainMode === "position") {
return this.calculateDerivedDomain(axis, positionDomains);
}
if (this.domainMode === "direction") {
return this.calculateDerivedDomain(axis, directionDomains);
}
return this.calculateDerivedDomain(axis, idDomains);
}
updateDomainState(axis) {
var _a, _b, _c, _d, _e;
const { syncManager } = this.moduleContext;
const chartId = syncManager.getChart().id;
const axisId = axis.id;
const groupState = syncManager.getGroupState(this.groupId);
if (!groupState)
throw new Error("AG Charts - no GroupState for groupId: " + this.groupId);
const domainsByDirection = groupState.domains ?? (groupState.domains = {});
const directionDomains = domainsByDirection[_a = axis.direction] ?? (domainsByDirection[_a] = { derived: [], sources: {}, dirty: true });
const chartDirectionDomains = (_b = directionDomains.sources)[chartId] ?? (_b[chartId] = {});
chartDirectionDomains[axisId] = axis.dataDomain.domain;
directionDomains.dirty = true;
const domainsById = groupState.domainsById ?? (groupState.domainsById = {});
const idDomains = domainsById[axisId] ?? (domainsById[axisId] = { derived: [], sources: {}, dirty: true });
const chartIdDomains = (_c = idDomains.sources)[chartId] ?? (_c[chartId] = {});
chartIdDomains[axisId] = axis.dataDomain.domain;
idDomains.dirty = true;
const domainsByPosition = groupState.domainsByPosition ?? (groupState.domainsByPosition = {});
const positionDomains = domainsByPosition[_d = axis.position] ?? (domainsByPosition[_d] = { derived: [], sources: {}, dirty: true });
const chartPositionDomains = (_e = positionDomains.sources)[chartId] ?? (_e[chartId] = {});
chartPositionDomains[axisId] = axis.dataDomain.domain;
positionDomains.dirty = true;
return { groupState, directionDomains, idDomains, positionDomains };
}
validateAxis(axis, groupState) {
const multiSeries = this.moduleContext.syncManager.getGroupSyncMode(this.groupId) === "multi-series";
if (!syncedDirections(this.axes).includes(axis.direction))
return;
if (multiSeries) {
this.validateMultiSeries(axis, groupState);
} else {
this.validateSingleSeries(axis, groupState);
}
}
validateMultiSeries(axis, groupState) {
const { min, max, nice, reverse } = axis;
const matchingKeys = new Set(axis.boundSeries.flatMap((s) => s.getKeys(axis.direction)));
for (const member of groupState.members) {
const { axes, modulesManager } = member;
const syncModule = modulesManager.getModule("sync");
const memberSyncDirections = syncedDirections(syncModule?.axes);
const keyMatchedAxes = axes.filter((a) => memberSyncDirections.includes(a.direction)).filter((a) => a.boundSeries.some((s) => s.getKeys(a.direction).some((k) => matchingKeys.has(k))));
if (keyMatchedAxes.length === 0)
continue;
const [firstAxis] = keyMatchedAxes;
if (firstAxis.min !== min || firstAxis.max !== max || firstAxis.nice !== nice || firstAxis.reverse !== reverse) {
Logger12.warnOnce(
"To allow synchronization, ensure that all synchronized axes with matching keys have matching min, max, nice, and reverse properties."
);
this.enabled = false;
return;
}
}
}
validateSingleSeries(axis, groupState) {
const members = groupState.members;
const [{ axes: syncAxes }] = members;
const { direction, min, max, nice, reverse } = axis;
for (const nextAxis of syncAxes) {
if (direction !== nextAxis.direction)
continue;
if (nice !== nextAxis.nice || reverse !== nextAxis.reverse || min !== nextAxis.min && (isFiniteNumber(min) || isFiniteNumber(nextAxis.min)) || max !== nextAxis.max && (isFiniteNumber(max) || isFiniteNumber(nextAxis.max))) {
Logger12.warnOnce(
"To allow synchronization, ensure that all charts have matching min, max, nice, and reverse properties on the synchronized axes."
);
this.enabled = false;
return;
}
}
}
calculateDerivedDomain(axis, domains) {
if (!domains.dirty)
return domains.derived;
let previousDerived = domains.derived;
const newDerivedBySource = Object.values(domains.sources).map((d) => Object.values(d));
let newDerived;
if (ContinuousScale4.is(axis.scale)) {
newDerived = newDerivedBySource.flat(2);
} else {
newDerived = newDerivedBySource.flat().toSorted((a, b) => a.length > b.length ? -1 : 1).flat();
}
domains.derived = unique(newDerived);
if (ContinuousScale4.is(axis.scale)) {
previousDerived = findMinMax4(previousDerived);
domains.derived = findMinMax4(domains.derived);
}
domains.dirty = false;
if (domainChanged(axis.scale, previousDerived, domains.derived)) {
debug(axis.id, "updated", { before: previousDerived, after: domains.derived });
this.updateSiblings();
}
return domains.derived;
}
removeAxis(axis) {
if (!CartesianAxis.is(axis) || this.axes !== "xy" && this.axes !== axis.direction) {
return;
}
const { syncManager } = this.moduleContext;
const syncGroup = syncManager.getGroupState(this.groupId);
const chartId = syncManager.getChart().id;
const axisId = axis.id;
delete syncGroup?.domains?.[axis.direction]?.sources?.[chartId]?.[axisId];
delete syncGroup?.domainsByPosition?.[axis.position]?.sources?.[chartId]?.[axisId];
delete syncGroup?.domainsById?.[axisId]?.sources?.[chartId]?.[axisId];
}
async waitForDomainsToBeReady() {
const { syncManager } = this.moduleContext;
let count = 0;
while (syncManager.getGroupMembers(this.groupId).some((c) => c.syncStatus === "init")) {
debug("ChartSync.waitForDomainsToBeReady() - waiting for all domains to be calculated", this.groupId);
await this.domainSync.waitForCompletion();
count++;
}
if (count > 0) {
debug("ChartSync.waitForDomainsToBeReady() - waited for", count, "iterations");
}
this.domainSync.notify();
}
prepareZoomUpdate() {
const { zoomManager } = this.moduleContext;
const zoom = zoomManager.getZoom();
if (this.axes === "x") {
delete zoom?.y;
} else if (this.axes === "y") {
delete zoom?.x;
}
return definedZoomState(zoom);
}
onEnabledChange() {
const { syncManager, highlightManager } = this.moduleContext;
if (this.enabled) {
syncManager.subscribe(this.groupId);
highlightManager.unhighlightDelay = 0;
} else {
syncManager.unsubscribe(this.groupId);
highlightManager.unhighlightDelay = 100;
}
this.updateSiblings();
this.onNodeInteractionChange();
this.onZoomChange();
}
onGroupIdChange(newValue, oldValue) {
if (!this.enabled || newValue === oldValue)
return;
const { syncManager } = this.moduleContext;
syncManager.unsubscribe(oldValue);
syncManager.subscribe(newValue);
this.updateSiblings(oldValue);
this.updateSiblings(newValue);
}
onAxesChange() {
if (!this.enabled)
return;
const { syncManager } = this.moduleContext;
this.updateChart(syncManager.getChart());
}
onNodeInteractionChange() {
if (this.enabled && this.nodeInteraction) {
this.enabledNodeInteractionSync();
} else {
this.disableNodeInteractionSync?.();
}
}
onZoomChange() {
if (this.enabled && this.zoom) {
this.enabledZoomSync();
} else {
this.disableZoomSync?.();
}
}
destroy() {
const { syncManager } = this.moduleContext;
syncManager.unsubscribe(this.groupId);
this.updateSiblings();
this.disableZoomSync?.();
}
};
ChartSync.className = "Sync";
__decorateClass([
Property63,
ObserveChanges5((target) => target.onEnabledChange())
], ChartSync.prototype, "enabled", 2);
__decorateClass([
Property63,
ObserveChanges5((target, newValue, oldValue) => target.onGroupIdChange(newValue, oldValue))
], ChartSync.prototype, "groupId", 2);
__decorateClass([
Property63,
ObserveChanges5((target) => target.onAxesChange())
], ChartSync.prototype, "axes", 2);
__decorateClass([
Property63,
ObserveChanges5((target) => target.onNodeInteractionChange())
], ChartSync.prototype, "nodeInteraction", 2);
__decorateClass([
Property63,
ObserveChanges5((target) => target.onZoomChange())
], ChartSync.prototype, "zoom", 2);
__decorateClass([
Property63,
ObserveChanges5((target) => target.onAxesChange())
], ChartSync.prototype, "domainMode", 2);
// packages/ag-charts-enterprise/src/features/sync/syncModule.ts
var SyncModule = {
type: "plugin",
name: "sync",
chartType: "cartesian",
enterprise: true,
version: VERSION26,
options: {
enabled: boolean14,
groupId: string8,
axes: union3("x", "y", "xy"),
nodeInteraction: boolean14,
zoom: boolean14
},
themeTemplate: { enabled: false },
create: (ctx) => new ChartSync(ctx)
};
// packages/ag-charts-enterprise/src/features/zoom/zoomModule.ts
import { VERSION as VERSION27 } from "ag-charts-community";
import {
arrayOfDefs as arrayOfDefs4,
boolean as boolean15,
or as or2,
positiveNumber as positiveNumber7,
ratio as ratio6,
strictUnion as strictUnion2,
string as string9,
toolbarButtonOptionsDefs as toolbarButtonOptionsDefs2,
undocumented as undocumented8,
union as union4
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/zoom/zoom.ts
import { _ModuleSupport as _ModuleSupport133 } from "ag-charts-community";
import {
AbstractModuleInstance as AbstractModuleInstance16,
ActionOnSet as ActionOnSet9,
ChartAxisDirection as ChartAxisDirection40,
ChartUpdateType as ChartUpdateType8,
Property as Property67,
ProxyProperty as ProxyProperty3,
UNIT_MAX as UNIT_MAX4,
UNIT_MIN as UNIT_MIN4,
debounce as debounce3,
definedZoomState as definedZoomState11,
entries as entries10,
roundTo
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/zoom/scenes/zoomRect.ts
import { _ModuleSupport as _ModuleSupport123 } from "ag-charts-community";
import { ZIndexMap as ZIndexMap11 } from "ag-charts-core";
var VALID_COLOR = "#2196f3";
var INVALID_COLOR = "#8a8a8a";
var ZoomRect = class extends _ModuleSupport123.Rect {
constructor() {
super();
this.fill = VALID_COLOR;
this.fillOpacity = 0.2;
this.zIndex = ZIndexMap11.ZOOM_SELECTION;
}
updateValid() {
this.fill = VALID_COLOR;
}
updateInvalid() {
this.fill = INVALID_COLOR;
}
};
ZoomRect.className = "ZoomRect";
// packages/ag-charts-enterprise/src/features/zoom/zoomAutoScale.ts
import "ag-charts-community";
import {
BaseProperties as BaseProperties26,
ChartAxisDirection as ChartAxisDirection32,
Property as Property64,
isFiniteNumber as isFiniteNumber2,
objectsEqual,
strictObjectKeys
} from "ag-charts-core";
var ZoomAutoScalingProperties = class extends BaseProperties26 {
constructor() {
super();
this.enabled = false;
this.padding = 0;
}
};
__decorateClass([
Property64
], ZoomAutoScalingProperties.prototype, "enabled", 2);
__decorateClass([
Property64
], ZoomAutoScalingProperties.prototype, "padding", 2);
var ZoomAutoScaler = class {
constructor(properties, zoomManager, deps, eventsHub, eventsCleanup) {
this.properties = properties;
this.zoomManager = zoomManager;
this.deps = deps;
this.manuallyAdjusted = false;
eventsCleanup.register(
eventsHub.on("zoom:save-memento", (e) => this.onSaveMemento(e)),
eventsHub.on("zoom:load-memento", (e) => this.onLoadMemento(e)),
eventsHub.on("zoom:change-request", (e) => this.onChangeRequest(e))
);
}
get enabled() {
return this.deps.enabled && this.properties.enabled && !this.manuallyAdjusted;
}
onManualAdjustment(direction) {
if (direction === ChartAxisDirection32.Y) {
this.manuallyAdjusted = true;
}
}
onChangeRequest(event) {
const hasYAxisChange = this.hasYAxisChange(event);
if (event.sourceDetail === "scrollbar" && hasYAxisChange) {
this.manuallyAdjusted = true;
}
if (event.isReset && hasYAxisChange) {
this.manuallyAdjusted = false;
}
if (this.enabled) {
const constrainedZoom = this.autoScaleYZoom(event.state);
if (constrainedZoom) {
event.constrainChanges(constrainedZoom);
}
}
}
hasYAxisChange(event) {
for (const id of event.changedAxes) {
if (event.state[id]?.direction === ChartAxisDirection32.Y) {
return true;
}
}
return false;
}
onSaveMemento(event) {
event.memento.autoScaledAxes = this.enabled ? ["y"] : void 0;
}
onLoadMemento(event) {
const { zoom, memento, navigatorModule, zoomModule } = event;
if (!navigatorModule || zoomModule) {
let yAutoScale = memento?.autoScaledAxes?.includes("y");
if (memento?.rangeY) {
yAutoScale ?? (yAutoScale = false);
zoom.y = this.zoomManager.rangeToRatioDirection(ChartAxisDirection32.Y, memento.rangeY) ?? {
min: 0,
max: 1
};
} else if (memento?.ratioY) {
yAutoScale ?? (yAutoScale = false);
zoom.y = {
min: memento.ratioY.start ?? 0,
max: memento.ratioY.end ?? 1
};
} else {
yAutoScale ?? (yAutoScale = true);
const autoZoomY = yAutoScale ? this.getAutoScaleYZoom(zoom.x) : void 0;
zoom.y = autoZoomY ?? { min: 0, max: 1 };
}
if (yAutoScale != void 0) {
this.manuallyAdjusted = !yAutoScale;
}
}
}
getAutoScaleYZoom(zoomX) {
if (!this.enabled)
return;
const { padding: padding2 } = this.properties;
let yZoom;
if (this.deps.enableIndependentAxes) {
yZoom = this.primaryAxisZoom(ChartAxisDirection32.Y, zoomX, { padding: padding2 });
} else {
yZoom = this.combinedAxisZoom(ChartAxisDirection32.Y, zoomX, { padding: padding2 });
}
if (zoomX.min === 0 && zoomX.max === 1) {
return yZoom == null ? void 0 : { min: 0, max: 1 };
} else {
return yZoom;
}
}
autoScaleYZoom(changes) {
const zoom = this.zoomManager.getZoom();
if (zoom && changes) {
const state = this.zoomManager.getAxisZooms();
for (const dir of [ChartAxisDirection32.X, ChartAxisDirection32.Y]) {
for (const id of strictObjectKeys(changes)) {
if (state[id]?.direction === dir) {
zoom[dir] = changes[id];
break;
}
}
}
}
if (zoom?.x == null)
return;
const zoomY = this.getAutoScaleYZoom(zoom.x);
if (zoomY == null || objectsEqual(zoom.y, zoomY))
return;
return this.zoomManager.toCoreZoomState({ x: zoom.x, y: zoomY });
}
zoomBounds(xAxis, yAxis, zoom, padding2) {
const xScale = xAxis.scale;
const xScaleRange = xScale.range;
xScale.range = [0, 1];
const yScale = yAxis.scale;
const yScaleRange = yScale.range;
yScale.range = [0, 1];
let min = 1;
let minPadding = false;
let max = 0;
let maxPadding = false;
for (const series of yAxis.boundSeries) {
if (!series.visible)
continue;
const { connectsToYAxis } = series;
const yValues = series.getRange(ChartAxisDirection32.Y, [zoom.min, zoom.max]);
for (const yValue of yValues) {
const y = yScale.convert(yValue);
if (!Number.isFinite(y))
continue;
if (y < min) {
min = y;
minPadding = !connectsToYAxis || yValue < 0;
}
if (y > max) {
max = y;
maxPadding = !connectsToYAxis || yValue > 0;
}
}
}
if (isFiniteNumber2(yAxis.min)) {
min = 0;
}
if (isFiniteNumber2(yAxis.max)) {
max = 1;
}
xScale.range = xScaleRange;
yScale.range = yScaleRange;
if (min >= max)
return;
const totalPadding = (minPadding ? padding2 : 0) + (maxPadding ? padding2 : 0);
const paddedDelta = Math.min((max - min) * (1 + totalPadding), 1);
if (paddedDelta <= 0)
return;
if (minPadding && maxPadding) {
const mid = (max + min) / 2;
min = mid - paddedDelta / 2;
max = mid + paddedDelta / 2;
} else if (!minPadding && maxPadding) {
max = min + paddedDelta;
} else if (minPadding && !maxPadding) {
min = max - paddedDelta;
}
if (min < 0) {
max += -min;
min = 0;
} else if (max > 1) {
min -= max - 1;
max = 1;
}
return { min, max };
}
primaryAxisZoom(direction, zoom, { padding: padding2 = 0 } = {}) {
const crossDirection = direction === ChartAxisDirection32.X ? ChartAxisDirection32.Y : ChartAxisDirection32.X;
const xAxis = this.zoomManager.getPrimaryAxis(crossDirection);
const yAxis = this.zoomManager.getPrimaryAxis(direction);
if (xAxis == null || yAxis == null)
return;
return this.zoomBounds(xAxis, yAxis, zoom, padding2);
}
combinedAxisZoom(direction, zoom, { padding: padding2 = 0 } = {}) {
const axes = this.zoomManager.getAxes();
const crossDirection = direction === ChartAxisDirection32.X ? ChartAxisDirection32.Y : ChartAxisDirection32.X;
const seriesXAxes = /* @__PURE__ */ new Map();
for (const xAxis of axes) {
if (xAxis.direction !== crossDirection)
continue;
for (const series of xAxis.boundSeries) {
seriesXAxes.set(series, xAxis);
}
}
let min = 1;
let max = 0;
for (const yAxis of axes) {
if (yAxis.direction !== direction)
continue;
for (const series of yAxis.boundSeries) {
const xAxis = seriesXAxes.get(series);
if (xAxis == null)
continue;
const bounds = this.zoomBounds(xAxis, yAxis, zoom, padding2);
if (bounds == null)
return;
min = Math.min(min, bounds.min);
max = Math.max(max, bounds.max);
}
}
const delta3 = 1e-6;
if (min < delta3)
min = 0;
if (max > 1 - delta3)
max = 1;
if (min > max)
return;
return { min, max };
}
};
// packages/ag-charts-enterprise/src/features/zoom/zoomAxisDragger.ts
import { ChartAxisDirection as ChartAxisDirection33, definedZoomState as definedZoomState3 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/features/zoom/zoomUtils.ts
import "ag-charts-community";
import { UNIT_MAX, UNIT_MIN, clamp as clamp10, definedZoomState as definedZoomState2, isNumberEqual as isNumberEqual8, jsonDiff as jsonDiff2 } from "ag-charts-core";
var UNIT_SIZE = UNIT_MAX - UNIT_MIN;
var DEFAULT_ANCHOR_POINT_X = "end";
var DEFAULT_ANCHOR_POINT_Y = "middle";
var ZOOM_VALID_CHECK_DEBOUNCE = 300;
var constrain = (value, min = UNIT_MIN, max = UNIT_MAX) => clamp10(min, value, max);
function dx(zoom) {
return zoom.x.max - zoom.x.min;
}
function dy(zoom) {
return zoom.y.max - zoom.y.min;
}
function isZoomRangeEqual(left, right) {
return isNumberEqual8(left.min, right.min) && isNumberEqual8(left.max, right.max);
}
function isZoomEqual(left, right) {
return isZoomRangeEqual(left.x, right.x) && isZoomRangeEqual(left.y, right.y);
}
function isMaxZoom(zoom) {
return isZoomEqual(zoom, definedZoomState2());
}
function pointToRatio(bbox, x, y) {
if (!bbox)
return { x: 0, y: 0 };
const constrainedX = constrain(x - bbox.x, 0, bbox.x + bbox.width);
const constrainedY = constrain(y - bbox.y, 0, bbox.y + bbox.height);
const rx = 1 / bbox.width * constrainedX;
const ry = 1 - 1 / bbox.height * constrainedY;
return { x: constrain(rx), y: constrain(ry) };
}
function translateZoom(zoom, x, y) {
return {
x: { min: zoom.x.min + x, max: zoom.x.max + x },
y: { min: zoom.y.min + y, max: zoom.y.max + y }
};
}
function scaleZoom(zoom, sx, sy) {
return {
x: { min: zoom.x.min, max: zoom.x.min + dx(zoom) * sx },
y: { min: zoom.y.min, max: zoom.y.min + dy(zoom) * sy }
};
}
function scaleZoomCenter(zoom, sx, sy) {
const dx_ = dx(zoom);
const dy_ = dy(zoom);
const cx = zoom.x.min + dx_ / 2;
const cy = zoom.y.min + dy_ / 2;
return {
x: { min: cx - dx_ * sx / 2, max: cx + dx_ * sx / 2 },
y: { min: cy - dy_ * sy / 2, max: cy + dy_ * sy / 2 }
};
}
function scaleZoomAxisWithAnchor(newState, oldState, anchor, origin) {
const { min, max } = oldState;
const center = min + (max - min) / 2;
const diff8 = newState.max - newState.min;
switch (anchor) {
case "start":
return { min, max: oldState.min + diff8 };
case "end":
return { min: oldState.max - diff8, max };
case "middle":
return { min: center - diff8 / 2, max: center + diff8 / 2 };
case "pointer":
return scaleZoomAxisWithPoint(newState, oldState, origin ?? center);
default:
return { min, max };
}
}
function scaleZoomAxisWithPoint(newState, oldState, origin) {
const newDelta = newState.max - newState.min;
const oldDelta = oldState.max - oldState.min;
const scaledOrigin = origin * (1 - (oldDelta - newDelta));
const translation = origin - scaledOrigin;
const min = newState.min + translation;
const max = newState.max + translation;
return { min, max };
}
function multiplyZoom(zoom, nx, ny) {
return {
x: { min: zoom.x.min * nx, max: zoom.x.max * nx },
y: { min: zoom.y.min * ny, max: zoom.y.max * ny }
};
}
function constrainZoom(zoom) {
return {
x: constrainAxis(zoom.x),
y: constrainAxis(zoom.y)
};
}
function constrainAxis(axis) {
const size = axis.max - axis.min;
let min = axis.max > UNIT_MAX ? UNIT_MAX - size : axis.min;
let max = axis.min < UNIT_MIN ? size : axis.max;
min = Math.max(UNIT_MIN, min);
max = Math.min(UNIT_MAX, max);
return { min, max };
}
function canResetZoom(zoomManager) {
const current = zoomManager.getCoreZoom();
const restore = zoomManager.getRestoredZoom();
return jsonDiff2(current, restore) != null;
}
// packages/ag-charts-enterprise/src/features/zoom/zoomAxisDragger.ts
var ZoomAxisDragger = class {
update(event, direction, anchor, bbox, zoom, axisZoom) {
this.oldZoom ?? (this.oldZoom = definedZoomState3(
direction === ChartAxisDirection33.X ? { ...zoom, x: axisZoom } : { ...zoom, y: axisZoom }
));
this.updateCoords(event.offsetX, event.offsetY);
return this.updateZoom(direction, anchor, bbox);
}
stop() {
this.coords = void 0;
this.oldZoom = void 0;
}
updateCoords(x, y) {
if (this.coords) {
this.coords.x2 = x;
this.coords.y2 = y;
} else {
this.coords = { x1: x, y1: y, x2: x, y2: y };
}
}
updateZoom(direction, anchor, bbox) {
const { coords, oldZoom } = this;
let newZoom = definedZoomState3(oldZoom);
if (!coords || !oldZoom) {
if (direction === ChartAxisDirection33.X)
return newZoom.x;
return newZoom.y;
}
const origin = pointToRatio(bbox, coords.x1, coords.y1);
const target = pointToRatio(bbox, coords.x2, coords.y2);
if (direction === ChartAxisDirection33.X) {
const scaleX = (target.x - origin.x) * dx(oldZoom);
newZoom.x.max += scaleX;
newZoom.x = scaleZoomAxisWithAnchor(newZoom.x, oldZoom.x, anchor, origin.x);
newZoom = constrainZoom(newZoom);
return newZoom.x;
}
const scaleY = (target.y - origin.y) * dy(oldZoom);
newZoom.y.max -= scaleY;
newZoom.y = scaleZoomAxisWithAnchor(newZoom.y, oldZoom.y, anchor, origin.y);
newZoom = constrainZoom(newZoom);
return newZoom.y;
}
};
// packages/ag-charts-enterprise/src/features/zoom/zoomContextMenu.ts
import { _ModuleSupport as _ModuleSupport126 } from "ag-charts-community";
import { definedZoomState as definedZoomState4 } from "ag-charts-core";
var { userInteraction: userInteraction2 } = _ModuleSupport126;
var ZoomContextMenu = class {
constructor(eventsHub, contextMenuRegistry, zoomManager, getModuleProperties, getRect, updateZoom, isZoomValid) {
this.eventsHub = eventsHub;
this.contextMenuRegistry = contextMenuRegistry;
this.zoomManager = zoomManager;
this.getModuleProperties = getModuleProperties;
this.getRect = getRect;
this.updateZoom = updateZoom;
this.isZoomValid = isZoomValid;
}
registerActions(enabled) {
const { contextMenuRegistry } = this;
const action = enabled ? "show" : "hide";
contextMenuRegistry.toggle("zoom-to-cursor", action);
contextMenuRegistry.toggle("pan-to-cursor", action);
contextMenuRegistry.toggle("reset-zoom", action);
if (!enabled) {
return;
}
contextMenuRegistry.builtins.items["zoom-to-cursor"].action = this.onZoomToHere.bind(this);
contextMenuRegistry.builtins.items["pan-to-cursor"].action = this.onPanToHere.bind(this);
contextMenuRegistry.builtins.items["reset-zoom"].action = this.onResetZoom.bind(this);
const shouldEnableZoomToHere = (event) => {
const rect = this.getRect();
if (!rect)
return true;
const origin = pointToRatio(rect, event.x, event.y);
return this.iterateFindNextZoomAtPoint(origin) != null;
};
const shouldEnablePanToHere = () => {
return !isMaxZoom(definedZoomState4(this.zoomManager.getZoom()));
};
const removeListener = this.eventsHub.on("context-menu:setup", (event) => {
contextMenuRegistry.builtins.items["zoom-to-cursor"].enabled = shouldEnableZoomToHere(event);
contextMenuRegistry.builtins.items["pan-to-cursor"].enabled = shouldEnablePanToHere();
contextMenuRegistry.builtins.items["reset-zoom"].enabled = canResetZoom(this.zoomManager);
});
return () => {
removeListener();
contextMenuRegistry.toggle("zoom-to-cursor", "hide");
contextMenuRegistry.toggle("pan-to-cursor", "hide");
contextMenuRegistry.toggle("reset-zoom", "hide");
};
}
computeOrigin(event) {
const rect = this.getRect();
const { enabled } = this.getModuleProperties();
if (!enabled || !rect || !event?.target || !(event instanceof MouseEvent))
return;
const relativeRect = { x: 0, y: 0, width: rect.width, height: rect.height };
return pointToRatio(relativeRect, event.offsetX, event.offsetY);
}
onZoomToHere({ event }) {
const origin = this.computeOrigin(event);
if (!origin)
return;
const zoom = this.iterateFindNextZoomAtPoint(origin);
if (zoom == null)
return;
this.updateZoom(userInteraction2("contextmenu-zoom-to-cursor"), zoom);
}
onPanToHere({ event }) {
const origin = this.computeOrigin(event);
if (!origin)
return;
const zoom = definedZoomState4(this.zoomManager.getZoom());
const scaleX = dx(zoom);
const scaleY = dy(zoom);
const scaledOriginX = origin.x * scaleX;
const scaledOriginY = origin.y * scaleY;
const halfSize = UNIT_SIZE / 2;
let newZoom = {
x: { min: origin.x - halfSize, max: origin.x + halfSize },
y: { min: origin.y - halfSize, max: origin.y + halfSize }
};
newZoom = scaleZoomCenter(newZoom, scaleX, scaleY);
newZoom = translateZoom(newZoom, zoom.x.min - origin.x + scaledOriginX, zoom.y.min - origin.y + scaledOriginY);
this.updateZoom(userInteraction2("contextmenu-pan-to-cursor"), constrainZoom(newZoom));
}
onResetZoom(_actionEvent) {
this.zoomManager.resetZoom(userInteraction2("contextmenu-reset"));
}
iterateFindNextZoomAtPoint(origin) {
const { scrollingStep } = this.getModuleProperties();
for (let i = scrollingStep; i <= 1 - scrollingStep; i += scrollingStep) {
const zoom = this.getNextZoomAtPoint(origin, i);
if (this.isZoomValid(zoom)) {
return zoom;
}
}
}
getNextZoomAtPoint(origin, step) {
const { isScalingX, isScalingY } = this.getModuleProperties();
const zoom = definedZoomState4(this.zoomManager.getZoom());
const scaledOriginX = origin.x * dx(zoom);
const scaledOriginY = origin.y * dy(zoom);
const halfSize = UNIT_SIZE / 2;
let newZoom = {
x: { min: origin.x - halfSize, max: origin.x + halfSize },
y: { min: origin.y - halfSize, max: origin.y + halfSize }
};
newZoom = scaleZoomCenter(
newZoom,
isScalingX ? dx(zoom) * step : UNIT_SIZE,
isScalingY ? dy(zoom) * step : UNIT_SIZE
);
newZoom = translateZoom(newZoom, zoom.x.min - origin.x + scaledOriginX, zoom.y.min - origin.y + scaledOriginY);
return constrainZoom(newZoom);
}
};
// packages/ag-charts-enterprise/src/features/zoom/zoomDOMProxy.ts
import { _ModuleSupport as _ModuleSupport127 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection34, boxEmpty } from "ag-charts-core";
var ZoomDOMProxy = class {
constructor(axesHandlers) {
this.axesHandlers = axesHandlers;
this.axes = [];
this.overlappingAxisIds = /* @__PURE__ */ new Set();
}
destroy() {
for (const a of this.axes) {
a.div.destroy();
}
}
update(enabled, enableAxisDragging, enableAxisScrolling, ctx, seriesRect) {
this.seriesRect = seriesRect;
const disabled = !enabled || !enableAxisDragging && !enableAxisScrolling;
for (const ax of this.axes) {
ax.div.setHidden(disabled);
}
if (disabled)
return;
const { X, Y } = ChartAxisDirection34;
const axesCtx = [...ctx.axisManager.getAxisContext(X), ...ctx.axisManager.getAxisContext(Y)];
const { removed, added } = this.diffAxisIds(axesCtx);
if (removed.length > 0) {
this.axes = this.axes.filter((entry) => {
if (removed.includes(entry.axisId)) {
entry.div.destroy();
this.overlappingAxisIds.delete(entry.axisId);
if (this.hoveredAxisId === entry.axisId)
this.hoveredAxisId = void 0;
if (this.activeAxisId === entry.axisId)
this.activeAxisId = void 0;
return false;
}
return true;
});
}
for (const newAxisCtx of added) {
const { axisId, direction } = newAxisCtx;
this.axes.push(this.initAxis(ctx, axisId, this.axesHandlers, direction));
}
for (const axis of this.axes) {
const axisCtx = axesCtx.find((ac) => ac.axisId === axis.axisId);
const bbox = axisCtx.getCanvasBounds();
axis.div.setHidden(boxEmpty(bbox));
if (bbox == void 0) {
axis.bounds = void 0;
} else {
axis.div.setBounds(bbox);
axis.bounds = new _ModuleSupport127.BBox(bbox.x, bbox.y, bbox.width, bbox.height);
}
}
this.updateOverlappingAxisPointerEvents(enableAxisDragging, enableAxisScrolling);
}
setAxisCursor(cursor) {
this.cursor = cursor;
for (const axis of this.axes) {
axis.div.setCursor(this.getCursor(axis.direction));
}
}
toggleAxisDraggingCursor(direction, enabled) {
for (const axis of this.axes) {
if (axis.direction !== direction)
continue;
axis.div.setCursor(enabled ? this.getCursor(direction) : void 0);
}
}
updateOverlappingAxisPointerEvents(enableAxisDragging, enableAxisScrolling) {
this.overlappingAxisIds.clear();
const shouldEnableInteraction = (enableAxisDragging || enableAxisScrolling) && this.seriesRect;
for (const axis of this.axes) {
if (!shouldEnableInteraction) {
axis.div.setPointerEvents(void 0);
continue;
}
const isOverlapping = Boolean(axis.bounds?.collidesBBox(this.seriesRect));
if (isOverlapping) {
this.overlappingAxisIds.add(axis.axisId);
axis.div.setPointerEvents("none");
} else {
axis.div.setPointerEvents(void 0);
}
}
this.cleanupAxisState();
}
cleanupAxisState() {
if (this.hoveredAxisId && !this.overlappingAxisIds.has(this.hoveredAxisId)) {
this.hoveredAxisId = void 0;
}
if (this.activeAxisId && !this.overlappingAxisIds.has(this.activeAxisId)) {
this.activeAxisId = void 0;
}
}
pickAxisAtPoint(point) {
for (const axis of this.axes) {
if (!this.overlappingAxisIds.has(axis.axisId))
continue;
if (axis.bounds?.containsPoint(point.canvasX, point.canvasY)) {
return { axisId: axis.axisId, direction: axis.direction };
}
}
return void 0;
}
setHoveredAxis(axisId) {
if (this.overlappingAxisIds.has(axisId)) {
this.hoveredAxisId = axisId;
}
}
clearHoveredAxis() {
if (!this.activeAxisId) {
this.hoveredAxisId = void 0;
}
}
beginDelegatedAxisDrag(axisId) {
if (!this.overlappingAxisIds.has(axisId))
return false;
this.activeAxisId = axisId;
this.hoveredAxisId = void 0;
return true;
}
endDelegatedAxisDrag(axisId) {
if (this.activeAxisId === axisId) {
this.activeAxisId = void 0;
}
this.hoveredAxisId = void 0;
}
hasOverlappingAxes() {
return this.overlappingAxisIds.size > 0;
}
getHoveredAxis() {
if (!this.hoveredAxisId)
return void 0;
const axis = this.axes.find((a) => a.axisId === this.hoveredAxisId);
return axis ? { axisId: axis.axisId, direction: axis.direction } : void 0;
}
getCursor(direction) {
if (this.cursor)
return this.cursor;
return direction === ChartAxisDirection34.X ? "ew-resize" : "ns-resize";
}
initAxis(ctx, axisId, handlers, direction) {
const where = "afterend";
const div = ctx.proxyInteractionService.createProxyElement({ type: "region", domManagerId: axisId, where });
div.setCursor(this.getCursor(direction));
div.addListener("drag-start", (e) => {
if (e.device === "touch") {
e.sourceEvent.preventDefault();
}
this.activeAxisId = axisId;
handlers.onAxisDragStart(direction);
});
div.addListener("drag-move", (event) => handlers.onAxisDragMove(axisId, direction, event));
div.addListener("drag-end", () => {
this.activeAxisId = void 0;
this.hoveredAxisId = void 0;
handlers.onAxisDragEnd();
});
div.addListener("dblclick", () => handlers.onAxisDoubleClick(axisId, direction));
div.addListener("wheel", (event) => handlers.onAxisWheel(direction, event));
return { axisId, div, direction };
}
diffAxisIds(axesCtx) {
const myIds = this.axes.map((entry) => entry.axisId);
const ctxIds = axesCtx.map((ctx) => ctx.axisId);
const removed = myIds.filter((id) => !ctxIds.includes(id));
const added = axesCtx.filter((ac) => !myIds.includes(ac.axisId));
return { removed, added };
}
};
// packages/ag-charts-enterprise/src/features/zoom/zoomOnDataChange.ts
import { _ModuleSupport as _ModuleSupport128 } from "ag-charts-community";
import { BaseProperties as BaseProperties27, ChartAxisDirection as ChartAxisDirection35, Logger as Logger13, Property as Property65, clamp as clamp11, definedZoomState as definedZoomState5 } from "ag-charts-core";
var { userInteraction: userInteraction3 } = _ModuleSupport128;
function shouldIgnoreDataUpdate(zoom) {
return zoom.x.min === 0 && zoom.x.max === 1 && zoom.y.min === 0 && zoom.y.max === 1;
}
function shouldStickToEnd(properties, zoom) {
return properties.stickToEnd && zoom.x.max === 1;
}
function toVisibleMinMax(axisId, domainMinMax, ratios) {
const { domainMin, domainMax } = domainMinMax;
const span = domainMax - domainMin;
return {
axisId,
visibleMin: domainMin + span * ratios.min,
visibleMax: domainMin + span * ratios.max
};
}
function fromVisibleMinMax(domainMinMax, visibleMinMax) {
const { domainMin, domainMax } = domainMinMax;
const { visibleMin, visibleMax } = visibleMinMax;
const span = domainMax - domainMin;
return {
direction: "x",
min: clamp11(0, (visibleMin - domainMin) / span, 1),
max: clamp11(0, (visibleMax - domainMin) / span, 1)
};
}
var ZoomOnDataChangeProperties = class extends BaseProperties27 {
constructor() {
super(...arguments);
this.strategy = "preserveDomain";
// TODO(olegat): change default to 'true'
this.stickToEnd = false;
}
};
__decorateClass([
Property65
], ZoomOnDataChangeProperties.prototype, "strategy", 2);
__decorateClass([
Property65
], ZoomOnDataChangeProperties.prototype, "stickToEnd", 2);
var ZoomOnDataChange = class {
constructor(onConstrainChangesCallback, properties, ctx, eventsCleanup) {
this.onConstrainChangesCallback = onConstrainChangesCallback;
this.properties = properties;
this.ctx = ctx;
const onFirstDraw = () => {
ctx.eventsHub.off("layout:complete", onFirstDraw);
eventsCleanup.register(
ctx.eventsHub.on("data:load", (e) => this.onDataLoad(e)),
ctx.eventsHub.on("data:update", (e) => this.onDataUpdate(e))
);
};
eventsCleanup.register(
ctx.eventsHub.on("layout:complete", onFirstDraw),
ctx.eventsHub.on("zoom:change-request", (e) => this.onZoomChangeRequest(e))
);
}
destroy() {
}
onDataLoad(_e) {
this.performUpdateStrategy();
}
onDataUpdate(_e) {
this.performUpdateStrategy();
}
onZoomChangeRequest(e) {
if (e.sourceDetail === "internal-requiredWidth") {
this.desiredChanges = void 0;
}
const changes = this.popDesiredChanges();
if (changes) {
e.constrainChanges(changes);
this.onConstrainChangesCallback(e);
}
}
/**
* Convert ambiguous axes-scale (number | Date | string) into a strictly numerical scale, so that we can use
* interpolation to implement preserveDomain in an axes-scale agnostic way.
*/
computeDomainMinMax(axisId) {
const ctx = this.ctx.axisManager.getAxisIdContext(axisId);
if (!ctx?.continuous || ctx.scale.domain.length === 0)
return;
const [min, max] = ctx.scale.getDomainMinMax();
if (typeof min === "number" && typeof max === "number") {
return { domainMin: min, domainMax: max };
} else if (min instanceof Date && max instanceof Date) {
return { domainMin: min.getTime(), domainMax: max.getTime() };
} else {
Logger13.error(`Unexpected range types: start (${typeof min}), end (${typeof max})`);
}
}
popDesiredChanges() {
const { desiredChanges } = this;
if (!desiredChanges)
return;
this.desiredChanges = void 0;
switch (desiredChanges.type) {
case "domain": {
const changes = {};
for (const entry of desiredChanges.domains) {
const domainMinMax = this.computeDomainMinMax(entry.axisId);
if (domainMinMax) {
changes[entry.axisId] = fromVisibleMinMax(domainMinMax, entry);
}
}
return changes;
}
case "stickToEnd": {
const { axisId, difference } = desiredChanges;
const domainMinMax = this.computeDomainMinMax(axisId);
if (domainMinMax) {
const visibleMinMax = {
axisId,
visibleMin: domainMinMax.domainMax - difference,
visibleMax: domainMinMax.domainMax
};
return { [axisId]: fromVisibleMinMax(domainMinMax, visibleMinMax) };
}
break;
}
default:
const unreachable = (a) => a;
return unreachable(desiredChanges);
}
}
performUpdateStrategy() {
const zoom = definedZoomState5(this.ctx.zoomManager.getZoom());
if (shouldIgnoreDataUpdate(zoom)) {
return;
} else if (shouldStickToEnd(this.properties, zoom)) {
return this.performStickToEnd();
}
switch (this.properties.strategy) {
case "reset":
return this.ctx.zoomManager.resetZoom(userInteraction3("onDataChange-reset"));
case "preserveRatios":
return;
case "preserveDomain":
return this.performPreserveDomain();
default:
const unreachable = (a) => a;
return unreachable(this.properties.strategy);
}
}
performPreserveDomain() {
this.desiredChanges = { type: "domain", domains: [] };
const xaxes = this.ctx.zoomManager.getAxes().filter((a) => a.direction === ChartAxisDirection35.X);
for (const { id: axisId } of xaxes) {
const domainMinMax = this.computeDomainMinMax(axisId);
if (domainMinMax) {
const ratios = this.ctx.zoomManager.getAxisZoom(axisId);
const entry = toVisibleMinMax(axisId, domainMinMax, ratios);
this.desiredChanges.domains.push(entry);
}
}
}
performStickToEnd() {
const axisId = this.ctx.zoomManager.getPrimaryAxisId(ChartAxisDirection35.X);
if (!axisId)
return;
const domainMinMax = this.computeDomainMinMax(axisId);
if (!domainMinMax)
return;
const ratios = this.ctx.zoomManager.getAxisZoom(axisId);
if (!ratios)
return;
const { visibleMin, visibleMax } = toVisibleMinMax(axisId, domainMinMax, ratios);
const difference = visibleMax - visibleMin;
this.desiredChanges = { type: "stickToEnd", axisId, difference };
}
};
// packages/ag-charts-enterprise/src/features/zoom/zoomPanner.ts
import "ag-charts-community";
import {
ChartAxisDirection as ChartAxisDirection36,
UNIT_MAX as UNIT_MAX2,
UNIT_MIN as UNIT_MIN2,
definedZoomState as definedZoomState6,
entries as entries6,
getWindow as getWindow3
} from "ag-charts-core";
var maxZoomCoords = 16;
var decelerationValues = {
off: 1,
short: 0.01,
long: 2e-3
};
var ZoomPanner = class {
constructor() {
this.deceleration = 1;
this.zoomCoordsHistoryIndex = 0;
this.coordsHistory = [];
}
get decelerationValue() {
const { deceleration } = this;
return Math.max(
typeof deceleration === "number" ? deceleration : decelerationValues[deceleration] ?? 1,
1e-4
);
}
addListener(_type, fn) {
this.onUpdate = fn;
return () => {
this.onUpdate = void 0;
};
}
stopInteractions() {
if (this.inertiaHandle != null) {
cancelAnimationFrame(this.inertiaHandle);
this.inertiaHandle = void 0;
}
}
update(event) {
this.updateCoords(event.currentX, event.currentY);
const { x1 = 0, y1 = 0, x2 = 0, y2 = 0 } = this.coords ?? {};
this.onUpdate?.({
type: "update",
deltaX: this.isPanningX() ? x1 - x2 : 0,
deltaY: this.isPanningY() ? y1 - y2 : 0
});
}
start(direction) {
this.direction = direction;
this.coordsMonitorTimeout = setInterval(this.recordCurrentZoomCoords.bind(this), 16);
}
stop() {
const { coordsHistory } = this;
let deltaX = 0;
let deltaY = 0;
let deltaT = 0;
if (coordsHistory.length > 0) {
const arrayIndex = this.zoomCoordsHistoryIndex % maxZoomCoords;
let index1 = arrayIndex - 1;
if (index1 < 0)
index1 = coordsHistory.length - 1;
let index0 = arrayIndex;
if (index0 >= coordsHistory.length)
index0 = 0;
const coords1 = coordsHistory[index1];
const coords0 = coordsHistory[index0];
deltaX = this.isPanningX() ? coords1.x - coords0.x : 0;
deltaY = this.isPanningY() ? coords1.y - coords0.y : 0;
deltaT = coords1.t - coords0.t;
}
this.coords = void 0;
this.direction = void 0;
clearInterval(this.coordsMonitorTimeout);
this.coordsMonitorTimeout = void 0;
this.zoomCoordsHistoryIndex = 0;
this.coordsHistory.length = 0;
if (deltaT > 0 && this.decelerationValue < 1) {
const xVelocity = deltaX / deltaT;
const yVelocity = deltaY / deltaT;
const velocity = Math.hypot(xVelocity, yVelocity);
const angle = Math.atan2(yVelocity, xVelocity);
const t0 = performance.now();
this.inertiaHandle = getWindow3().requestAnimationFrame((t) => {
this.animateInertia(t, t, t0, velocity, angle);
});
}
}
recordCurrentZoomCoords() {
const { coords, coordsHistory, zoomCoordsHistoryIndex } = this;
if (!coords)
return;
const { x2: x, y2: y } = coords;
const t = Date.now();
coordsHistory[zoomCoordsHistoryIndex % maxZoomCoords] = { x, y, t };
this.zoomCoordsHistoryIndex += 1;
}
animateInertia(t, prevT, t0, velocity, angle) {
const friction = 1 - this.decelerationValue;
const maxS = -velocity / Math.log(friction);
const s0 = velocity * (friction ** (prevT - t0) - 1) / Math.log(friction);
const s1 = velocity * (friction ** (t - t0) - 1) / Math.log(friction);
this.onUpdate?.({
type: "update",
deltaX: this.isPanningX() ? -Math.cos(angle) * (s1 - s0) : 0,
deltaY: this.isPanningY() ? -Math.sin(angle) * (s1 - s0) : 0
});
if (s1 >= maxS - 1)
return;
this.inertiaHandle = requestAnimationFrame((nextT) => {
this.animateInertia(nextT, t, t0, velocity, angle);
});
}
updateCoords(x, y) {
if (this.coords) {
this.coords = { x1: this.coords.x2, y1: this.coords.y2, x2: x, y2: y };
} else {
this.coords = { x1: x, y1: y, x2: x, y2: y };
}
}
isPanningX() {
return this.direction == null || this.direction === ChartAxisDirection36.X;
}
isPanningY() {
return this.direction == null || this.direction === ChartAxisDirection36.Y;
}
translateZooms(bbox, currentZooms, deltaX, deltaY) {
const offset = pointToRatio(bbox, bbox.x + Math.abs(deltaX), bbox.y + bbox.height - Math.abs(deltaY));
const offsetX = Math.sign(deltaX) * offset.x;
const offsetY = -Math.sign(deltaY) * offset.y;
const newZooms = {};
for (const [axisId, currentZoom] of entries6(currentZooms)) {
if (currentZoom == null)
continue;
if (currentZoom.min === UNIT_MIN2 && currentZoom.max === UNIT_MAX2) {
continue;
}
const { direction } = currentZoom;
let zoom = definedZoomState6({ [direction]: currentZoom });
zoom = constrainZoom(translateZoom(zoom, offsetX * dx(zoom), offsetY * dy(zoom)));
const { min, max } = zoom[direction];
newZooms[axisId] = { direction, min, max };
}
return newZooms;
}
};
// packages/ag-charts-enterprise/src/features/zoom/zoomScrollPanner.ts
import "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection37, definedZoomState as definedZoomState7, entries as entries7 } from "ag-charts-core";
var DELTA_SCALE = 200;
var ZoomScrollPanner = class {
update(event, step, bbox, zooms) {
const deltaX = event.deltaX * step * DELTA_SCALE;
return this.translateZooms(bbox, zooms, deltaX);
}
translateZooms(bbox, currentZooms, deltaX) {
const newZooms = {};
const offset = pointToRatio(bbox, bbox.x + Math.abs(deltaX), 0);
const offsetX = deltaX < 0 ? -offset.x : offset.x;
for (const [axisId, value] of entries7(currentZooms)) {
if (value?.direction !== ChartAxisDirection37.X)
continue;
const { direction, min, max } = value;
let zoom = definedZoomState7({ x: { min, max } });
zoom = constrainZoom(translateZoom(zoom, offsetX * dx(zoom), 0));
newZooms[axisId] = { direction, min: zoom.x.min, max: zoom.x.max };
}
return newZooms;
}
};
// packages/ag-charts-enterprise/src/features/zoom/zoomScroller.ts
import "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection38, definedZoomState as definedZoomState8, entries as entries8 } from "ag-charts-core";
var ZoomScroller = class {
updateAxes(event, props, bbox, zooms) {
const sourceEvent = event.sourceEvent;
const newZooms = {};
const { anchorPointX, anchorPointY, isScalingX, isScalingY, scrollingStep } = props;
const origin = pointToRatio(
bbox,
sourceEvent.offsetX ?? sourceEvent.clientX,
sourceEvent.offsetY ?? sourceEvent.clientY
);
for (const [axisId, value] of entries8(zooms)) {
if (value == null)
continue;
const { direction, min, max } = value;
let newZoom = { min, max };
const delta3 = scrollingStep * event.deltaY * (max - min);
if (direction === ChartAxisDirection38.X && isScalingX) {
newZoom.max += delta3;
newZoom = scaleZoomAxisWithAnchor(newZoom, value, anchorPointX, origin.x);
} else if (direction === ChartAxisDirection38.Y && isScalingY) {
newZoom.max += delta3;
newZoom = scaleZoomAxisWithAnchor(newZoom, value, anchorPointY, origin.y);
} else {
continue;
}
if (newZoom.max < newZoom.min)
continue;
const constrained = constrainAxis(newZoom);
newZooms[axisId] = { direction, min: constrained.min, max: constrained.max };
}
return newZooms;
}
update(event, props, bbox, oldZoom) {
const { anchorPointX, anchorPointY, isScalingX, isScalingY, scrollingStep } = props;
const canvasX = event.offsetX + bbox.x;
const canvasY = event.offsetY + bbox.y;
const origin = pointToRatio(bbox, canvasX, canvasY);
const dir = event.deltaY;
let newZoom = definedZoomState8(oldZoom);
newZoom.x.max += isScalingX ? scrollingStep * dir * dx(oldZoom) : 0;
newZoom.y.max += isScalingY ? scrollingStep * dir * dy(oldZoom) : 0;
if (newZoom.x.max < newZoom.x.min || newZoom.y.max < newZoom.y.min)
return;
if (isScalingX) {
newZoom.x = scaleZoomAxisWithAnchor(newZoom.x, oldZoom.x, anchorPointX, origin.x);
}
if (isScalingY) {
newZoom.y = scaleZoomAxisWithAnchor(newZoom.y, oldZoom.y, anchorPointY, origin.y);
}
newZoom = constrainZoom(newZoom);
return newZoom;
}
updateDelta(delta3, props, oldZoom) {
const { anchorPointX, anchorPointY, isScalingX, isScalingY, scrollingStep } = props;
let newZoom = definedZoomState8(oldZoom);
newZoom.x.max += isScalingX ? scrollingStep * -delta3 * dx(oldZoom) : 0;
newZoom.y.max += isScalingY ? scrollingStep * -delta3 * dy(oldZoom) : 0;
if (isScalingX) {
newZoom.x = scaleZoomAxisWithAnchor(newZoom.x, oldZoom.x, anchorPointX);
}
if (isScalingY) {
newZoom.y = scaleZoomAxisWithAnchor(newZoom.y, oldZoom.y, anchorPointY);
}
newZoom = constrainZoom(newZoom);
return newZoom;
}
};
// packages/ag-charts-enterprise/src/features/zoom/zoomSelector.ts
import { definedZoomState as definedZoomState9 } from "ag-charts-core";
var ZoomSelector = class {
constructor(rect, getZoom, isZoomValid) {
this.rect = rect;
this.getZoom = getZoom;
this.isZoomValid = isZoomValid;
this.rect.visible = false;
}
update(event, props, bbox) {
const canvasX = event.currentX + (bbox?.x ?? 0);
const canvasY = event.currentY + (bbox?.y ?? 0);
this.rect.visible = true;
this.updateCoords(canvasX, canvasY, props, bbox);
this.updateRect(bbox);
}
stop(innerBBox, bbox, currentZoom) {
let zoom = definedZoomState9();
if (!innerBBox || !bbox)
return zoom;
if (this.coords) {
zoom = this.createZoomFromCoords(bbox, currentZoom);
}
const multiplyX = bbox.width / innerBBox.width;
const multiplyY = bbox.height / innerBBox.height;
zoom = constrainZoom(multiplyZoom(zoom, multiplyX, multiplyY));
this.reset();
if (this.isZoomValid(zoom)) {
return zoom;
}
}
reset() {
this.coords = void 0;
this.rect.visible = false;
}
didUpdate() {
return this.rect.visible && this.rect.width > 0 && this.rect.height > 0;
}
updateCoords(x, y, props, bbox) {
if (!this.coords) {
this.coords = { x1: x, y1: y, x2: x, y2: y };
return;
}
const { coords } = this;
coords.x2 = x;
coords.y2 = y;
if (!bbox)
return;
const { isScalingX, isScalingY, keepAspectRatio } = props;
const normal = this.getNormalisedDimensions();
if (keepAspectRatio && isScalingX && isScalingY) {
const aspectRatio = bbox.width / bbox.height;
if (coords.y2 < coords.y1) {
coords.y2 = Math.min(coords.y1 - normal.width / aspectRatio, coords.y1);
} else {
coords.y2 = Math.max(coords.y1 + normal.width / aspectRatio, coords.y1);
}
}
if (!isScalingX) {
coords.x1 = bbox.x;
coords.x2 = bbox.x + bbox.width;
}
if (!isScalingY) {
coords.y1 = bbox.y;
coords.y2 = bbox.y + bbox.height;
}
}
updateRect(bbox) {
if (!bbox)
return;
const { rect } = this;
const normal = this.getNormalisedDimensions();
const { width, height } = normal;
let { x, y } = normal;
x = Math.max(x, bbox.x);
x -= Math.max(0, x + width - (bbox.x + bbox.width));
y = Math.max(y, bbox.y);
y -= Math.max(0, y + height - (bbox.y + bbox.height));
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
const zoom = this.createZoomFromCoords(bbox, this.getZoom());
if (this.isZoomValid(zoom)) {
rect.updateValid();
} else {
rect.updateInvalid();
}
}
createZoomFromCoords(bbox, currentZoom) {
const oldZoom = definedZoomState9(currentZoom);
const normal = this.getNormalisedDimensions();
const origin = pointToRatio(bbox, normal.x, normal.y + normal.height);
const xFactor = normal.width / bbox.width;
const yFactor = normal.height / bbox.height;
let newZoom = scaleZoom(oldZoom, xFactor, yFactor);
const translateX = origin.x * dx(oldZoom);
const translateY = origin.y * dy(oldZoom);
newZoom = translateZoom(newZoom, translateX, translateY);
newZoom = constrainZoom(newZoom);
return newZoom;
}
getNormalisedDimensions() {
const { x1 = 0, y1 = 0, x2 = 0, y2 = 0 } = this.coords ?? {};
const x = Math.min(x1, x2);
const y = Math.min(y1, y2);
const width = x1 <= x2 ? x2 - x1 : x1 - x2;
const height = y1 <= y2 ? y2 - y1 : y1 - y2;
return { x, y, width, height };
}
};
// packages/ag-charts-enterprise/src/features/zoom/zoomToolbar.ts
import { _ModuleSupport as _ModuleSupport132 } from "ag-charts-community";
import {
ActionOnSet as ActionOnSet8,
BaseProperties as BaseProperties28,
ChartAxisDirection as ChartAxisDirection39,
CleanupRegistry as CleanupRegistry6,
PropertiesArray as PropertiesArray6,
Property as Property66,
UNIT_MAX as UNIT_MAX3,
UNIT_MIN as UNIT_MIN3,
createElement as createElement7,
debounce,
definedZoomState as definedZoomState10,
entries as entries9
} from "ag-charts-core";
var { userInteraction: userInteraction4, NativeWidget: NativeWidget2, Toolbar: Toolbar2 } = _ModuleSupport132;
var ZoomButtonProperties = class extends ToolbarButtonProperties {
};
__decorateClass([
Property66
], ZoomButtonProperties.prototype, "value", 2);
__decorateClass([
Property66
], ZoomButtonProperties.prototype, "section", 2);
var ZoomToolbar = class extends BaseProperties28 {
constructor(ctx, getModuleProperties, updateZoom, updateAxisZoom, resetZoom, isZoomValid) {
super();
this.ctx = ctx;
this.getModuleProperties = getModuleProperties;
this.updateZoom = updateZoom;
this.updateAxisZoom = updateAxisZoom;
this.resetZoom = resetZoom;
this.isZoomValid = isZoomValid;
this.enabled = false;
this.buttons = new PropertiesArray6(ZoomButtonProperties);
this.visible = "hover";
this.verticalSpacing = 10;
this.detectionRange = 38;
this.cleanup = new CleanupRegistry6();
this.toggleButtonsDebounced = debounce(this.toggleButtons.bind(this), ZOOM_VALID_CHECK_DEBOUNCE, {
leading: true,
trailing: true
});
this.container = new NativeWidget2(createElement7("div"));
this.container.addClass("ag-charts-zoom-buttons");
ctx.domManager.addChild("canvas-overlay", "zoom-buttons", this.container.getElement());
this.toolbar = new Toolbar2(ctx, "ariaLabelZoomToolbar", "horizontal");
this.container.addChild(this.toolbar);
this.toolbar.getElement().style.transform = `translateY(54px)`;
this.toolbar.setHidden(!this.enabled);
this.toggleVisibility(this.visible === "always");
this.cleanup.register(
this.toolbar.addToolbarListener("button-pressed", this.onButtonPress.bind(this)),
this.toolbar.addToolbarListener("button-focused", this.onButtonFocus.bind(this)),
ctx.widgets.containerWidget.addListener("mousemove", this.onHover.bind(this)),
ctx.widgets.containerWidget.addListener("mouseleave", this.onLeave.bind(this)),
ctx.eventsHub.on("layout:complete", this.onLayoutComplete.bind(this)),
this.teardown.bind(this)
);
}
destroy() {
this.cleanup.flush();
}
toggleVisibleZoomed(maxZoom) {
if (this.visible !== "zoomed")
return;
this.toggleVisibility(!maxZoom);
}
teardown() {
this.ctx.domManager.removeChild("canvas-overlay", "zoom-buttons");
this.container.destroy();
}
onLayoutComplete(event) {
if (!this.enabled)
return;
const { buttons, container } = this;
const { rect } = event.series;
for (const b of buttons) {
if (b.tooltip == null && b.label == null) {
const map = {
"pan-end": "toolbarZoomPanEnd",
"pan-left": "toolbarZoomPanLeft",
"pan-right": "toolbarZoomPanRight",
"pan-start": "toolbarZoomPanStart",
"zoom-in": "toolbarZoomZoomIn",
"zoom-out": "toolbarZoomZoomOut",
reset: "toolbarZoomReset"
};
b.tooltip = map[b.value];
}
}
this.toolbar.updateButtons(buttons);
this.toggleButtonsDebounced();
const height = container.getBounds().height;
container.setBounds({ y: rect.y + rect.height - height });
}
onHover(event) {
if (!this.enabled || this.visible !== "hover" || this.toolbar.isHidden())
return;
const {
container,
detectionRange,
ctx: { scene }
} = this;
const {
currentY,
sourceEvent: { target }
} = event;
const element = container.getElement();
const detectionY = element.offsetTop - detectionRange;
const visible = currentY > detectionY && currentY < scene.canvas.element.offsetHeight || target === element;
this.toggleVisibility(visible);
}
onLeave() {
if (this.visible !== "hover")
return;
this.toggleVisibility(false);
}
toggleVisibility(visible, immediate = false) {
const { container, toolbar: toolbar2, verticalSpacing } = this;
toolbar2.toggleClass("ag-charts-zoom-buttons__toolbar--hidden", !visible);
const element = toolbar2.getElement();
element.style.transitionDuration = immediate ? "0s" : "";
element.style.transform = visible ? "translateY(0)" : `translateY(${container.getBounds().height + verticalSpacing}px)`;
}
toggleButtons() {
const zoom = definedZoomState10(this.ctx.zoomManager.getZoom());
if (this.previousZoom && isZoomEqual(this.previousZoom, zoom))
return;
this.previousZoom = zoom;
for (const [index, button] of this.buttons.entries()) {
let enabled = true;
switch (button?.value) {
case "pan-start":
enabled = zoom.x.min > UNIT_MIN3;
break;
case "pan-end":
enabled = zoom.x.max < UNIT_MAX3;
break;
case "pan-left":
enabled = zoom.x.min > UNIT_MIN3;
break;
case "pan-right":
enabled = zoom.x.max < UNIT_MAX3;
break;
case "zoom-out":
enabled = !isMaxZoom(zoom);
break;
case "zoom-in":
enabled = this.isZoomValid(
this.getNextZoomStateUnified("zoom-in", zoom, this.getModuleProperties())
);
break;
case "reset":
enabled = canResetZoom(this.ctx.zoomManager);
break;
}
this.toolbar.toggleButtonEnabledByIndex(index, enabled);
}
}
onButtonPress({ button }) {
if (!this.enabled || this.toolbar.isHidden())
return;
const props = this.getModuleProperties();
if (props.independentAxes && button.value !== "reset") {
const axisZooms = this.ctx.zoomManager.getAxisZooms();
for (const [axisId, value] of entries9(axisZooms)) {
if (value == null)
continue;
const { direction, min, max } = value;
this.onButtonPressAxis(button, props, axisId, direction, { min, max });
}
} else {
this.onButtonPressUnified(button, props);
}
}
onButtonFocus(_event) {
this.toggleVisibility(true, true);
}
onButtonPressAxis(event, props, axisId, direction, zoom) {
const { isScalingX, isScalingY, scrollingStep } = props;
let newZoom = { ...zoom };
const delta3 = zoom.max - zoom.min;
switch (event.value) {
case "pan-start":
newZoom.max = delta3;
newZoom.min = 0;
break;
case "pan-end":
newZoom.min = newZoom.max - delta3;
newZoom.max = UNIT_MAX3;
break;
case "pan-left":
newZoom.min -= delta3 * scrollingStep;
newZoom.max -= delta3 * scrollingStep;
break;
case "pan-right":
newZoom.min += delta3 * scrollingStep;
newZoom.max += delta3 * scrollingStep;
break;
case "zoom-in":
case "zoom-out": {
const isDirectionX = direction === ChartAxisDirection39.X;
const isScalingDirection = isDirectionX && isScalingX || !isDirectionX && isScalingY;
let scale = event.value === "zoom-in" ? 1 - scrollingStep : 1 + scrollingStep;
if (!isScalingDirection)
scale = 1;
const placement = isDirectionX ? this.getAnchorPointX(props) : this.getAnchorPointY(props);
newZoom.max = newZoom.min + (newZoom.max - newZoom.min) * scale;
newZoom = scaleZoomAxisWithAnchor(newZoom, zoom, placement);
break;
}
}
this.updateAxisZoom(userInteraction4(`zoom-button-${event.value}`), axisId, direction, constrainAxis(newZoom));
}
onButtonPressUnified(event, props) {
const { scrollingStep } = props;
const oldZoom = definedZoomState10(this.ctx.zoomManager.getZoom());
let zoom = definedZoomState10(oldZoom);
switch (event.value) {
case "reset":
this.resetZoom("zoom-button-reset");
return;
case "pan-start":
zoom.x.max = dx(zoom);
zoom.x.min = 0;
break;
case "pan-end":
zoom.x.min = UNIT_MAX3 - dx(zoom);
zoom.x.max = UNIT_MAX3;
break;
case "pan-left":
zoom = translateZoom(zoom, -dx(zoom) * scrollingStep, 0);
break;
case "pan-right":
zoom = translateZoom(zoom, dx(zoom) * scrollingStep, 0);
break;
case "zoom-in":
case "zoom-out": {
zoom = this.getNextZoomStateUnified(event.value, oldZoom, props);
break;
}
}
this.updateZoom(userInteraction4(`zoom-button-${event.value}`), constrainZoom(zoom));
}
getNextZoomStateUnified(button, oldZoom, props) {
const { isScalingX, isScalingY, scrollingStep } = props;
const scale = button === "zoom-in" ? 1 - scrollingStep : 1 + scrollingStep;
const zoom = scaleZoom(oldZoom, isScalingX ? scale : 1, isScalingY ? scale : 1);
zoom.x = scaleZoomAxisWithAnchor(zoom.x, oldZoom.x, this.getAnchorPointX(props));
zoom.y = scaleZoomAxisWithAnchor(zoom.y, oldZoom.y, this.getAnchorPointY(props));
return zoom;
}
getAnchorPointX(props) {
const anchorPointX = this.anchorPointX ?? props.anchorPointX;
return anchorPointX === "pointer" ? DEFAULT_ANCHOR_POINT_X : anchorPointX;
}
getAnchorPointY(props) {
const anchorPointY = this.anchorPointY ?? props.anchorPointY;
return anchorPointY === "pointer" ? DEFAULT_ANCHOR_POINT_Y : anchorPointY;
}
};
__decorateClass([
Property66,
ActionOnSet8({
changeValue(enabled) {
this.toolbar?.setHidden(!enabled);
}
})
], ZoomToolbar.prototype, "enabled", 2);
__decorateClass([
Property66
], ZoomToolbar.prototype, "buttons", 2);
__decorateClass([
Property66,
ActionOnSet8({
changeValue(visible, oldValue) {
if (oldValue == null)
return;
const always = visible === "always";
const zoomed = visible === "zoomed" && this.previousZoom != null && !isMaxZoom(this.previousZoom);
this.toggleVisibility(always || zoomed);
}
})
], ZoomToolbar.prototype, "visible", 2);
__decorateClass([
Property66
], ZoomToolbar.prototype, "anchorPointX", 2);
__decorateClass([
Property66
], ZoomToolbar.prototype, "anchorPointY", 2);
// packages/ag-charts-enterprise/src/features/zoom/zoomTwoFingers.ts
var N = 1e6;
function clientToNormal({ min, max }, a, Rx, Rw) {
if (Rw === 0)
return 0;
return N * ((a - Rx) / Rw * (max - min) + min);
}
function solveTwoUnknowns(x1, x2, a1, a2, Rx, Rw) {
[x1, x2] = [Math.min(x1, x2), Math.max(x1, x2)];
[a1, a2] = [Math.min(a1, a2), Math.max(a1, a2)];
const t1 = N * (a1 - Rx) / Rw;
const t2 = N * (a2 - Rx) / Rw;
const c = (a1 - Rx) / (a2 - Rx);
const min = (x1 - c * x2) / (N - t1 + c * (t2 - N));
const max = (x2 + (t2 - N) * min) / t2;
return { min, max };
}
function isRangeOverlapping(centerA, radiusA, centerB, radiusB) {
if (radiusA === 0)
radiusA = 30;
if (radiusB === 0)
radiusB = 30;
const minA = centerA - radiusA;
const maxA = centerA + radiusA;
const minB = centerB - radiusB;
const maxB = centerB + radiusB;
return !(maxA < minB || maxB < minA);
}
var ZoomTwoFingers = class {
constructor() {
this.touchStart = {
origins: [
{ identifier: 0, normalX: Number.NaN, normalY: Number.NaN },
{ identifier: 0, normalX: Number.NaN, normalY: Number.NaN }
]
};
this.initialZoom = { x: { min: 0, max: 1 }, y: { min: 0, max: 1 } };
this.previous = { a1: Number.NaN, a2: Number.NaN, b1: Number.NaN, b2: Number.NaN };
}
start(event, target, zoom) {
if (event.sourceEvent.targetTouches.length !== 2)
return false;
event.sourceEvent.preventDefault();
const targetTouches = Array.from(event.sourceEvent.targetTouches);
const { x: Rx, y: Ry, width: Rw, height: Rh } = target.getBoundingClientRect();
this.initialZoom.x.min = zoom.x?.min ?? 0;
this.initialZoom.x.max = zoom.x?.max ?? 1;
this.initialZoom.y.min = zoom.y?.min ?? 0;
this.initialZoom.y.max = zoom.y?.max ?? 1;
for (const t of this.touchStart.origins) {
t.identifier = 0;
}
this.previous.a1 = Number.NaN;
this.previous.a2 = Number.NaN;
this.previous.b1 = Number.NaN;
this.previous.b2 = Number.NaN;
for (const i of [0, 1]) {
const a = targetTouches[i].clientX;
const b = Ry + Rh - targetTouches[i].clientY;
this.touchStart.origins[i].identifier = targetTouches[i].identifier;
this.touchStart.origins[i].normalX = clientToNormal(this.initialZoom.x, a, Rx, Rw);
this.touchStart.origins[i].normalY = clientToNormal(this.initialZoom.y, b, Ry, Rh);
}
const [tA, tB] = targetTouches;
const [oA, oB] = this.touchStart.origins;
const xOverlap = isRangeOverlapping(tA.clientX, tA.radiusX, tB.clientX, tB.radiusX);
const yOverlap = isRangeOverlapping(tA.clientY, tA.radiusY, tB.clientY, tB.radiusY);
if (yOverlap)
oA.normalY = oB.normalY = (oA.normalY + oB.normalY) / 2;
if (xOverlap)
oA.normalX = oB.normalX = (oA.normalX + oB.normalX) / 2;
return true;
}
update(event, target) {
event.sourceEvent.preventDefault();
const targetTouches = Array.from(event.sourceEvent.targetTouches);
const { x: Rx, y: Ry, width: Rw, height: Rh } = target.getBoundingClientRect();
const { origins } = this.touchStart;
const touches = [0, 1].map((i) => targetTouches.find((t) => t.identifier === origins[i].identifier));
const x1 = origins[0].normalX;
const x2 = origins[1].normalX;
const a1 = touches[0].clientX;
const a2 = touches[1].clientX;
const y1 = origins[0].normalY;
const y2 = origins[1].normalY;
const b1 = Ry + Rh - touches[0].clientY;
const b2 = Ry + Rh - touches[1].clientY;
return this.twitchTolerantZoomPan4(x1, x2, a1, a2, y1, y2, b1, b2, Rx, Ry, Rw, Rh);
}
end(event) {
const identifiers = Array.from(event.sourceEvent.targetTouches).map((t) => t.identifier);
return !identifiers.includes(this.touchStart.origins[0].identifier) || !identifiers.includes(this.touchStart.origins[1].identifier);
}
// Small touch deltas on an axis, which can defined as one fingers moving ±1 pixel and the other not moving, can
// cause the canvas to flicker between two zoompan views.
//
// For example, consider two fingers moving upwards slowly on the Y-axis with the following events (Y=0 is the top
// of the screen):
//
// [0]: { finger1: { clientY: 101 }, finger2: { clientY: 201 } }
// [1]: { finger1: { clientY: 101 }, finger2: { clientY: 200 } }
// [2]: { finger1: { clientY: 100 }, finger2: { clientY: 200 } }
//
// The following transitions cause these changes to the zoompan respectively.
//
// [0] => [1] : yMin decreases, yMax increases
// [1] => [2] : yMin increases, yMax decreases
//
// At highly-zoomed views, this sudden shift in yMin/yMax in the [1] => [2] transition is very noticeable. When many
// of these kind of a transitions occur, the chart flickers between pan states instead of smoothly panning. Note
// however that, if we didn't receive event [1], our transition would like this:
//
// [0] => [2] : yMin increases, yMax increases
//
// ... which is a smooth panning transition. Therefore to prevent flickering, we skip event [1].
twitchTolerantZoomPan4(x1, x2, a1, a2, y1, y2, b1, b2, Rx, Ry, Rw, Rh) {
const { initialZoom, previous } = this;
const x = twitchTolerantZoomPan2(x1, x2, a1, a2, previous, "a1", "a2", Rx, Rw, initialZoom.x);
const y = twitchTolerantZoomPan2(y1, y2, b1, b2, previous, "b1", "b2", Ry, Rh, initialZoom.y);
return { x, y };
}
};
function twitchTolerantZoomPan2(x1, x2, a1, a2, previous, previousKey1, previousKey2, Rx, Rw, initialZoom) {
if (x1 == x2) {
const xn1 = clientToNormal(initialZoom, a1, Rx, Rw);
const xn2 = clientToNormal(initialZoom, a2, Rx, Rw);
const xavg = (xn1 + xn2) / 2;
const dzoom = (x1 - xavg) / N;
return { min: initialZoom.min + dzoom, max: initialZoom.max + dzoom };
} else {
const a1prev = previous[previousKey1];
const a2prev = previous[previousKey2];
const dx2 = Math.abs(a1 - a1prev) + Math.abs(a2 - a2prev);
if (dx2 <= 1) {
a1 = a1prev;
a2 = a2prev;
} else {
previous[previousKey1] = a1;
previous[previousKey2] = a2;
}
return solveTwoUnknowns(x1, x2, a1, a2, Rx, Rw);
}
}
// packages/ag-charts-enterprise/src/features/zoom/zoomWheelSequencer.ts
import { debounce as debounce2 } from "ag-charts-core";
var ZoomWheelSequencer = class {
constructor() {
this.isFirstWheelEvent = true;
this.debouncedWheelReset = debounce2(() => {
this.isFirstWheelEvent = true;
this.wasFirstWheelEventZoomCapped = void 0;
}, 100);
}
onWheel(event, callback4) {
if (event.sourceEvent.cancelable === false) {
return;
}
const result = callback4();
if (result === "abort")
return;
const isZoomCapped = result === "capped";
if (this.firstWheelEventDirection != null && this.firstWheelEventDirection !== event.deltaY < 0) {
this.isFirstWheelEvent = true;
}
if (this.isFirstWheelEvent) {
this.wasFirstWheelEventZoomCapped = isZoomCapped;
this.firstWheelEventDirection = event.deltaY < 0;
if (!isZoomCapped) {
event.sourceEvent.preventDefault();
}
} else if (this.wasFirstWheelEventZoomCapped === false) {
event.sourceEvent.preventDefault();
}
this.isFirstWheelEvent = false;
this.debouncedWheelReset();
}
};
// packages/ag-charts-enterprise/src/features/zoom/zoom.ts
var { userInteraction: userInteraction5, InteractionState: InteractionState6 } = _ModuleSupport133;
var round = (value) => roundTo(value, 10);
var CURSOR_ID = "zoom-cursor";
var TOOLTIP_ID = "zoom-tooltip";
var Zoom = class extends AbstractModuleInstance16 {
constructor(ctx) {
super();
this.ctx = ctx;
this.enabled = false;
this.enableAxisDragging = true;
this.enableAxisScrolling = true;
this.enableDoubleClickToReset = true;
this.enablePanning = true;
this.enableScrolling = true;
this.enableSelecting = false;
this.enableTwoFingerZoom = true;
this.panKey = "alt";
this.axes = "x";
this.scrollingStep = UNIT_SIZE / 10;
this.keepAspectRatio = false;
this.minVisibleItems = 2;
this.anchorPointX = DEFAULT_ANCHOR_POINT_X;
this.anchorPointY = DEFAULT_ANCHOR_POINT_Y;
this.autoScaling = new ZoomAutoScalingProperties();
this.axisDraggingMode = "zoom";
this.buttons = new ZoomToolbar(
this.ctx,
this.getModuleProperties.bind(this),
this.updateZoom.bind(this),
this.updateAxisZoom.bind(this),
this.resetZoom.bind(this),
this.isZoomValid.bind(this)
);
this.onDataChange = new ZoomOnDataChangeProperties();
// Zoom methods
this.axisDragger = new ZoomAxisDragger();
this.panner = new ZoomPanner();
this.scroller = new ZoomScroller();
this.scrollPanner = new ZoomScrollPanner();
this.twoFingers = new ZoomTwoFingers();
this.deceleration = "short";
// State
this.dragState = 0 /* None */;
this.isState = (state) => this.ctx.interactionManager.isState(state);
this.destroyContextMenuActions = void 0;
this.wheelSequencer = new ZoomWheelSequencer();
this.previousZoomValid = true;
this.previousAxisZoomValid = {
[ChartAxisDirection40.X]: true,
[ChartAxisDirection40.Y]: true
};
this.toggleAxisDraggingCursorsDebounced = debounce3(
this.toggleAxisDraggingCursors.bind(this),
ZOOM_VALID_CHECK_DEBOUNCE,
{
leading: true,
trailing: true
}
);
const selectionRect = new ZoomRect();
this.selector = new ZoomSelector(selectionRect, this.getZoom.bind(this), this.isZoomValid.bind(this));
this.contextMenu = new ZoomContextMenu(
ctx.eventsHub,
ctx.contextMenuRegistry,
ctx.zoomManager,
this.getModuleProperties.bind(this),
() => this.paddedRect,
this.updateZoom.bind(this),
this.isZoomValid.bind(this)
);
const minVisibleItemsCallback = (event) => {
if (this.minVisibleItems > 0) {
const restrictions = event.stateAsDefinedZoom();
event.constrainZoom(this.constrainZoom(restrictions));
}
};
this.dataChangeHandler = new ZoomOnDataChange(
minVisibleItemsCallback,
this.onDataChange,
this.ctx,
this.cleanup
);
this.domProxy = new ZoomDOMProxy({
onAxisDragStart: (direction) => this.onAxisDragStart(direction),
onAxisDragMove: (id, direction, event) => this.onAxisDragMove(id, direction, event),
onAxisDragEnd: () => this.onAxisDragEnd(),
onAxisDoubleClick: (id) => this.onAxisDoubleClick(id),
onAxisWheel: (direction, event) => this.onAxisWheel(direction, event)
});
if (ctx.widgets.seriesDragInterpreter) {
this.cleanup.register(
ctx.widgets.seriesDragInterpreter.events.on("dblclick", (event) => this.onSeriesAreaDoubleClick(event)),
ctx.widgets.seriesDragInterpreter.events.on("drag-move", (event) => this.onSeriesAreaDragMove(event)),
ctx.widgets.seriesDragInterpreter.events.on("drag-start", (event) => this.onSeriesAreaDragStart(event)),
ctx.widgets.seriesDragInterpreter.events.on("drag-end", () => this.onSeriesAreaDragEnd())
);
}
this.cleanup.register(
ctx.scene.attachNode(selectionRect),
ctx.eventsHub.on("series-area:hover", (event) => this.onSeriesAreaHoverEvent(event)),
ctx.eventsHub.on("series-area:click", (event) => this.onSeriesAreaClickEvent(event)),
ctx.eventsHub.on("series:keynav-zoom", (event) => this.onNavZoom(event)),
ctx.widgets.seriesWidget.addListener("wheel", (event) => this.onWheel(event)),
ctx.widgets.seriesWidget.addListener("touchstart", (event, current) => this.onTouchStart(event, current)),
ctx.widgets.seriesWidget.addListener("touchmove", (event, current) => this.onTouchMove(event, current)),
ctx.widgets.seriesWidget.addListener("touchend", (event) => this.onTouchEnd(event)),
ctx.widgets.seriesWidget.addListener("touchcancel", (event) => this.onTouchEnd(event)),
ctx.updateService.addListener("process-data", (event) => this.onProcessData(event)),
ctx.eventsHub.on("layout:complete", (event) => this.onLayoutComplete(event)),
ctx.eventsHub.on("zoom:change-request", (event) => this.onZoomChangeRequested(event)),
ctx.eventsHub.on("zoom:pan-start", (event) => this.onZoomPanStart(event)),
this.panner.addListener("update", (event) => this.onPanUpdate(event)),
() => this.teardown()
);
this.autoScaler = new ZoomAutoScaler(this.autoScaling, ctx.zoomManager, this, ctx.eventsHub, this.cleanup);
}
teardown() {
this.ctx.zoomManager.setZoomModuleEnabled(false);
this.buttons.destroy();
this.destroyContextMenuActions?.();
this.domProxy.destroy();
this.dataChangeHandler.destroy();
}
onEnabledChange(enabled) {
this.ctx.zoomManager.setZoomModuleEnabled(enabled);
if (this.contextMenu) {
this.destroyContextMenuActions?.();
this.destroyContextMenuActions = this.contextMenu.registerActions(enabled);
}
}
isIgnoredTouch(event) {
if (event?.device !== "touch") {
return false;
}
if (this.ctx.chartService.touch.dragAction !== "drag") {
return true;
}
if (this.enableSelecting) {
return false;
}
if (!this.enablePanning) {
return true;
}
return isMaxZoom(this.getZoom());
}
onSeriesAreaDoubleClick(event) {
const { enabled, enableDoubleClickToReset } = this;
if (!enabled || !enableDoubleClickToReset)
return;
if (event?.preventZoomDblClick || !this.isState(InteractionState6.ZoomClickable))
return;
this.resetZoom("zoom-seriesarea-dblclick");
}
onSeriesAreaHoverEvent(event) {
if (!this.shouldHandleAxisHover(event)) {
this.clearHoveredAxis();
return;
}
const axis = this.domProxy.pickAxisAtPoint(event);
if (axis) {
this.domProxy.setHoveredAxis(axis.axisId);
this.ctx.domManager.updateCursor(CURSOR_ID, this.domProxy.getCursor(axis.direction));
} else {
this.clearHoveredAxis();
}
}
onSeriesAreaClickEvent(event) {
if (!this.shouldHandleAxisClick(event))
return;
const axis = this.domProxy.pickAxisAtPoint(event);
if (axis && event.sourceEvent?.type === "dblclick") {
this.onAxisDoubleClick(axis.axisId);
}
}
shouldHandleAxisHover(event) {
const { enabled, enableAxisDragging, enableAxisScrolling, dragState } = this;
return enabled && (enableAxisDragging || enableAxisScrolling) && !event.consumed && !this.activeAxis && dragState === 0 /* None */ && this.domProxy.hasOverlappingAxes();
}
shouldHandleAxisClick(event) {
const { enabled, enableAxisDragging, enableAxisScrolling, enableDoubleClickToReset } = this;
return enabled && !this.activeAxis && !event.consumed && (enableAxisDragging || enableAxisScrolling || enableDoubleClickToReset);
}
clearHoveredAxis() {
if (this.activeAxis)
return;
this.domProxy.clearHoveredAxis();
if (this.dragState === 0 /* None */) {
this.ctx.domManager.updateCursor(CURSOR_ID);
}
}
tryBeginAxisDelegation(event) {
const hoveredAxis = this.domProxy.getHoveredAxis();
if (!this.enabled || !this.enableAxisDragging || !hoveredAxis) {
return false;
}
if (!this.domProxy.beginDelegatedAxisDrag(hoveredAxis.axisId)) {
return false;
}
this.activeAxis = hoveredAxis;
this.onAxisDragStart(hoveredAxis.direction);
const cursor = this.dragState === 2 /* Pan */ ? "grabbing" : this.domProxy.getCursor(hoveredAxis.direction);
this.ctx.domManager.updateCursor(CURSOR_ID, cursor);
if (event.device === "touch") {
event.sourceEvent.preventDefault();
}
return true;
}
onSeriesAreaDragStart(event) {
const {
enabled,
enablePanning,
enableSelecting,
ctx: { domManager, zoomManager }
} = this;
if (!enabled || !this.isState(InteractionState6.ZoomDraggable) || this.dragState !== 0 /* None */ || this.isIgnoredTouch(event)) {
return;
}
this.panner.stopInteractions();
if (this.tryBeginAxisDelegation(event)) {
return;
}
let newDragState = 0 /* None */;
const panKeyPressed = this.isPanningKeyPressed(event.sourceEvent);
if (enablePanning && (!enableSelecting || panKeyPressed)) {
domManager.updateCursor(CURSOR_ID, "grabbing");
newDragState = 2 /* Pan */;
this.panner.start();
} else if (enableSelecting && !panKeyPressed) {
newDragState = 3 /* Select */;
}
if ((this.dragState = newDragState) !== 0 /* None */) {
zoomManager.fireZoomPanStartEvent("zoom");
}
}
onSeriesAreaDragMove(event) {
const {
dragState,
enabled,
paddedRect,
panner,
selector,
ctx: { interactionManager, tooltipManager, updateService }
} = this;
if (this.activeAxis) {
this.onAxisDragMove(this.activeAxis.axisId, this.activeAxis.direction, event);
return;
}
if (!enabled || !paddedRect || !this.isState(InteractionState6.ZoomDraggable) || this.isIgnoredTouch(event)) {
return;
}
interactionManager.pushState(_ModuleSupport133.InteractionState.ZoomDrag);
if (event.device === "touch") {
event.sourceEvent.preventDefault();
}
switch (dragState) {
case 2 /* Pan */:
panner.update(event);
break;
case 3 /* Select */:
selector.update(event, this.getModuleProperties(), paddedRect);
break;
case 0 /* None */:
return;
}
tooltipManager.updateTooltip(TOOLTIP_ID);
updateService.update(ChartUpdateType8.PERFORM_LAYOUT, { skipAnimations: true });
}
onSeriesAreaDragEnd() {
const {
ctx: { interactionManager }
} = this;
if (this.activeAxis) {
this.handleAxisDragEnd();
return;
}
interactionManager.popState(_ModuleSupport133.InteractionState.ZoomDrag);
if (!this.enabled || this.dragState === 0 /* None */)
return;
this.handleRegularDragEnd();
this.resetDragState();
}
handleAxisDragEnd() {
this.onAxisDragEnd();
this.domProxy.endDelegatedAxisDrag(this.activeAxis.axisId);
this.activeAxis = void 0;
this.clearHoveredAxis();
}
handleRegularDragEnd() {
const { panner, selector } = this;
switch (this.dragState) {
case 2 /* Pan */:
panner.stop();
break;
case 3 /* Select */:
if (selector.didUpdate()) {
const newZoom = selector.stop(this.seriesRect, this.paddedRect, this.getZoom());
if (newZoom) {
this.updateZoom(userInteraction5("zoom-seriesarea-selector"), newZoom);
} else {
this.ctx.updateService.update();
}
}
break;
}
}
resetDragState() {
this.dragState = 0 /* None */;
this.ctx.domManager.updateCursor(CURSOR_ID);
this.ctx.tooltipManager.removeTooltip(TOOLTIP_ID);
}
onAxisDoubleClick(id) {
const {
enabled,
enableDoubleClickToReset,
ctx: { zoomManager }
} = this;
if (!enabled || !enableDoubleClickToReset || !this.isState(InteractionState6.ZoomClickable))
return;
this.previousAxisZoomValid = { [ChartAxisDirection40.X]: true, [ChartAxisDirection40.Y]: true };
zoomManager.resetAxisZoom({ source: "user-interaction", sourceDetail: "zoom-axis-dblclick" }, id);
}
onAxisDragStart(direction) {
const {
axisDraggingMode,
domProxy,
enabled,
enableAxisDragging,
panner,
ctx: { zoomManager }
} = this;
if (!enabled || !enableAxisDragging)
return;
panner.stopInteractions();
if (axisDraggingMode === "pan") {
domProxy.setAxisCursor("grabbing");
this.dragState = 2 /* Pan */;
this.panner.start(direction);
zoomManager.fireZoomPanStartEvent("zoom");
} else {
this.dragState = 1 /* Axis */;
}
}
onAxisDragMove(axisId, direction, event) {
const {
anchorPointX,
anchorPointY,
axisDragger,
dragState,
enabled,
enableAxisDragging,
seriesRect,
shouldFlipXY,
ctx: { interactionManager, tooltipManager, updateService, zoomManager }
} = this;
if (!enabled || !enableAxisDragging || !seriesRect)
return;
interactionManager.pushState(_ModuleSupport133.InteractionState.ZoomDrag);
if (event.device === "touch") {
event.sourceEvent.preventDefault();
}
const zoom = this.getZoom();
if (dragState === 2 /* Pan */) {
this.panner.update({ currentX: event.offsetX, currentY: event.offsetY });
} else {
let anchor = direction === ChartAxisDirection40.X ? anchorPointX : anchorPointY;
if (shouldFlipXY)
anchor = direction === ChartAxisDirection40.X ? anchorPointY : anchorPointX;
const axisZoom = zoomManager.getAxisZoom(axisId);
const newZoom = axisDragger.update(event, direction, anchor, seriesRect, zoom, axisZoom);
this.autoScaler.onManualAdjustment(direction);
this.updateAxisZoom(
userInteraction5("zoom-axis-drag"),
axisId,
direction,
newZoom,
{ directional: true }
);
}
tooltipManager.updateTooltip(TOOLTIP_ID);
updateService.update(ChartUpdateType8.PERFORM_LAYOUT, { skipAnimations: true });
}
onAxisDragEnd() {
const {
axisDraggingMode,
axisDragger,
dragState,
domProxy,
enabled,
enableAxisDragging,
ctx: { domManager, interactionManager, tooltipManager }
} = this;
interactionManager.popState(_ModuleSupport133.InteractionState.ZoomDrag);
if (!enabled || !enableAxisDragging || dragState === 0 /* None */)
return;
this.dragState = 0 /* None */;
if (axisDraggingMode === "pan") {
domProxy.setAxisCursor("grab");
this.panner.stop();
}
axisDragger.stop();
domManager.updateCursor(CURSOR_ID);
tooltipManager.removeTooltip(TOOLTIP_ID);
}
onNavZoom(event) {
const { enabled, enableScrolling, scroller } = this;
const isDefaultState = this.ctx.interactionManager.isState(_ModuleSupport133.InteractionState.Default);
if (!isDefaultState || !enabled || !enableScrolling)
return;
event.widgetEvent.sourceEvent.preventDefault();
this.updateZoom(
userInteraction5(`keyboard(${event.delta})`),
scroller.updateDelta(event.delta, this.getModuleProperties(), this.getZoom())
);
}
onWheel(event) {
const { enabled, enablePanning, enableScrolling, paddedRect } = this;
if (!enabled || !enableScrolling || !paddedRect || !this.isState(InteractionState6.ZoomWheelable))
return;
const { deltaX, deltaY } = event.sourceEvent;
const isHorizontalScrolling = deltaX != null && deltaY != null && Math.abs(deltaX) > Math.abs(deltaY);
if (enablePanning && isHorizontalScrolling) {
this.onWheelPanning(event);
} else {
this.onWheelScrolling(event);
}
}
onWheelPanning(event) {
const {
scrollingStep,
scrollPanner,
seriesRect,
ctx: { zoomManager }
} = this;
if (!seriesRect)
return;
event.sourceEvent.preventDefault();
const newZooms = scrollPanner.update(event, scrollingStep, seriesRect, zoomManager.getAxisZooms());
this.updateChanges(userInteraction5("zoom-seriesarea-wheel"), newZooms);
}
onWheelScrolling(event) {
const zoom = this.getZoom();
const isZoomCapped = event.deltaY > 0 && isMaxZoom(zoom);
this.wheelSequencer.onWheel(event, () => this.handleWheelScrolling(event, isZoomCapped));
}
onAxisWheel(axisDirection, event) {
if (!this.enableAxisScrolling)
return;
if (axisDirection !== ChartAxisDirection40.X && axisDirection !== ChartAxisDirection40.Y) {
return;
}
const isScalingX = axisDirection === ChartAxisDirection40.X;
const isScalingY = !isScalingX;
const props = this.getModuleProperties({ isScalingX, isScalingY });
const zoom = this.getZoom();
const isZoomCapped = event.deltaY > 0 && zoom[axisDirection].min === UNIT_MIN4 && zoom[axisDirection].max === UNIT_MAX4;
this.autoScaler.onManualAdjustment(axisDirection);
this.wheelSequencer.onWheel(event, () => this.handleWheelScrolling(event, isZoomCapped, props));
}
handleWheelScrolling(event, isZoomCapped, props = this.getModuleProperties()) {
const {
enableIndependentAxes,
scroller,
seriesRect,
ctx: { zoomManager }
} = this;
if (!seriesRect)
return "abort";
let updated = true;
const sourcing = userInteraction5("zoom-axis-wheel");
if (enableIndependentAxes === true) {
const newZooms = scroller.updateAxes(event, props, seriesRect, zoomManager.getAxisZooms());
for (const [axisId, { direction, min, max }] of entries10(newZooms)) {
const constrainedZoom = direction === ChartAxisDirection40.X ? this.constrainZoom({ x: { min, max }, y: { min: UNIT_MAX4, max: UNIT_MAX4 } }).x : { min, max };
updated && (updated = this.updateAxisZoom(sourcing, axisId, direction, constrainedZoom));
}
} else {
const newZoom = scroller.update(event, props, seriesRect, this.getZoom());
if (newZoom == null)
return "abort";
updated = this.updateUnifiedZoom(sourcing, newZoom, { directional: true });
}
return isZoomCapped || event.deltaY < 0 && !updated ? "capped" : "uncapped";
}
onTouchStart(event, current) {
if (!this.enableTwoFingerZoom || this.dragState !== 0 /* None */)
return;
if (this.twoFingers.start(event, current, this.getZoom())) {
this.dragState = 4 /* TwoFingers */;
}
}
onTouchMove(event, current) {
if (!this.enableTwoFingerZoom || this.dragState !== 4 /* TwoFingers */)
return;
const newZoom = this.twoFingers.update(event, current);
this.updateZoom(userInteraction5("zoom-seriesarea-twofingers"), constrainZoom(newZoom));
}
onTouchEnd(event) {
if (!this.enableTwoFingerZoom || this.dragState !== 4 /* TwoFingers */)
return;
event.sourceEvent.preventDefault();
if (this.twoFingers.end(event)) {
this.dragState = 0 /* None */;
}
}
onProcessData(event) {
this.shouldFlipXY = event.series.shouldFlipXY;
}
onLayoutComplete(event) {
this.domProxy.update(
this.enabled,
this.enableAxisDragging,
this.enableAxisScrolling,
this.ctx,
event.series.rect
);
if (!this.enabled)
return;
this.seriesRect = event.series.rect;
this.paddedRect = event.series.paddedRect;
if (this.enableAxisDragging) {
this.toggleAxisDraggingCursorsDebounced();
}
}
onZoomChangeRequested(event) {
if (event.sourceDetail !== "zoom-seriesarea-panner") {
this.panner.stopInteractions();
}
const zoom = this.getZoom();
this.buttons.toggleVisibleZoomed(isMaxZoom(zoom));
}
onZoomPanStart(event) {
if (event.callerId === "zoom") {
this.panner.stopInteractions();
}
}
onPanUpdate(event) {
const {
panner,
seriesRect,
ctx: { tooltipManager, zoomManager }
} = this;
if (!seriesRect)
return;
const newZooms = panner.translateZooms(seriesRect, zoomManager.getAxisZooms(), event.deltaX, event.deltaY);
this.updateChanges(userInteraction5("zoom-seriesarea-panner"), newZooms);
tooltipManager.updateTooltip(TOOLTIP_ID);
}
isPanningKeyPressed(event) {
switch (this.panKey) {
case "alt":
return event.altKey;
case "ctrl":
return event.ctrlKey;
case "shift":
return event.shiftKey;
case "meta":
return event.metaKey;
}
}
isScalingX() {
if (this.axes === "xy")
return true;
return this.shouldFlipXY ? this.axes === "y" : this.axes === "x";
}
isScalingY() {
if (this.axes === "xy")
return true;
return this.shouldFlipXY ? this.axes === "x" : this.axes === "y";
}
getAnchorPointX() {
return this.shouldFlipXY ? this.anchorPointY : this.anchorPointX;
}
getAnchorPointY() {
return this.shouldFlipXY ? this.anchorPointX : this.anchorPointY;
}
constrainZoom(newZoom) {
return this.ctx.zoomManager.constrainZoomToItemCount(newZoom, this.minVisibleItems, this.autoScaler.enabled);
}
isZoomValid(newZoom, options) {
const {
minVisibleItems,
ctx: { zoomManager }
} = this;
if (minVisibleItems === 0) {
this.previousZoomValid = true;
return true;
}
const zoom = this.getZoom();
const zoomedInX = round(dx(newZoom)) < round(dx(zoom));
const zoomedInY = round(dy(newZoom)) < round(dy(zoom));
if (!zoomedInX && !zoomedInY) {
this.previousZoomValid = true;
return true;
}
if (!this.previousZoomValid && options?.directional) {
return false;
}
const includeYVisibleRange = options?.includeYVisibleRange ?? false;
const autoScaleYAxis = this.autoScaler.enabled;
const valid = zoomManager.isVisibleItemsCountAtLeast(newZoom, minVisibleItems, {
includeYVisibleRange,
autoScaleYAxis
});
this.previousZoomValid = options?.directional ? valid : true;
return valid;
}
isAxisZoomValid(direction, axisZoom, options) {
const {
minVisibleItems,
ctx: { zoomManager }
} = this;
const zoom = this.getZoom();
const deltaAxis = axisZoom.max - axisZoom.min;
const deltaOld = zoom[direction].max - zoom[direction].min;
const newZoom = { ...zoom, [direction]: axisZoom };
if (deltaAxis >= deltaOld) {
this.previousAxisZoomValid[direction] = true;
return true;
}
if (!this.previousAxisZoomValid[direction] && options?.directional) {
return false;
}
const opts = { includeYVisibleRange: false, autoScaleYAxis: this.autoScaler.enabled };
const valid = zoomManager.isVisibleItemsCountAtLeast(newZoom, minVisibleItems, opts);
this.previousAxisZoomValid[direction] = options?.directional ? valid : true;
return valid;
}
resetZoom(sourceDetail) {
this.previousZoomValid = true;
this.previousAxisZoomValid = { [ChartAxisDirection40.X]: true, [ChartAxisDirection40.Y]: true };
this.ctx.zoomManager.resetZoom({ source: "user-interaction", sourceDetail });
}
updateSyncZoom(zoom) {
this.updateZoom({ source: "sync", sourceDetail: "internal-updateSyncZoom" }, zoom);
}
updateChanges(sourcing, changes) {
const partialZoom = this.ctx.zoomManager.toZoomState(changes) ?? {};
const currentZoom = definedZoomState11(this.ctx.zoomManager.getZoom());
this.updateZoom(sourcing, {
x: partialZoom.x ?? currentZoom.x,
y: partialZoom.y ?? currentZoom.y
});
}
updateZoom(sourcing, zoom) {
if (this.enableIndependentAxes) {
this.updatePrimaryAxisZooms(sourcing, zoom);
} else {
this.updateUnifiedZoom(sourcing, zoom);
}
}
updateUnifiedZoom(sourcing, zoom, validOptions) {
zoom = this.constrainZoom(zoom);
if (!this.isZoomValid(zoom, validOptions)) {
this.ctx.updateService.update(ChartUpdateType8.SCENE_RENDER, { skipAnimations: true });
return false;
}
this.ctx.zoomManager.updateZoom(sourcing, zoom);
return true;
}
updatePrimaryAxisZooms(sourcing, zoom) {
this.updatePrimaryAxisZoom(sourcing, zoom, ChartAxisDirection40.X);
this.updatePrimaryAxisZoom(sourcing, zoom, ChartAxisDirection40.Y);
}
updatePrimaryAxisZoom(sourcing, zoom, direction) {
const axisId = this.ctx.zoomManager.getPrimaryAxisId(direction);
if (axisId == null)
return;
this.updateAxisZoom(sourcing, axisId, direction, zoom[direction]);
}
updateAxisZoom(sourcing, axisId, direction, axisZoom, validOptions) {
const {
enableIndependentAxes,
ctx: { zoomManager }
} = this;
if (!axisZoom)
return false;
const zoom = this.getZoom();
if (enableIndependentAxes !== true) {
zoom[direction] = axisZoom;
return this.updateUnifiedZoom(sourcing, zoom, validOptions);
}
if (!this.isAxisZoomValid(direction, axisZoom, validOptions))
return false;
const { source, sourceDetail } = sourcing;
zoomManager.updateChanges({ source, sourceDetail, changes: { [axisId]: axisZoom }, isReset: false });
return true;
}
updateAxisCursor(opts) {
if (!this.domProxy)
return;
const {
enableAxisDragging = this.enableAxisDragging,
enableAxisScrolling = this.enableAxisScrolling,
axisDraggingMode = this.axisDraggingMode
} = opts;
if (enableAxisDragging) {
this.domProxy.setAxisCursor(axisDraggingMode === "pan" ? "grab" : void 0);
} else if (enableAxisScrolling) {
this.domProxy.setAxisCursor("default");
} else {
this.domProxy.setAxisCursor(void 0);
}
}
toggleAxisDraggingCursors() {
const { anchorPointX, anchorPointY, domProxy } = this;
const zoom = this.getZoom();
let showCursorX = dx(zoom) !== UNIT_SIZE;
let showCursorY = dy(zoom) !== UNIT_SIZE;
if (!showCursorX) {
const checkZoomX = scaleZoom(zoom, 0.999, 1);
checkZoomX.x = scaleZoomAxisWithAnchor(checkZoomX.x, zoom.x, anchorPointX);
showCursorX = this.isZoomValid(checkZoomX, { includeYVisibleRange: true });
}
if (!showCursorY) {
const checkZoomY = scaleZoom(zoom, 1, 0.999);
checkZoomY.y = scaleZoomAxisWithAnchor(checkZoomY.y, zoom.y, anchorPointY);
showCursorY = this.isZoomValid(checkZoomY, { includeYVisibleRange: true });
}
domProxy.toggleAxisDraggingCursor(ChartAxisDirection40.X, showCursorX);
domProxy.toggleAxisDraggingCursor(ChartAxisDirection40.Y, showCursorY);
}
getZoom() {
return definedZoomState11(this.ctx.zoomManager.getZoom());
}
getModuleProperties(overrides) {
return {
anchorPointX: overrides?.anchorPointX ?? this.getAnchorPointX(),
anchorPointY: overrides?.anchorPointY ?? this.getAnchorPointY(),
enabled: overrides?.enabled ?? this.enabled,
independentAxes: overrides?.independentAxes ?? this.enableIndependentAxes === true,
isScalingX: overrides?.isScalingX ?? this.isScalingX(),
isScalingY: overrides?.isScalingY ?? this.isScalingY(),
keepAspectRatio: overrides?.keepAspectRatio ?? this.keepAspectRatio,
scrollingStep: overrides?.scrollingStep ?? this.scrollingStep
};
}
};
__decorateClass([
ActionOnSet9({
newValue(enabled) {
this.onEnabledChange(enabled);
}
}),
Property67
], Zoom.prototype, "enabled", 2);
__decorateClass([
ActionOnSet9({
changeValue(newValue) {
this.updateAxisCursor({ enableAxisDragging: newValue });
}
}),
Property67
], Zoom.prototype, "enableAxisDragging", 2);
__decorateClass([
ActionOnSet9({
changeValue(newValue) {
this.updateAxisCursor({ enableAxisScrolling: newValue });
}
}),
Property67
], Zoom.prototype, "enableAxisScrolling", 2);
__decorateClass([
Property67
], Zoom.prototype, "enableDoubleClickToReset", 2);
__decorateClass([
ActionOnSet9({
changeValue(newValue) {
this.ctx.zoomManager.setIndependentAxes(Boolean(newValue));
}
}),
Property67
], Zoom.prototype, "enableIndependentAxes", 2);
__decorateClass([
Property67
], Zoom.prototype, "enablePanning", 2);
__decorateClass([
Property67
], Zoom.prototype, "enableScrolling", 2);
__decorateClass([
Property67
], Zoom.prototype, "enableSelecting", 2);
__decorateClass([
Property67
], Zoom.prototype, "enableTwoFingerZoom", 2);
__decorateClass([
Property67
], Zoom.prototype, "panKey", 2);
__decorateClass([
Property67
], Zoom.prototype, "axes", 2);
__decorateClass([
Property67
], Zoom.prototype, "scrollingStep", 2);
__decorateClass([
Property67
], Zoom.prototype, "keepAspectRatio", 2);
__decorateClass([
Property67
], Zoom.prototype, "minVisibleItems", 2);
__decorateClass([
Property67
], Zoom.prototype, "anchorPointX", 2);
__decorateClass([
Property67
], Zoom.prototype, "anchorPointY", 2);
__decorateClass([
Property67
], Zoom.prototype, "autoScaling", 2);
__decorateClass([
ActionOnSet9({
changeValue(newValue) {
this.updateAxisCursor({ axisDraggingMode: newValue });
}
}),
Property67
], Zoom.prototype, "axisDraggingMode", 2);
__decorateClass([
Property67
], Zoom.prototype, "buttons", 2);
__decorateClass([
Property67
], Zoom.prototype, "onDataChange", 2);
__decorateClass([
ProxyProperty3("panner.deceleration"),
Property67
], Zoom.prototype, "deceleration", 2);
// packages/ag-charts-enterprise/src/features/zoom/zoomModule.ts
var zoomAnchorPoint = union4("pointer", "start", "middle", "end");
var ZoomModule = {
type: "plugin",
name: "zoom",
enterprise: true,
version: VERSION27,
options: {
enabled: boolean15,
enableAxisDragging: boolean15,
enableAxisScrolling: boolean15,
enableDoubleClickToReset: boolean15,
enablePanning: boolean15,
enableScrolling: boolean15,
enableSelecting: boolean15,
enableTwoFingerZoom: boolean15,
keepAspectRatio: boolean15,
anchorPointX: zoomAnchorPoint,
anchorPointY: zoomAnchorPoint,
axisDraggingMode: union4("pan", "zoom"),
axes: union4("x", "y", "xy"),
deceleration: or2(union4("off", "short", "long"), ratio6),
minVisibleItems: positiveNumber7,
panKey: union4("alt", "ctrl", "meta", "shift"),
scrollingStep: ratio6,
autoScaling: {
enabled: boolean15,
padding: ratio6
},
onDataChange: {
strategy: strictUnion2()("reset", "preserveDomain", "preserveRatios"),
stickToEnd: boolean15
},
buttons: {
enabled: boolean15,
buttons: arrayOfDefs4(
{
...toolbarButtonOptionsDefs2,
value: union4("reset", "zoom-in", "zoom-out", "pan-left", "pan-right", "pan-start", "pan-end"),
section: string9
},
"zoom button options array"
),
visible: union4("always", "zoomed", "hover")
}
},
themeTemplate: {
enabled: false,
enableAxisDragging: true,
enableAxisScrolling: true,
enableDoubleClickToReset: true,
enablePanning: true,
enableScrolling: true,
enableSelecting: false,
enableTwoFingerZoom: true,
deceleration: "short",
minVisibleItems: 2,
panKey: "alt",
scrollingStep: 0.1,
autoScaling: {
enabled: {
$and: [
{ $eq: [{ $path: "../axes" }, "x"] },
{ $not: { $eq: [{ $path: "/series/0/direction" }, "horizontal"] } }
]
},
padding: 0.05
},
onDataChange: {
strategy: "preserveDomain",
stickToEnd: false
// TODO(olegat): change default to 'true'
},
anchorPointX: "end",
anchorPointY: "middle",
axes: "x",
buttons: {
enabled: { $path: "../enabled" },
visible: "hover",
buttons: {
$shallowSimple: [
{ icon: "zoom-out", value: "zoom-out", section: "scale" },
{ icon: "zoom-in", value: "zoom-in", section: "scale" },
{ icon: "pan-left", value: "pan-left", section: "pan" },
{ icon: "pan-right", value: "pan-right", section: "pan" },
{ icon: "reset", value: "reset", section: "reset" }
]
}
}
},
create: (ctx) => new Zoom(ctx)
};
ZoomModule.options.enableIndependentAxes = undocumented8(boolean15);
ZoomModule.options.buttons.anchorPointX = undocumented8(zoomAnchorPoint);
ZoomModule.options.buttons.anchorPointY = undocumented8(zoomAnchorPoint);
// packages/ag-charts-enterprise/src/gradient-legend/gradientLegendModule.ts
import { VERSION as VERSION28 } from "ag-charts-community";
import {
FILL_GRADIENT_BLANK_DEFAULTS,
FILL_IMAGE_BLANK_DEFAULTS,
FILL_PATTERN_BLANK_DEFAULTS,
LEGEND_CONTAINER_THEME,
and as and2,
array as array2,
boolean as boolean16,
borderOptionsDef,
callback as callback3,
colorUnion,
fontOptionsDef as fontOptionsDef2,
greaterThan,
legendPositionValidator,
lessThan,
number as number7,
numberFormatValidator as numberFormatValidator2,
padding,
positiveNumber as positiveNumber8,
ratio as ratio7
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/gradient-legend/gradientLegend.ts
import {
_ModuleSupport as _ModuleSupport135
} from "ag-charts-community";
import {
BaseProperties as BaseProperties29,
Border,
CleanupRegistry as CleanupRegistry7,
Property as Property68,
ProxyProperty as ProxyProperty4,
ZIndexMap as ZIndexMap13,
createId as createId6,
expandLegendPosition
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/gradient-legend/axisTicks.ts
import { _ModuleSupport as _ModuleSupport134 } from "ag-charts-community";
import {
ZIndexMap as ZIndexMap12,
cachedTextMeasurer as cachedTextMeasurer4,
countFractionDigits as countFractionDigits2,
createId as createId5,
createIdsGenerator,
estimateTickCount,
findMinMax as findMinMax5,
findRangeExtent,
isArray,
measureTextSegments,
toPlainText as toPlainText4,
toTextString
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/utils/formatter.ts
import { callWithContext as callWithContext2 } from "ag-charts-core";
function formatWithContext(ctx, formatter, params) {
return callWithContext2(ctx.chartService, formatter, params);
}
// packages/ag-charts-enterprise/src/gradient-legend/axisTicks.ts
var { AxisInterval: AxisInterval2, AxisLabel: AxisLabel2, LinearScale: LinearScale3, BBox: BBox15, TranslatableGroup: TranslatableGroup4, Selection: Selection4, Text: Text2 } = _ModuleSupport134;
var _AxisTicks = class _AxisTicks {
constructor(ctx, dataProvider) {
this.ctx = ctx;
this.dataProvider = dataProvider;
this.id = createId5(this);
this.axisGroup = new TranslatableGroup4({ name: `${this.id}-AxisTicks`, zIndex: ZIndexMap12.AXIS });
this.labelSelection = Selection4.select(this.axisGroup, Text2);
this.interval = new AxisInterval2();
this.label = new AxisLabel2();
this.scale = new LinearScale3();
this.placement = "bottom";
this.translationX = 0;
this.translationY = 0;
this.padding = 0;
}
get horizontal() {
return this.placement.startsWith("top") || this.placement.startsWith("bottom");
}
attachAxis(axisNode) {
axisNode.appendChild(this.axisGroup);
}
calculateLayout() {
const { placement, translationX, translationY, horizontal, label } = this;
function unreachable(_a) {
return void 0;
}
let textBaseline;
let textAlign;
switch (placement) {
case "top":
case "top-right":
case "top-left":
textBaseline = "bottom";
textAlign = "center";
label.mirrored = false;
label.parallel = true;
break;
case "bottom":
case "bottom-right":
case "bottom-left":
textBaseline = "top";
textAlign = "center";
label.mirrored = false;
label.parallel = true;
break;
case "right":
case "right-top":
case "right-bottom":
case "left":
case "left-top":
case "left-bottom":
textBaseline = "middle";
textAlign = "left";
label.mirrored = true;
label.parallel = false;
break;
default:
unreachable(placement);
}
const boxes = [];
const tickGenerationResult = this.generateTicks();
const { ticks } = tickGenerationResult;
this.labelSelection.update(ticks, void 0, (datum) => datum.tickId);
this.axisGroup.setProperties({ translationX, translationY });
this.labelSelection.each((node, datum) => {
node.fontFamily = label.fontFamily;
node.fontSize = label.fontSize;
node.fontStyle = label.fontStyle;
node.fontWeight = label.fontWeight;
node.fill = label.color;
node.textBaseline = textBaseline;
node.textAlign = textAlign;
node.text = datum.tickLabel;
node.x = horizontal ? datum.translation : 0;
node.y = horizontal ? 0 : datum.translation;
boxes.push(node.getBBox());
});
return boxes.length > 0 ? BBox15.merge(boxes).translate(translationX, translationY) : void 0;
}
tickFormatter(domain, _ticks, _primary, fractionDigits) {
const { ctx } = this;
const { formatManager } = ctx;
const boundSeries = this.dataProvider.data.flatMap((d) => d.series);
return (value, index) => {
const formatParams = {
type: "number",
value,
datum: void 0,
seriesId: void 0,
legendItemName: void 0,
key: void 0,
source: "gradient-legend",
property: "color",
domain,
boundSeries,
fractionDigits,
visibleDomain: void 0
};
return this.label.formatValue((fn, params) => formatWithContext(ctx, fn, params), formatParams, index) ?? formatManager.format((fn, params) => formatWithContext(ctx, fn, params), formatParams) ?? formatManager.defaultFormat(formatParams);
};
}
inRange(x, tolerance = 1e-3) {
const [min, max] = findMinMax5(this.scale.range);
return x >= min - tolerance && x <= max + tolerance;
}
generateTicks() {
const { minSpacing, maxSpacing } = this.interval;
const { maxTickCount, minTickCount, tickCount } = estimateTickCount(
findRangeExtent(this.scale.range),
1,
minSpacing,
maxSpacing,
_AxisTicks.DefaultTickCount,
_AxisTicks.DefaultMinSpacing
);
const tickData = this.getTicksData({
nice: [true, true],
interval: this.interval.step,
tickCount,
minTickCount,
maxTickCount
});
if (this.placement === "bottom" || this.placement === "top") {
const measurer3 = cachedTextMeasurer4(this.label);
const { domain } = this.scale;
const reversed = domain[0] > domain[1];
const direction = reversed ? -1 : 1;
let lastTickPosition = -Infinity * direction;
tickData.ticks = tickData.ticks.filter((data) => {
if (Math.sign(data.translation - lastTickPosition) !== direction)
return false;
const { width: labelWidth } = isArray(data.tickLabel) ? measureTextSegments(data.tickLabel, this.label) : measurer3.measureLines(toTextString(data.tickLabel));
lastTickPosition = data.translation + labelWidth * direction;
return true;
});
}
return tickData;
}
getTicksData(tickParams) {
const ticks = [];
const domain = tickParams.nice ? this.scale.niceDomain(tickParams) : this.scale.domain;
const rawTicks = this.scale.ticks(tickParams, domain)?.ticks ?? [];
const fractionDigits = rawTicks.reduce((max, tick) => Math.max(max, countFractionDigits2(tick)), 0);
const idGenerator = createIdsGenerator();
const tickFormatter = this.tickFormatter(domain, rawTicks, false, fractionDigits);
for (let index = 0; index < rawTicks.length; index++) {
const tick = rawTicks[index];
const translation = this.scale.convert(tick);
if (!this.inRange(translation))
continue;
const tickLabel = tickFormatter(tick, index);
if (tickLabel == null || tickLabel === "")
continue;
const tickId = idGenerator(toPlainText4(tickLabel));
ticks.push({ tick, tickId, tickLabel, translation });
}
return { rawTicks, fractionDigits, ticks };
}
};
_AxisTicks.className = "AxisTicks";
_AxisTicks.DefaultTickCount = 5;
_AxisTicks.DefaultMinSpacing = 10;
var AxisTicks = _AxisTicks;
// packages/ag-charts-enterprise/src/gradient-legend/gradientLegend.ts
var { LayoutElement: LayoutElement6, Group: Group9, Rect: Rect6, Marker: Marker2, TranslatableGroup: TranslatableGroup5, BBox: BBox16 } = _ModuleSupport135;
var GradientBar = class extends BaseProperties29 {
constructor() {
super(...arguments);
this.thickness = 16;
this.preferredLength = 100;
}
};
__decorateClass([
Property68
], GradientBar.prototype, "thickness", 2);
__decorateClass([
Property68
], GradientBar.prototype, "preferredLength", 2);
var GradientLegendScale = class extends BaseProperties29 {
constructor(axisTicks) {
super();
this.axisTicks = axisTicks;
}
};
__decorateClass([
ProxyProperty4("axisTicks.label")
], GradientLegendScale.prototype, "label", 2);
__decorateClass([
ProxyProperty4("axisTicks.interval")
], GradientLegendScale.prototype, "interval", 2);
__decorateClass([
ProxyProperty4("axisTicks.padding")
], GradientLegendScale.prototype, "padding", 2);
var GradientLegend = class extends BaseProperties29 {
constructor(ctx) {
super();
this.ctx = ctx;
this.id = createId6(this);
this.legendGroup = new TranslatableGroup5({ name: "legend", zIndex: ZIndexMap13.LEGEND });
this.containerNode = this.legendGroup.appendChild(new Rect6({ name: "legend-container" }));
this.gradientRect = new Rect6();
this.arrow = new Marker2({ shape: "triangle" });
this.ticksGroup = new Group9({ name: "legend-axis-group" });
this.cleanup = new CleanupRegistry7();
this.enabled = false;
this.position = "bottom";
this.reverseOrder = false;
this.gradient = new GradientBar();
this.spacing = 20;
this.border = new Border(this.containerNode);
this.cornerRadius = 0;
this.fillOpacity = 1;
this.padding = 4;
this.data = [];
this.highlightManager = ctx.highlightManager;
this.axisTicks = new AxisTicks(ctx, this);
this.axisTicks.attachAxis(this.ticksGroup);
this.scale = new GradientLegendScale(this.axisTicks);
this.legendGroup.append([this.gradientRect, this.arrow, this.ticksGroup]);
this.cleanup.register(
ctx.eventsHub.on("highlight:change", () => this.onChartHoverChange()),
ctx.layoutManager.registerElement(LayoutElement6.Legend, (e) => this.onStartLayout(e)),
() => this.legendGroup.remove()
);
}
isVertical() {
const { placement } = expandLegendPosition(this.position);
return placement.startsWith("right") || placement.startsWith("left");
}
destroy() {
this.cleanup.flush();
}
attachLegend(scene) {
scene.appendChild(this.legendGroup);
}
onStartLayout({ layoutBox }) {
const [data] = this.data;
if (!this.enabled || !data?.enabled || data.legendType !== "gradient") {
this.legendGroup.visible = false;
return;
}
const { colorRange } = this.normalizeColorArrays(data);
const { strokeWidth, padding: padding2 } = this.getContainerStyles();
const gradientRectBBox = this.updateGradientRect(layoutBox, colorRange);
const axisBBox = this.updateAxis(data, gradientRectBBox) ?? new BBox16(0, 0, 0, 0);
const legendBBox = BBox16.merge([gradientRectBBox, axisBBox]);
legendBBox.grow(padding2).grow(strokeWidth);
const { left, top } = this.getMeasurements(layoutBox, legendBBox);
this.updateContainer(legendBBox);
this.updateArrow();
this.legendGroup.visible = true;
this.legendGroup.translationX = left;
this.legendGroup.translationY = top;
}
normalizeColorArrays(data) {
let colorDomain = data.colorDomain.slice();
const colorRange = data.colorRange.slice();
if (colorDomain.length === colorRange.length) {
return { colorDomain, colorRange };
}
if (colorDomain.length > colorRange.length) {
colorRange.splice(colorDomain.length);
}
const [d0, d1] = colorDomain;
const count = colorRange.length;
colorDomain = colorRange.map((_, i) => {
if (i === 0) {
return d0;
} else if (i === count - 1) {
return d1;
}
return d0 + (d1 - d0) * i / (count - 1);
});
return { colorDomain, colorRange };
}
updateGradientRect(shrinkRect, colorRange) {
const { gradientRect, gradient } = this;
const { preferredLength, thickness } = gradient;
const gradientRectBBox = new BBox16(0, 0, 0, 0);
const colorCount = Math.max(colorRange.length - 1, 1);
let angle;
if (this.isVertical()) {
angle = 0;
gradientRectBBox.width = thickness;
gradientRectBBox.height = Math.min(shrinkRect.height, preferredLength);
} else {
angle = 90;
gradientRectBBox.width = Math.min(shrinkRect.width, preferredLength);
gradientRectBBox.height = thickness;
}
gradientRect.x = gradientRectBBox.x;
gradientRect.y = gradientRectBBox.y;
gradientRect.width = gradientRectBBox.width;
gradientRect.height = gradientRectBBox.height;
gradientRect.fill = {
type: "gradient",
gradient: "linear",
colorSpace: "oklch",
colorStops: colorRange.map((color7, i) => ({
stop: i / colorCount,
color: color7
})),
rotation: angle
};
return gradientRectBBox;
}
updateAxis(data, gradientRectBBox) {
const { axisTicks, gradient, scale } = this;
const { placement } = expandLegendPosition(this.position);
const vertical = this.isVertical();
const positiveAxis = this.reverseOrder !== vertical;
axisTicks.placement = placement;
const offset = gradient.thickness + (scale.padding ?? 0);
axisTicks.translationX = vertical ? offset : gradientRectBBox.x;
axisTicks.translationY = vertical ? gradientRectBBox.y : offset;
axisTicks.scale.domain = positiveAxis ? data.colorDomain.slice().reverse() : data.colorDomain;
axisTicks.scale.range = vertical ? [gradientRectBBox.x, gradientRectBBox.height] : [gradientRectBBox.y, gradientRectBBox.width];
return axisTicks.calculateLayout();
}
updateContainer(bbox) {
const containerStyles = this.getContainerStyles();
this.containerNode.setStyleProperties(containerStyles);
this.containerNode.cornerRadius = containerStyles.cornerRadius;
this.containerNode.x = bbox.x;
this.containerNode.y = bbox.y;
this.containerNode.width = bbox.width;
this.containerNode.height = bbox.height;
}
updateArrow() {
const highlighted = this.highlightManager.getActiveHighlight();
const { arrow } = this;
if (highlighted?.colorValue == null) {
arrow.visible = false;
return;
}
const { scale, label } = this.axisTicks;
const size = label.fontSize ?? 0;
const t = scale.convert(highlighted.colorValue);
let { x, y } = this.gradientRect;
let rotation = Math.PI;
if (this.isVertical()) {
x -= size / 2;
y += t;
rotation /= 2;
} else {
x += t;
y -= size / 2;
}
arrow.visible = true;
arrow.fill = label.color;
arrow.rotation = rotation;
arrow.size = size;
arrow.translationX = x;
arrow.translationY = y;
}
getMeasurements(shrinkRect, legendBBox) {
const unreachable = (_a) => {
return void 0;
};
let { x: left, y: top } = shrinkRect;
const { width, height } = legendBBox;
const { placement, floating, xOffset, yOffset } = expandLegendPosition(this.position);
const containerStyles = this.getContainerStyles();
left += containerStyles.strokeWidth + containerStyles.padding.left;
top += containerStyles.strokeWidth + containerStyles.padding.top;
switch (placement) {
case "left":
top += shrinkRect.height / 2 - height / 2;
break;
case "right":
left += shrinkRect.width - width;
top += shrinkRect.height / 2 - height / 2;
break;
case "top":
left += shrinkRect.width / 2 - width / 2;
break;
case "bottom":
left += shrinkRect.width / 2 - width / 2;
top += shrinkRect.height - height;
break;
case "right-top":
case "top-right":
left += shrinkRect.width - width;
break;
case "right-bottom":
case "bottom-right":
left += shrinkRect.width - width;
top += shrinkRect.height - height;
break;
case "left-bottom":
case "bottom-left":
top += shrinkRect.height - height;
break;
case "left-top":
case "top-left":
break;
default:
unreachable(placement);
}
if (!floating) {
switch (placement) {
case "left":
case "left-top":
case "left-bottom":
shrinkRect.shrink(width + this.spacing, "left");
break;
case "right":
case "right-top":
case "right-bottom":
shrinkRect.shrink(width + this.spacing, "right");
break;
case "top":
case "top-left":
case "top-right":
shrinkRect.shrink(height + this.spacing, "top");
break;
case "bottom":
case "bottom-left":
case "bottom-right":
shrinkRect.shrink(height + this.spacing, "bottom");
break;
default:
unreachable(placement);
}
}
left += xOffset;
top += yOffset;
return { top, left };
}
getContainerStyles() {
const { stroke: stroke3, strokeOpacity, strokeWidth } = this.border;
const { cornerRadius, fill, fillOpacity, padding: padding2 } = this;
const isPaddingNumber = typeof padding2 === "number";
return {
cornerRadius,
fill,
fillOpacity,
padding: {
top: isPaddingNumber ? padding2 : padding2.top ?? 0,
right: isPaddingNumber ? padding2 : padding2.right ?? 0,
bottom: isPaddingNumber ? padding2 : padding2.bottom ?? 0,
left: isPaddingNumber ? padding2 : padding2.left ?? 0
},
stroke: stroke3,
strokeOpacity,
strokeWidth: this.border.enabled ? strokeWidth : 0
};
}
onChartHoverChange() {
if (!this.enabled)
return;
this.updateArrow();
}
};
GradientLegend.className = "GradientLegend";
__decorateClass([
Property68
], GradientLegend.prototype, "enabled", 2);
__decorateClass([
Property68
], GradientLegend.prototype, "position", 2);
__decorateClass([
Property68
], GradientLegend.prototype, "reverseOrder", 2);
__decorateClass([
Property68
], GradientLegend.prototype, "gradient", 2);
__decorateClass([
Property68
], GradientLegend.prototype, "spacing", 2);
__decorateClass([
Property68
], GradientLegend.prototype, "border", 2);
__decorateClass([
Property68
], GradientLegend.prototype, "cornerRadius", 2);
__decorateClass([
Property68
], GradientLegend.prototype, "fill", 2);
__decorateClass([
Property68
], GradientLegend.prototype, "fillOpacity", 2);
__decorateClass([
Property68
], GradientLegend.prototype, "padding", 2);
__decorateClass([
Property68
], GradientLegend.prototype, "scale", 2);
// packages/ag-charts-enterprise/src/gradient-legend/gradientLegendModule.ts
var GradientLegendModule = {
type: "plugin",
name: "gradientLegend",
enterprise: true,
version: VERSION28,
// removable: 'standalone-only',
options: {
enabled: boolean16,
position: legendPositionValidator,
spacing: positiveNumber8,
reverseOrder: boolean16,
border: borderOptionsDef,
cornerRadius: number7,
padding,
fill: colorUnion,
fillOpacity: ratio7,
gradient: {
preferredLength: positiveNumber8,
thickness: positiveNumber8
},
scale: {
label: {
...fontOptionsDef2,
minSpacing: positiveNumber8,
format: numberFormatValidator2,
formatter: callback3
},
padding: positiveNumber8,
interval: {
step: number7,
values: array2,
minSpacing: and2(positiveNumber8, lessThan("maxSpacing")),
maxSpacing: and2(positiveNumber8, greaterThan("minSpacing"))
}
}
},
themeTemplate: {
...LEGEND_CONTAINER_THEME,
enabled: false,
position: "bottom",
spacing: 20,
scale: {
padding: 13,
label: {
color: { $ref: "textColor" },
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
minSpacing: 5
},
interval: {
minSpacing: 15
}
},
gradient: {
preferredLength: 100,
thickness: 16
},
reverseOrder: false,
fill: {
$applySwitch: [
{ $path: "type" },
{ $ref: "chartBackgroundColour" },
["gradient", FILL_GRADIENT_BLANK_DEFAULTS],
["pattern", FILL_PATTERN_BLANK_DEFAULTS],
["image", FILL_IMAGE_BLANK_DEFAULTS]
]
}
},
create: (ctx) => {
const moduleInstance = new GradientLegend(ctx);
moduleInstance.attachLegend(ctx.scene);
return moduleInstance;
}
};
// packages/ag-charts-enterprise/src/series/chord/chordModule.ts
import { VERSION as VERSION30 } from "ag-charts-community";
import {
FILL_GRADIENT_LINEAR_DEFAULTS as FILL_GRADIENT_LINEAR_DEFAULTS4,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS6,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS4,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS5,
SINGLE_SERIES_HIGHLIGHT_STYLE as SINGLE_SERIES_HIGHLIGHT_STYLE2
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/charts/standaloneChartModule.ts
import { VERSION as VERSION29, _ModuleSupport as _ModuleSupport137 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/charts/standaloneChart.ts
import { _ModuleSupport as _ModuleSupport136 } from "ag-charts-community";
var { Chart } = _ModuleSupport136;
var StandaloneChart = class extends Chart {
getChartType() {
return "standalone";
}
performLayout(ctx) {
const { seriesRoot, annotationRoot } = this;
const seriesRect = ctx.layoutBox.clone().shrink(this.seriesArea.getPadding());
this.seriesRect = seriesRect;
this.animationRect = seriesRect;
for (const group of [seriesRoot, annotationRoot]) {
group.translationX = Math.floor(seriesRect.x);
group.translationY = Math.floor(seriesRect.y);
}
seriesRoot.visible = this.series[0].visible;
this.ctx.layoutManager.emitLayoutComplete(ctx, {
series: { visible: true, rect: seriesRect, paddedRect: ctx.layoutBox }
});
}
getAriaLabel() {
const seriesType = this.series[0]?.type;
if (seriesType == null)
return "";
const caption = this.getCaptionText();
switch (seriesType) {
case "radial-gauge":
case "linear-gauge": {
const captions = [];
if (caption.length !== 0) {
captions.push(caption);
}
for (const series of this.series) {
captions.push(series.getCaptionText());
}
return this.ctx.localeManager.t("ariaAnnounceGaugeChart", { caption: captions.join(". ") });
}
case "treemap":
case "sunburst":
return this.ctx.localeManager.t("ariaAnnounceHierarchyChart", { caption });
default: {
return this.ctx.localeManager.t("ariaAnnounceStandaloneChart", { caption });
}
}
}
};
StandaloneChart.className = "StandaloneChart";
StandaloneChart.type = "standalone";
// packages/ag-charts-enterprise/src/charts/standaloneChartModule.ts
var { standaloneChartOptionsDefs } = _ModuleSupport137;
var StandaloneChartModule = {
type: "chart",
name: "standalone",
enterprise: true,
version: VERSION29,
options: standaloneChartOptionsDefs,
create(options, resources) {
return new StandaloneChart(options, resources);
}
};
// packages/ag-charts-enterprise/src/series/chord/chordSeries.ts
import { _ModuleSupport as _ModuleSupport141 } from "ag-charts-community";
import {
Logger as Logger15,
angleBetween as angleBetween2,
cachedTextMeasurer as cachedTextMeasurer5,
calcLineHeight as calcLineHeight6,
evaluateBezier,
isBetweenAngles,
mergeDefaults as mergeDefaults10,
normalizeAngle360 as normalizeAngle3604,
toPlainText as toPlainText5,
wrapText as wrapText3
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/flow-proportion/flowProportionSeries.ts
import {
_ModuleSupport as _ModuleSupport138
} from "ag-charts-community";
// packages/ag-charts-enterprise/src/series/flow-proportion/flowProportionUtil.ts
import { Logger as Logger14 } from "ag-charts-core";
function computeNodeGraph(nodes, links, includeCircularReferences) {
if (!includeCircularReferences) {
links = removeCircularLinks(links);
}
const nodeGraph = /* @__PURE__ */ new Map();
for (const datum of nodes) {
const itemId = datum.datumIndex.type === 0 /* Link */ ? `link-${datum.datumIndex.index}` : `node-${datum.datumIndex.index}`;
nodeGraph.set(datum.id, {
itemId,
datum,
linksBefore: [],
linksAfter: [],
maxPathLengthBefore: -1,
maxPathLengthAfter: -1
});
}
let maxPathLength = 0;
for (const [id, node] of nodeGraph.entries()) {
maxPathLength = Math.max(
maxPathLength,
computePathLength(nodeGraph, links, node, id, -1, []) + computePathLength(nodeGraph, links, node, id, 1, []) + 1
);
}
return { links, nodeGraph, maxPathLength };
}
function findCircularLinks(links, link, into, stack) {
const stackIndex = stack.indexOf(link);
if (stackIndex !== -1) {
for (let i = stackIndex; i < stack.length; i += 1) {
into.add(stack[i]);
}
return;
}
stack.push(link);
const { toNode } = link;
for (const next of links) {
if (next.fromNode === toNode) {
findCircularLinks(links, next, into, stack);
}
}
stack.pop();
}
function removeCircularLinks(links) {
const circularLinks = /* @__PURE__ */ new Set();
for (const link of links) {
findCircularLinks(links, link, circularLinks, []);
}
if (circularLinks.size !== 0) {
Logger14.warnOnce("Some links formed circular references. These will be removed from the output.");
}
return circularLinks.size === 0 ? links : links.filter((link) => !circularLinks.has(link));
}
function computePathLength(nodeGraph, links, node, id, direction, stack) {
if (stack.includes(id)) {
return Infinity;
}
let maxPathLength = direction === -1 ? node.maxPathLengthBefore : node.maxPathLengthAfter;
if (maxPathLength === -1) {
maxPathLength = 0;
const connectedLinks = direction === -1 ? node.linksBefore : node.linksAfter;
for (const link of links) {
const { fromNode, toNode } = link;
const linkId = direction === -1 ? toNode.id : fromNode.id;
const nextNodeId = direction === -1 ? fromNode.id : toNode.id;
const nextNode = id === linkId ? nodeGraph.get(nextNodeId) : void 0;
if (nextNode == null)
continue;
connectedLinks.push({ node: nextNode, link });
stack?.push(id);
maxPathLength = Math.max(
maxPathLength,
computePathLength(nodeGraph, links, nextNode, nextNodeId, direction, stack) + 1
);
stack?.pop();
}
if (direction === -1) {
node.maxPathLengthBefore = maxPathLength;
} else {
node.maxPathLengthAfter = maxPathLength;
}
}
return maxPathLength;
}
// packages/ag-charts-enterprise/src/series/flow-proportion/flowProportionSeries.ts
var {
findNodeDatumInArray,
keyProperty: keyProperty7,
valueProperty: valueProperty9,
DataController,
Group: Group10,
HighlightState: HighlightState4,
Selection: Selection5,
Series,
TransformableText
} = _ModuleSupport138;
var FlowProportionSeriesNodeEvent = class extends _ModuleSupport138.SeriesNodeEvent {
constructor(type, nativeEvent, datum, series) {
super(type, nativeEvent, datum, series);
const { datumIndex } = datum;
const nodeDatum = series.contextNodeData?.nodeData.find(
(d) => d.datumIndex.type === datumIndex.type && d.datumIndex.index === datumIndex.index
);
this.size = nodeDatum?.size;
this.label = nodeDatum?.type === 1 /* Node */ ? nodeDatum?.label : void 0;
}
};
var FlowProportionSeries = class extends Series {
constructor() {
super(...arguments);
this.NodeEvent = FlowProportionSeriesNodeEvent;
this.nodeCount = 0;
this.linkCount = 0;
this.linksDataModel = void 0;
this.linksProcessedData = void 0;
this.nodesDataModel = void 0;
this.nodesProcessedData = void 0;
this.processedNodes = /* @__PURE__ */ new Map();
this.linkGroup = this.contentGroup.appendChild(new Group10({ name: "linkGroup" }));
this.nodeGroup = this.contentGroup.appendChild(new Group10({ name: "nodeGroup" }));
this.focusLinkGroup = this.highlightGroup.appendChild(new Group10({ name: "linkGroup" }));
this.focusNodeGroup = this.highlightGroup.appendChild(new Group10({ name: "nodeGroup" }));
this.highlightLinkGroup = this.highlightGroup.appendChild(new Group10({ name: "linkGroup" }));
this.labelSelection = Selection5.select(
this.labelGroup,
TransformableText
);
this.linkSelection = Selection5.select(
this.linkGroup,
() => this.linkFactory()
);
this.nodeSelection = Selection5.select(
this.nodeGroup,
() => this.nodeFactory()
);
this.focusLinkSelection = Selection5.select(
this.focusLinkGroup,
() => this.linkFactory()
);
this.focusNodeSelection = Selection5.select(
this.focusNodeGroup,
() => this.nodeFactory()
);
this.highlightLinkSelection = Selection5.select(
this.highlightLinkGroup,
() => this.linkFactory()
);
this.highlightNodeSelection = Selection5.select(
this.highlightNodeGroup,
() => this.nodeFactory()
);
}
get nodes() {
return this.properties.nodes;
}
async processData(dataController) {
const { data, nodes } = this;
if (data == null)
return;
const { fromKey, toKey, sizeKey, idKey, labelKey } = this.properties;
const nodesDataController = new DataController(
"standalone",
dataController.suppressFieldDotNotation,
this.ctx.eventsHub
);
const nodesDataModelPromise = nodes == null ? null : nodesDataController.request(
this.id,
_ModuleSupport138.DataSet.wrap(nodes) ?? _ModuleSupport138.DataSet.empty(),
{
props: [
keyProperty7(idKey, void 0, { id: "idValue", includeProperty: false }),
...labelKey == null ? [] : [valueProperty9(labelKey, void 0, { id: "labelValue", includeProperty: false })]
],
groupByKeys: true
}
);
const linksDataModelPromise = dataController.request(this.id, data, {
props: [
valueProperty9(fromKey, void 0, { id: "fromValue", includeProperty: false }),
valueProperty9(toKey, void 0, { id: "toValue", includeProperty: false }),
...sizeKey == null ? [] : [
valueProperty9(sizeKey, void 0, {
id: "sizeValue",
includeProperty: false,
missingValue: 0
})
]
],
groupByKeys: false
});
if (nodes != null) {
nodesDataController.execute();
}
const [nodesDataModel, linksDataModel] = await Promise.all([
nodesDataModelPromise ?? Promise.resolve(null),
linksDataModelPromise
]);
this.nodesDataModel = nodesDataModel?.dataModel;
this.nodesProcessedData = nodesDataModel?.processedData;
this.linksDataModel = linksDataModel?.dataModel;
this.linksProcessedData = linksDataModel?.processedData;
const processedNodes = /* @__PURE__ */ new Map();
if (nodesDataModel == null) {
const fromIdValues = linksDataModel.dataModel.resolveColumnById(
this,
"fromValue",
linksDataModel.processedData
);
const toIdValues = linksDataModel.dataModel.resolveColumnById(
this,
"toValue",
linksDataModel.processedData
);
const createImplicitNode = (id) => {
const datumIndex = processedNodes.size;
const label = id;
return {
series: this,
itemId: `node-${datumIndex}`,
datum: {},
// Must be a referential object for tooltips
datumIndex: { type: 1 /* Node */, index: datumIndex },
type: 1 /* Node */,
index: datumIndex,
linksBefore: [],
linksAfter: [],
id,
size: 0,
label,
style: this.getNodeStyle(
{
datumIndex: { type: 1 /* Node */, index: datumIndex },
datum: {},
size: 0,
label
},
datumIndex,
false
)
};
};
const linkData = linksDataModel.processedData.dataSources.get(this.id)?.data;
if (linkData) {
for (const [datumIndex] of linkData.entries()) {
const fromId = fromIdValues[datumIndex];
const toId = toIdValues[datumIndex];
if (fromId == null || toId == null)
continue;
if (!processedNodes.has(fromId)) {
processedNodes.set(fromId, createImplicitNode(fromId));
}
if (!processedNodes.has(toId)) {
processedNodes.set(toId, createImplicitNode(toId));
}
}
}
} else {
const nodeIdValues = nodesDataModel.dataModel.resolveColumnById(
this,
"idValue",
nodesDataModel.processedData
);
const labelValues = labelKey == null ? void 0 : nodesDataModel.dataModel.resolveColumnById(
this,
"labelValue",
nodesDataModel.processedData
);
const nodeData = nodesDataModel.processedData.dataSources.get(this.id)?.data;
if (nodeData) {
for (const [datumIndex, datum] of nodeData.entries()) {
const id = nodeIdValues[datumIndex];
const label = labelValues?.[datumIndex];
const nodeDatumIndex = { type: 1 /* Node */, index: datumIndex };
processedNodes.set(id, {
series: this,
itemId: `node-${datumIndex}`,
datum,
datumIndex: nodeDatumIndex,
type: 1 /* Node */,
index: datumIndex,
linksBefore: [],
linksAfter: [],
id,
size: 0,
label,
style: this.getNodeStyle(
{ datumIndex: nodeDatumIndex, datum, size: 0, label },
datumIndex,
false
)
});
}
}
}
this.processedNodes = processedNodes;
}
findNodeDatum(itemId) {
return findNodeDatumInArray(itemId, this.contextNodeData?.nodeData);
}
getNodeGraph(createNode, createLink, { includeCircularReferences }) {
const { linksDataModel, linksProcessedData } = this;
if (linksDataModel == null || linksProcessedData == null) {
const { links: links2, nodeGraph: nodeGraph2, maxPathLength: maxPathLength2 } = computeNodeGraph(
(/* @__PURE__ */ new Map()).values(),
[],
includeCircularReferences
);
this.nodeCount = 0;
this.linkCount = 0;
return { nodeGraph: nodeGraph2, links: links2, maxPathLength: maxPathLength2 };
}
const { sizeKey } = this.properties;
const fromIdValues = linksDataModel.resolveColumnById(this, "fromValue", linksProcessedData);
const toIdValues = linksDataModel.resolveColumnById(this, "toValue", linksProcessedData);
const sizeValues = sizeKey == null ? void 0 : linksDataModel.resolveColumnById(this, "sizeValue", linksProcessedData);
const nodesById = /* @__PURE__ */ new Map();
for (const datum of this.processedNodes.values()) {
const node = createNode(datum);
nodesById.set(datum.id, node);
}
const baseLinks = [];
const linkData = linksProcessedData.dataSources.get(this.id)?.data;
if (linkData) {
for (const [datumIndex, datum] of linkData.entries()) {
const fromId = fromIdValues[datumIndex];
const toId = toIdValues[datumIndex];
const size = sizeValues == null ? 1 : sizeValues[datumIndex];
const fromNode = nodesById.get(fromId);
const toNode = nodesById.get(toId);
if (size <= 0 || fromNode == null || toNode == null)
continue;
const linkNodeDatumIndex = { type: 0 /* Link */, index: datumIndex };
const link = createLink({
series: this,
itemId: `link-${datumIndex}`,
datum,
datumIndex: linkNodeDatumIndex,
type: 0 /* Link */,
index: datumIndex,
fromNode,
toNode,
size,
style: this.getLinkStyle(
{ datum, datumIndex: linkNodeDatumIndex },
fromNode.datumIndex,
false
)
});
baseLinks.push(link);
}
}
const { links, nodeGraph, maxPathLength } = computeNodeGraph(
nodesById.values(),
baseLinks,
includeCircularReferences
);
for (const node of nodeGraph.values()) {
node.datum.linksBefore = node.linksBefore.map((linkedNode) => linkedNode.link);
node.datum.linksAfter = node.linksAfter.map((linkedNode) => linkedNode.link);
}
this.nodeCount = nodeGraph.size;
this.linkCount = links.length;
return { nodeGraph, links, maxPathLength };
}
updateSelections() {
if (this.nodeDataRefresh) {
this.contextNodeData = this.createNodeData();
this.nodeDataRefresh = false;
}
}
update(opts) {
const { seriesRect } = opts;
const newNodeDataDependencies = {
seriesRectWidth: seriesRect?.width ?? 0,
seriesRectHeight: seriesRect?.height ?? 0
};
if (this._nodeDataDependencies == null || this._nodeDataDependencies.seriesRectWidth !== newNodeDataDependencies.seriesRectWidth || this._nodeDataDependencies.seriesRectHeight !== newNodeDataDependencies.seriesRectHeight) {
this._nodeDataDependencies = newNodeDataDependencies;
}
this.updateSelections();
const nodeData = this.contextNodeData?.nodeData ?? [];
const labelData = this.contextNodeData?.labelData ?? [];
const highlightedDatum = this.getHighlightedDatum();
this.contentGroup.visible = this.visible;
const highlightState = highlightedDatum == null ? HighlightState4.None : HighlightState4.OtherItem;
this.contentGroup.opacity = this.properties.highlight.getStyle(highlightState).opacity ?? 1;
this.labelSelection = this.updateLabelSelection({ labelData, labelSelection: this.labelSelection });
this.updateLabelNodes({ labelSelection: this.labelSelection });
this.linkSelection = this.updateLinkSelection({
nodeData: nodeData.filter((d) => d.type === 0 /* Link */),
datumSelection: this.linkSelection
});
this.updateLinkNodes({ datumSelection: this.linkSelection, isHighlight: false });
this.nodeSelection = this.updateNodeSelection({
nodeData: nodeData.filter((d) => d.type === 1 /* Node */),
datumSelection: this.nodeSelection
});
this.updateNodeNodes({ datumSelection: this.nodeSelection, isHighlight: false });
let focusLinkSelection;
let focusNodeSelection;
let highlightLinkSelection;
let highlightNodeSelection;
if (highlightedDatum?.type === 1 /* Node */) {
focusLinkSelection = nodeData.filter((node) => {
return node.type === 0 /* Link */ && (node.toNode === highlightedDatum || node.fromNode === highlightedDatum);
});
focusNodeSelection = focusLinkSelection.map((link) => {
return link.fromNode === highlightedDatum ? link.toNode : link.fromNode;
});
focusNodeSelection.push(highlightedDatum);
highlightLinkSelection = [];
highlightNodeSelection = [highlightedDatum];
} else if (highlightedDatum?.type === 0 /* Link */) {
focusLinkSelection = [highlightedDatum];
focusNodeSelection = [highlightedDatum.fromNode, highlightedDatum.toNode];
highlightLinkSelection = [highlightedDatum];
highlightNodeSelection = [];
} else {
focusLinkSelection = [];
focusNodeSelection = [];
highlightLinkSelection = [];
highlightNodeSelection = [];
}
this.focusLinkSelection = this.updateLinkSelection({
nodeData: focusLinkSelection,
datumSelection: this.focusLinkSelection
});
this.updateLinkNodes({ datumSelection: this.focusLinkSelection, isHighlight: false });
this.focusNodeSelection = this.updateNodeSelection({
nodeData: focusNodeSelection,
datumSelection: this.focusNodeSelection
});
this.updateNodeNodes({ datumSelection: this.focusNodeSelection, isHighlight: false });
this.highlightLinkSelection = this.updateLinkSelection({
nodeData: highlightLinkSelection,
datumSelection: this.highlightLinkSelection
});
this.updateLinkNodes({ datumSelection: this.highlightLinkSelection, isHighlight: true });
this.highlightNodeSelection = this.updateNodeSelection({
nodeData: highlightNodeSelection,
datumSelection: this.highlightNodeSelection
});
this.updateNodeNodes({ datumSelection: this.highlightNodeSelection, isHighlight: true });
}
getHighlightedDatum() {
let highlightedDatum = this.ctx.highlightManager?.getActiveHighlight();
if (highlightedDatum?.series === this && highlightedDatum.type == null) {
const { itemId } = highlightedDatum;
const nodeData = this.contextNodeData?.nodeData ?? [];
highlightedDatum = itemId == null ? void 0 : nodeData.find((node) => node.type === 1 /* Node */ && node.id === itemId);
} else if (highlightedDatum?.series !== this) {
highlightedDatum = void 0;
}
return highlightedDatum;
}
isLabelHighlighted(datum, activeHighlight) {
if (activeHighlight == null)
return false;
if (activeHighlight.type === 1 /* Node */) {
return activeHighlight === datum;
}
if (activeHighlight.type === 0 /* Link */) {
return activeHighlight.fromNode === datum || activeHighlight.toNode === datum;
}
return false;
}
resetAnimation(_chartAnimationPhase) {
}
dataCount() {
return Number.NaN;
}
getSeriesDomain(_direction) {
return { domain: [] };
}
getSeriesRange(_direction, _visibleRange) {
return [Number.NaN, Number.NaN];
}
legendItemSymbol(_type, nodeIndex, format = {}) {
const { fills, strokes } = this.properties;
const {
fill = fills[nodeIndex % fills.length],
fillOpacity = 1,
stroke: stroke3 = strokes[nodeIndex % strokes.length],
strokeWidth = 0,
strokeOpacity = 1,
lineDash = [0],
lineDashOffset = 0
} = format;
return {
marker: {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
}
};
}
getLegendData(legendType) {
if (legendType !== "category")
return [];
const { showInLegend } = this.properties;
return Array.from(
this.processedNodes.values(),
({ id, label }, nodeIndex) => ({
legendType: "category",
id: this.id,
itemId: id,
seriesId: this.id,
enabled: true,
label: { text: label ?? id },
symbol: this.legendItemSymbol(1 /* Node */, nodeIndex),
hideInLegend: !showInLegend,
isFixed: true
})
);
}
pickNodeClosestDatum({ x, y }) {
let minDistanceSquared = Infinity;
let minDatum;
this.linkSelection.each((node, datum) => {
const distanceSquared = node.distanceSquared(x, y);
if (distanceSquared < minDistanceSquared) {
minDistanceSquared = distanceSquared;
minDatum = datum;
}
});
this.nodeSelection.each((node, datum) => {
const distanceSquared = node.distanceSquared(x, y);
if (distanceSquared < minDistanceSquared) {
minDistanceSquared = distanceSquared;
minDatum = datum;
}
});
return minDatum == null ? void 0 : { datum: minDatum, distance: Math.sqrt(minDistanceSquared) };
}
getDatumAriaText(datum, description) {
if (datum.type === 0 /* Link */) {
return this.ctx.localeManager.t("ariaAnnounceFlowProportionLink", {
index: datum.index + 1,
count: this.linkCount,
from: datum.fromNode.id,
to: datum.toNode.id,
size: datum.size,
sizeName: this.properties.sizeName ?? this.properties.sizeKey
});
} else if (datum.type === 1 /* Node */) {
return this.ctx.localeManager.t("ariaAnnounceFlowProportionNode", {
index: datum.index + 1,
count: this.nodeCount,
description
});
}
}
pickFocus(opts) {
const { datumIndexDelta: childDelta, otherIndexDelta: depthDelta } = opts;
const currentNodeDatum = this.contextNodeData?.nodeData[opts.datumIndex - opts.datumIndexDelta];
let nextNodeDatum = currentNodeDatum;
if (depthDelta !== 0 || childDelta === 0)
return;
if (currentNodeDatum?.type === 0 /* Link */) {
const allLinks = Array.from(this.linkSelection, (link) => link.datum);
const selfIndex = allLinks.indexOf(currentNodeDatum);
const nextIndex = selfIndex + childDelta;
if (nextIndex >= 0 && nextIndex < allLinks.length) {
nextNodeDatum = allLinks[nextIndex];
} else if (nextIndex > 0) {
nextNodeDatum = allLinks.at(-1);
} else {
const allNodes = Array.from(this.nodeSelection, (node) => node.datum);
nextNodeDatum = allNodes.at(-1);
}
} else if (currentNodeDatum?.type === 1 /* Node */) {
const allNodes = Array.from(this.nodeSelection, (node) => node.datum);
const selfIndex = allNodes.indexOf(currentNodeDatum);
const nextIndex = selfIndex + childDelta;
if (nextIndex >= 0 && nextIndex < allNodes.length) {
nextNodeDatum = allNodes[nextIndex];
} else if (nextIndex < 0) {
nextNodeDatum = allNodes[0];
} else {
const allLinks = Array.from(this.linkSelection, (link) => link.datum);
nextNodeDatum = allLinks[0];
}
}
if (nextNodeDatum == null)
return;
const nodeDatum = nextNodeDatum.type === 1 /* Node */ ? Array.from(this.nodeSelection).find((n) => n.datum === nextNodeDatum) : Array.from(this.linkSelection).find((n) => n.datum === nextNodeDatum);
if (nodeDatum == null)
return;
const bounds = this.computeFocusBounds(nodeDatum.node);
if (bounds == null)
return;
return {
datum: nodeDatum.datum,
datumIndex: this.contextNodeData?.nodeData.indexOf(nodeDatum.datum) ?? 0,
otherIndex: 0,
bounds,
clipFocusBox: true
};
}
getCategoryValue(_datumIndex) {
return;
}
datumIndexForCategoryValue(_categoryValue) {
return;
}
};
// packages/ag-charts-enterprise/src/series/chord/chordLink.ts
import { _ModuleSupport as _ModuleSupport139 } from "ag-charts-community";
import { SceneChangeDetection as SceneChangeDetection6 } from "ag-charts-core";
var { Path: Path9 } = _ModuleSupport139;
function bezierControlPoints({
radius,
startAngle,
endAngle,
tension
}) {
const cp0x = radius * Math.cos(startAngle);
const cp0y = radius * Math.sin(startAngle);
const cp3x = radius * Math.cos(endAngle);
const cp3y = radius * Math.sin(endAngle);
const cp1x = cp0x * tension;
const cp1y = cp0y * tension;
const cp2x = cp3x * tension;
const cp2y = cp3y * tension;
return {
x: [cp0x, cp1x, cp2x, cp3x],
y: [cp0y, cp1y, cp2y, cp3y]
};
}
var ChordLink = class extends Path9 {
constructor() {
super(...arguments);
this.centerX = 0;
this.centerY = 0;
this.radius = 0;
this.startAngle1 = 0;
this.endAngle1 = 0;
this.startAngle2 = 0;
this.endAngle2 = 0;
this.tension = 1;
}
tensionedCurveTo(cp0x, cp0y, cp1x, cp1y, cp2x, cp2y, cp3x, cp3y) {
const { path, tension } = this;
const scale = 1 - tension;
path.cubicCurveTo(
(cp1x - cp0x) * scale + cp0x,
(cp1y - cp0y) * scale + cp0y,
(cp2x - cp3x) * scale + cp3x,
(cp2y - cp3y) * scale + cp3y,
cp3x,
cp3y
);
}
updatePath() {
const { path, centerX, centerY, radius } = this;
let { startAngle1, endAngle1, startAngle2, endAngle2 } = this;
if (startAngle1 > startAngle2) {
[startAngle1, startAngle2] = [startAngle2, startAngle1];
[endAngle1, endAngle2] = [endAngle2, endAngle1];
}
path.clear();
const startX = centerX + radius * Math.cos(startAngle1);
const startY = centerY + radius * Math.sin(startAngle1);
path.moveTo(startX, startY);
this.tensionedCurveTo(
startX,
startY,
centerX,
centerY,
centerX,
centerY,
centerX + radius * Math.cos(endAngle2),
centerY + radius * Math.sin(endAngle2)
);
path.arc(centerX, centerY, radius, endAngle2, startAngle2, true);
this.tensionedCurveTo(
centerX + radius * Math.cos(startAngle2),
centerY + radius * Math.sin(startAngle2),
centerX,
centerY,
centerX,
centerY,
centerX + radius * Math.cos(endAngle1),
centerY + radius * Math.sin(endAngle1)
);
path.arc(centerX, centerY, radius, endAngle1, startAngle1, true);
path.closePath();
}
};
__decorateClass([
SceneChangeDetection6()
], ChordLink.prototype, "centerX", 2);
__decorateClass([
SceneChangeDetection6()
], ChordLink.prototype, "centerY", 2);
__decorateClass([
SceneChangeDetection6()
], ChordLink.prototype, "radius", 2);
__decorateClass([
SceneChangeDetection6()
], ChordLink.prototype, "startAngle1", 2);
__decorateClass([
SceneChangeDetection6()
], ChordLink.prototype, "endAngle1", 2);
__decorateClass([
SceneChangeDetection6()
], ChordLink.prototype, "startAngle2", 2);
__decorateClass([
SceneChangeDetection6()
], ChordLink.prototype, "endAngle2", 2);
__decorateClass([
SceneChangeDetection6()
], ChordLink.prototype, "tension", 2);
// packages/ag-charts-enterprise/src/series/chord/chordSeriesProperties.ts
import {
_ModuleSupport as _ModuleSupport140
} from "ag-charts-community";
import { BaseProperties as BaseProperties30, Property as Property69 } from "ag-charts-core";
var { FillGradientDefaults: FillGradientDefaults2, FillPatternDefaults: FillPatternDefaults2, FillImageDefaults: FillImageDefaults2, makeSeriesTooltip: makeSeriesTooltip8, SeriesProperties, Label: Label6 } = _ModuleSupport140;
var ChordSeriesLabelProperties = class extends Label6 {
constructor() {
super(...arguments);
this.spacing = 1;
this.maxWidth = 1;
}
};
__decorateClass([
Property69
], ChordSeriesLabelProperties.prototype, "spacing", 2);
__decorateClass([
Property69
], ChordSeriesLabelProperties.prototype, "maxWidth", 2);
var ChordSeriesLinkProperties = class extends BaseProperties30 {
constructor() {
super(...arguments);
this.fill = void 0;
this.fillOpacity = 1;
this.stroke = void 0;
this.strokeOpacity = 1;
this.strokeWidth = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.tension = 0;
}
getStyle(fills, strokes, index) {
const { fillOpacity, strokeWidth, strokeOpacity, lineDash, lineDashOffset, tension } = this;
const fill = this.fill ?? fills[index % fills.length];
const stroke3 = this.stroke ?? strokes[index % fills.length];
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
tension
};
}
};
__decorateClass([
Property69
], ChordSeriesLinkProperties.prototype, "fill", 2);
__decorateClass([
Property69
], ChordSeriesLinkProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property69
], ChordSeriesLinkProperties.prototype, "stroke", 2);
__decorateClass([
Property69
], ChordSeriesLinkProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property69
], ChordSeriesLinkProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property69
], ChordSeriesLinkProperties.prototype, "lineDash", 2);
__decorateClass([
Property69
], ChordSeriesLinkProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property69
], ChordSeriesLinkProperties.prototype, "tension", 2);
__decorateClass([
Property69
], ChordSeriesLinkProperties.prototype, "itemStyler", 2);
var ChordSeriesNodeProperties = class extends BaseProperties30 {
constructor() {
super(...arguments);
this.spacing = 1;
this.width = 1;
this.fill = void 0;
this.fillOpacity = 1;
this.stroke = void 0;
this.strokeOpacity = 1;
this.strokeWidth = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
}
getStyle(fills, strokes, index) {
const { fillOpacity, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = this;
const fill = this.fill ?? fills[index % fills.length];
const stroke3 = this.stroke ?? strokes[index % fills.length];
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
};
}
};
__decorateClass([
Property69
], ChordSeriesNodeProperties.prototype, "spacing", 2);
__decorateClass([
Property69
], ChordSeriesNodeProperties.prototype, "width", 2);
__decorateClass([
Property69
], ChordSeriesNodeProperties.prototype, "fill", 2);
__decorateClass([
Property69
], ChordSeriesNodeProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property69
], ChordSeriesNodeProperties.prototype, "stroke", 2);
__decorateClass([
Property69
], ChordSeriesNodeProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property69
], ChordSeriesNodeProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property69
], ChordSeriesNodeProperties.prototype, "lineDash", 2);
__decorateClass([
Property69
], ChordSeriesNodeProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property69
], ChordSeriesNodeProperties.prototype, "itemStyler", 2);
var ChordSeriesProperties = class extends SeriesProperties {
constructor() {
super(...arguments);
this.idKey = "";
this.idName = void 0;
this.labelKey = void 0;
this.labelName = void 0;
this.sizeKey = void 0;
this.sizeName = void 0;
this.nodes = void 0;
this.fillGradientDefaults = new FillGradientDefaults2();
this.fillPatternDefaults = new FillPatternDefaults2();
this.fillImageDefaults = new FillImageDefaults2();
this.fills = [];
this.strokes = [];
this.label = new ChordSeriesLabelProperties();
this.link = new ChordSeriesLinkProperties();
this.node = new ChordSeriesNodeProperties();
this.tooltip = makeSeriesTooltip8();
}
};
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "fromKey", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "toKey", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "idKey", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "idName", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "labelKey", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "labelName", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "sizeKey", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "sizeName", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "nodes", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "fillGradientDefaults", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "fillPatternDefaults", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "fillImageDefaults", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "fills", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "strokes", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "label", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "link", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "node", 2);
__decorateClass([
Property69
], ChordSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/chord/chordSeries.ts
var { SeriesNodePickMode: SeriesNodePickMode6, createDatumId: createDatumId7, Sector: Sector3, getShapeStyle, getLabelStyles, BBox: BBox17 } = _ModuleSupport141;
var nodeMidAngle = (node) => node.startAngle + angleBetween2(node.startAngle, node.endAngle) / 2;
var ChordSeries = class extends FlowProportionSeries {
constructor(moduleCtx) {
super({
moduleCtx,
pickModes: [SeriesNodePickMode6.NEAREST_NODE, SeriesNodePickMode6.EXACT_SHAPE_MATCH]
});
this.properties = new ChordSeriesProperties();
}
isLabelEnabled() {
return (this.properties.labelKey != null || this.nodes == null) && this.properties.label.enabled;
}
linkFactory() {
return new ChordLink();
}
nodeFactory() {
return new Sector3();
}
createNodeData() {
const {
id: seriesId,
_nodeDataDependencies: { seriesRectWidth, seriesRectHeight } = { seriesRectWidth: 0, seriesRectHeight: 0 },
properties
} = this;
const {
fromKey,
toKey,
sizeKey,
labelKey,
label: { spacing: labelSpacing, maxWidth: labelMaxWidth, fontSize },
node: { width: nodeWidth, spacing: nodeSpacing }
} = properties;
const centerX = seriesRectWidth / 2;
const centerY = seriesRectHeight / 2;
let labelData = [];
const { nodeGraph, links } = this.getNodeGraph(
(node) => ({
...node,
centerX,
centerY,
innerRadius: Number.NaN,
outerRadius: Number.NaN,
startAngle: Number.NaN,
endAngle: Number.NaN
}),
(link) => ({
...link,
centerX,
centerY,
radius: Number.NaN,
startAngle1: Number.NaN,
endAngle1: Number.NaN,
startAngle2: Number.NaN,
endAngle2: Number.NaN
}),
{ includeCircularReferences: true }
);
let totalSize = 0;
for (const [id, { datum: node, linksBefore, linksAfter }] of nodeGraph.entries()) {
const size = linksBefore.reduce((acc, { link }) => acc + link.size, 0) + linksAfter.reduce((acc, { link }) => acc + link.size, 0);
if (size === 0) {
nodeGraph.delete(id);
} else {
const { label } = properties;
node.size = size;
totalSize += node.size;
const labelText = label.enabled ? this.getLabelText(
node.label,
node.datum,
labelKey,
"label",
[],
label,
{ datum: node.datum, value: node.label, fromKey, toKey, sizeKey, size: node.size }
) : void 0;
node.label = toPlainText5(labelText);
}
}
let labelInset = 0;
if (this.isLabelEnabled()) {
const measurer3 = cachedTextMeasurer5(this.properties.label);
let maxMeasuredLabelWidth = 0;
for (const { datum: node } of nodeGraph.values()) {
const { id, label } = node;
if (label == null)
continue;
const text2 = wrapText3(label, {
maxWidth: labelMaxWidth,
font: this.properties.label,
textWrap: "never"
});
const { width } = measurer3.measureLines(text2);
maxMeasuredLabelWidth = Math.max(width, maxMeasuredLabelWidth);
labelData.push({
id,
text: text2,
centerX,
centerY,
angle: Number.NaN,
radius: Number.NaN,
size: node.size,
datumIndex: node.datumIndex,
nodeDatum: node
});
}
labelInset = maxMeasuredLabelWidth + labelSpacing;
}
const nodeCount = nodeGraph.size;
let radius = Math.min(seriesRectWidth, seriesRectHeight) / 2 - nodeWidth - labelInset;
let spacingSweep = nodeSpacing / radius;
if (labelInset !== 0 && (nodeCount * spacingSweep >= 1.5 * Math.PI || radius <= 0)) {
labelData = [];
radius = Math.min(seriesRectWidth, seriesRectHeight) / 2 - nodeWidth;
spacingSweep = nodeSpacing / radius;
}
if (nodeCount * spacingSweep >= 2 * Math.PI || radius <= 0) {
Logger15.warnOnce("There was insufficient space to display the Chord Series.");
return;
}
const innerRadius = radius;
const outerRadius = radius + nodeWidth;
const sizeScale = Math.max((2 * Math.PI - nodeCount * spacingSweep) / totalSize, 0);
let nodeAngle = 0;
for (const { datum: node } of nodeGraph.values()) {
node.innerRadius = innerRadius;
node.outerRadius = outerRadius;
node.startAngle = nodeAngle;
node.endAngle = nodeAngle + node.size * sizeScale;
nodeAngle = node.endAngle + spacingSweep;
const midR = (node.innerRadius + node.outerRadius) / 2;
const midAngle = nodeMidAngle(node);
node.midPoint = {
x: node.centerX + midR * Math.cos(midAngle),
y: node.centerY + midR * Math.sin(midAngle)
};
}
const nodeData = [];
for (const { datum: node, linksBefore, linksAfter } of nodeGraph.values()) {
const midAngle = nodeMidAngle(node);
const combinedLinks = [
...linksBefore.map((l) => ({
link: l.link,
distance: angleBetween2(nodeMidAngle(l.node.datum), midAngle),
after: false
})),
...linksAfter.map((l) => ({
link: l.link,
distance: angleBetween2(nodeMidAngle(l.node.datum), midAngle),
after: true
}))
];
let linkAngle = node.startAngle;
for (const { link, after } of combinedLinks.toSorted((a, b) => a.distance - b.distance)) {
const linkSweep = link.size * sizeScale;
if (after) {
link.startAngle1 = linkAngle;
link.endAngle1 = linkAngle + linkSweep;
} else {
link.startAngle2 = linkAngle;
link.endAngle2 = linkAngle + linkSweep;
}
linkAngle += link.size * sizeScale;
}
nodeData.push(node);
}
const { tension } = this.properties.link;
for (const link of links) {
link.radius = radius;
const outer = bezierControlPoints({
radius,
startAngle: link.startAngle1,
endAngle: link.endAngle2,
tension
});
const inner = bezierControlPoints({
radius,
startAngle: link.startAngle2,
endAngle: link.endAngle1,
tension
});
const outerX = evaluateBezier(...outer.x, 0.5);
const outerY = evaluateBezier(...outer.y, 0.5);
const innerX = evaluateBezier(...inner.x, 0.5);
const innerY = evaluateBezier(...inner.y, 0.5);
link.midPoint = {
x: link.centerX + (outerX + innerX) / 2,
y: link.centerY + (outerY + innerY) / 2
};
nodeData.push(link);
}
for (const label of labelData) {
const node = nodeGraph.get(label.id)?.datum;
if (node == null)
continue;
label.radius = outerRadius + labelSpacing;
label.angle = normalizeAngle3604(node.startAngle + angleBetween2(node.startAngle, node.endAngle) / 2);
label.datumIndex = node.datumIndex;
label.nodeDatum = node;
}
labelData.sort((a, b) => a.angle - b.angle);
let minAngle = Infinity;
let maxAngle = -Infinity;
labelData = labelData.filter((label) => {
const labelHeight = calcLineHeight6(fontSize);
const da = Math.atan2(labelHeight / 2, label.radius);
const a0 = label.angle - da;
const a1 = label.angle + da;
if (isBetweenAngles(minAngle, a0, a1))
return false;
if (isBetweenAngles(maxAngle, a0, a1))
return false;
minAngle = Math.min(a0, minAngle);
maxAngle = Math.max(a1, maxAngle);
return true;
});
return {
itemId: seriesId,
nodeData,
labelData
};
}
updateLabelSelection(opts) {
const labels = this.isLabelEnabled() ? opts.labelData : [];
return opts.labelSelection.update(labels);
}
updateLabelNodes(opts) {
const params = {
toKey: this.properties.toKey,
fromKey: this.properties.fromKey,
sizeKey: this.properties.sizeKey,
size: Number.NaN
};
const activeHighlightDatum = this.getHighlightedDatum();
opts.labelSelection.each((label, labelNodeDatum) => {
const { size, text: text2, centerX, centerY, radius, angle, datumIndex, nodeDatum } = labelNodeDatum;
params.size = size;
const isHighlight = this.isLabelHighlighted(nodeDatum, activeHighlightDatum);
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
const style = getLabelStyles(
this,
void 0,
params,
this.properties.label,
isHighlight,
activeHighlightDatum
);
const { fontStyle, fontWeight, fontSize, fontFamily, color: fill } = style;
label.visible = true;
label.translationX = centerX + radius * Math.cos(angle);
label.translationY = centerY + radius * Math.sin(angle);
label.text = text2;
label.fill = fill;
label.fontStyle = fontStyle;
label.fontWeight = fontWeight;
label.fontSize = fontSize;
label.fontFamily = fontFamily;
label.textBaseline = "middle";
if (Math.cos(angle) >= 0) {
label.textAlign = "left";
label.rotation = angle;
} else {
label.textAlign = "right";
label.rotation = angle - Math.PI;
}
const opacity = highlightStyle.opacity ?? 1;
label.opacity = opacity;
label.fillOpacity = opacity;
label.setBoxing(style);
});
}
updateNodeSelection(opts) {
return opts.datumSelection.update(opts.nodeData, void 0, (datum) => createDatumId7(datum.type, datum.id));
}
getNodeStyle(nodeDatum, fromNodeDatumIndex, isHighlight) {
const { properties } = this;
const { fills, strokes, fillGradientDefaults: fillGradientDefaults3, fillPatternDefaults: fillPatternDefaults3, fillImageDefaults: fillImageDefaults3 } = properties;
const { itemStyler } = properties.node;
const highlightStyle = this.getHighlightStyle(isHighlight, nodeDatum.datumIndex);
const baseStyle = mergeDefaults10(highlightStyle, properties.node.getStyle(fills, strokes, fromNodeDatumIndex));
let style = getShapeStyle(baseStyle, fillGradientDefaults3, fillPatternDefaults3, fillImageDefaults3);
if (itemStyler != null && nodeDatum.datumIndex != null) {
const overrides = this.cachedDatumCallback(
createDatumId7(nodeDatum.datumIndex.index, "node", isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(nodeDatum, isHighlight, style);
return this.callWithContext(itemStyler, params);
}
);
if (overrides) {
style = getShapeStyle(
mergeDefaults10(overrides, style),
fillGradientDefaults3,
fillPatternDefaults3,
fillImageDefaults3
);
}
}
style.opacity = 1;
return style;
}
makeItemStylerParams({ datum, datumIndex, size = 0, label }, isHighlight, style) {
const { id: seriesId } = this;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightState = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum,
highlightState,
...style,
size,
label,
fill
};
}
updateNodeNodes(opts) {
const { datumSelection, isHighlight } = opts;
const fillBBox = this.getShapeFillBBox();
datumSelection.each((sector, datum) => {
const { datumIndex } = datum;
const style = this.getNodeStyle(datum, datumIndex.index, isHighlight);
sector.setStyleProperties(style, fillBBox);
sector.centerX = datum.centerX;
sector.centerY = datum.centerY;
sector.innerRadius = datum.innerRadius;
sector.outerRadius = datum.outerRadius;
sector.startAngle = datum.startAngle;
sector.endAngle = datum.endAngle;
sector.inset = sector.strokeWidth / 2;
});
}
updateLinkSelection(opts) {
return opts.datumSelection.update(
opts.nodeData,
void 0,
(datum) => createDatumId7(datum.type, datum.index, datum.fromNode.id, datum.toNode.id)
);
}
getLinkStyle({ datumIndex, datum }, fromNodeDatumIndex, isHighlight) {
const { id: seriesId, properties } = this;
const { fills, strokes, fillGradientDefaults: fillGradientDefaults3, fillPatternDefaults: fillPatternDefaults3, fillImageDefaults: fillImageDefaults3 } = properties;
const { itemStyler } = properties.link;
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
const baseStyle = mergeDefaults10(
highlightStyle,
properties.link.getStyle(fills, strokes, fromNodeDatumIndex.index)
);
let style = getShapeStyle(baseStyle, fillGradientDefaults3, fillPatternDefaults3, fillImageDefaults3);
if (itemStyler != null && datumIndex != null) {
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const overrides = this.cachedDatumCallback(
createDatumId7(datumIndex.index, "link", isHighlight ? "highlight" : "node"),
() => {
const highlightState = this.getHighlightStateString(
activeHighlight,
isHighlight,
fromNodeDatumIndex
);
return this.callWithContext(itemStyler, {
seriesId,
datum,
highlightState,
...style
});
}
);
if (overrides) {
style = getShapeStyle(
mergeDefaults10(overrides, style),
fillGradientDefaults3,
fillPatternDefaults3,
fillImageDefaults3
);
}
}
style.opacity = 1;
return style;
}
updateLinkNodes(opts) {
const { datumSelection, isHighlight } = opts;
const fillBBox = this.getShapeFillBBox();
datumSelection.each((link, datum) => {
const fromNodeDatumIndex = datum.fromNode.datumIndex;
const style = this.getLinkStyle(datum, fromNodeDatumIndex, isHighlight);
link.centerX = datum.centerX;
link.centerY = datum.centerY;
link.radius = datum.radius;
link.startAngle1 = datum.startAngle1;
link.endAngle1 = datum.endAngle1;
link.startAngle2 = datum.startAngle2;
link.endAngle2 = datum.endAngle2;
link.tension = style.tension;
link.setStyleProperties(style, fillBBox);
});
}
getShapeFillBBox() {
const width = this._nodeDataDependencies?.seriesRectWidth ?? 0;
const height = this._nodeDataDependencies?.seriesRectHeight ?? 0;
const size = Math.min(width, height);
const x = (width - size) / 2;
const y = (height - size) / 2;
const bbox = new BBox17(x, y, width, height);
return { series: bbox, axis: bbox };
}
getTooltipContent(datumIndex) {
const {
id: seriesId,
linksProcessedData,
nodesProcessedData,
properties,
ctx: { formatManager }
} = this;
const { fromKey, toKey, sizeKey, sizeName, tooltip } = properties;
const seriesDatum = this.contextNodeData?.nodeData.find(
(d) => d.datumIndex.type === datumIndex.type && d.datumIndex.index === datumIndex.index
);
if (seriesDatum == null)
return;
const nodeIndex = seriesDatum.type === 0 /* Link */ ? seriesDatum.fromNode.index : seriesDatum.index;
const title = seriesDatum.type === 0 /* Link */ ? `${seriesDatum.fromNode.label} - ${seriesDatum.toNode.label}` : seriesDatum.label;
const datum = datumIndex.type === 0 /* Link */ ? linksProcessedData?.dataSources.get(this.id)?.data[datumIndex.index] : nodesProcessedData?.dataSources.get(this.id)?.data[datumIndex.index];
const size = seriesDatum.size;
let format;
if (seriesDatum.type === 0 /* Link */) {
const fromNodeDatumIndex = seriesDatum.fromNode.datumIndex;
format = this.getLinkStyle({ datumIndex, datum }, fromNodeDatumIndex, false);
} else {
const label = seriesDatum.label;
format = this.getNodeStyle({ datumIndex, datum, size, label }, datumIndex.index, false);
}
const data = [];
if (sizeKey != null) {
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: size,
datum,
seriesId,
legendItemName: void 0,
key: sizeKey,
source: "tooltip",
property: "size",
domain: [],
boundSeries: this.getFormatterContext("size"),
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: sizeName, fallbackLabel: sizeKey, value: content ?? String(size) });
}
return this.formatTooltipWithContext(
tooltip,
{
title,
symbol: this.legendItemSymbol(seriesDatum.type, nodeIndex, format),
data
},
{
seriesId,
datum,
title,
fromKey,
toKey,
sizeKey,
sizeName,
size,
...format
}
);
}
computeFocusBounds(node) {
return node;
}
hasItemStylers() {
return this.properties.node.itemStyler != null || this.properties.link.itemStyler != null || this.properties.label.itemStyler != null;
}
};
ChordSeries.className = "ChordSeries";
ChordSeries.type = "chord";
// packages/ag-charts-enterprise/src/series/chord/chordSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport142 } from "ag-charts-community";
import {
commonSeriesOptionsDefs as commonSeriesOptionsDefs8,
constant as constant8,
fillGradientDefaults,
fillImageDefaults,
fillPatternDefaults,
required as required8,
string as string10,
undocumented as undocumented9
} from "ag-charts-core";
var { chordSeriesThemeableOptionsDef } = _ModuleSupport142;
var chordSeriesOptionsDef = {
...chordSeriesThemeableOptionsDef,
...commonSeriesOptionsDefs8,
type: required8(constant8("chord")),
fromKey: required8(string10),
toKey: required8(string10),
sizeKey: string10,
sizeName: string10
};
chordSeriesOptionsDef.fillGradientDefaults = undocumented9(fillGradientDefaults);
chordSeriesOptionsDef.fillPatternDefaults = undocumented9(fillPatternDefaults);
chordSeriesOptionsDef.fillImageDefaults = undocumented9(fillImageDefaults);
// packages/ag-charts-enterprise/src/series/chord/chordModule.ts
var ChordSeriesModule = {
type: "series",
name: "chord",
chartType: "standalone",
enterprise: true,
solo: true,
version: VERSION30,
dependencies: [StandaloneChartModule],
options: chordSeriesOptionsDef,
themeTemplate: {
series: {
fills: { $palette: "fills" },
strokes: { $palette: "strokes" },
fillGradientDefaults: FILL_GRADIENT_LINEAR_DEFAULTS4,
fillPatternDefaults: FILL_PATTERN_DEFAULTS4,
fillImageDefaults: FILL_IMAGE_DEFAULTS6,
highlight: SINGLE_SERIES_HIGHLIGHT_STYLE2,
label: {
...LABEL_BOXING_DEFAULTS5,
enabled: true,
fontFamily: { $ref: "fontFamily" },
fontSize: { $ref: "fontSize" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "textColor" },
spacing: 5,
maxWidth: 100
},
node: {
spacing: 8,
width: 10,
strokeWidth: { $isUserOption: ["./stroke", 2, 0] }
},
link: {
fillOpacity: 0.5,
strokeWidth: { $isUserOption: ["./stroke", 2, 0] },
tension: 0.4
}
},
legend: {
enabled: false,
toggleSeries: false
}
},
create: (ctx) => new ChordSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/cone-funnel/coneFunnelModule.ts
import { CartesianChartModule as CartesianChartModule8, VERSION as VERSION31 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/series/funnel/funnelThemes.ts
import {
CARTESIAN_AXIS_TYPE as CARTESIAN_AXIS_TYPE9,
CARTESIAN_POSITION as CARTESIAN_POSITION5,
DEFAULT_SHADOW_COLOUR,
FILL_GRADIENT_LINEAR_SINGLE_DEFAULTS,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS7,
FILL_PATTERN_SINGLE_DEFAULTS,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS6
} from "ag-charts-core";
var isHorizontal = { $eq: [{ $path: ["/series/0/direction", void 0] }, "horizontal"] };
var labelOptions = { $clone: { $omit: [["placement", "spacing"], { $path: "/series/0/stageLabel" }] } };
var FUNNEL_SERIES_AXES = {
y: {
type: {
$if: [isHorizontal, CARTESIAN_AXIS_TYPE9.NUMBER, CARTESIAN_AXIS_TYPE9.CATEGORY]
},
position: {
$if: [
isHorizontal,
CARTESIAN_POSITION5.LEFT,
{
$if: [
{ $eq: [{ $path: ["/series/0/stageLabel/placement", void 0] }, "after"] },
CARTESIAN_POSITION5.RIGHT,
CARTESIAN_POSITION5.LEFT
]
}
]
},
label: {
$if: [isHorizontal, void 0, labelOptions]
}
},
x: {
type: {
$if: [isHorizontal, CARTESIAN_AXIS_TYPE9.CATEGORY, CARTESIAN_AXIS_TYPE9.NUMBER]
},
position: {
$if: [
isHorizontal,
{
$if: [
{ $eq: [{ $path: ["/series/0/stageLabel/placement", void 0] }, "before"] },
CARTESIAN_POSITION5.TOP,
CARTESIAN_POSITION5.BOTTOM
]
},
CARTESIAN_POSITION5.BOTTOM
]
},
label: {
$if: [isHorizontal, labelOptions, void 0]
}
}
};
var FUNNEL_SERIES_THEME = {
series: {
direction: "vertical",
strokeWidth: { $isUserOption: ["./strokes/0", 2, 0] },
spacingRatio: 0.25,
fills: {
$applyCycle: [
{ $size: { $path: ["./data", { $path: "/data" }] } },
[{ $path: ["/0", void 0, { $palette: "fills" }] }],
{
$applySwitch: [
{ $path: ["/type", void 0, { $value: "$1" }] },
{ $value: "$1" },
["gradient", FILL_GRADIENT_LINEAR_SINGLE_DEFAULTS],
["pattern", FILL_PATTERN_SINGLE_DEFAULTS],
["image", FILL_IMAGE_DEFAULTS7]
]
}
]
},
strokes: {
$applyCycle: [
{ $size: { $path: ["./data", { $path: "/data" }] } },
[{ $path: ["/0", void 0, { $palette: "strokes" }] }]
]
},
label: {
...LABEL_BOXING_DEFAULTS6,
enabled: true,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "chartBackgroundColor" }
},
dropOff: {
enabled: true,
fillOpacity: 0.2,
strokeWidth: { $isUserOption: ["./stroke", 2, 0] }
},
shadow: {
enabled: false,
color: DEFAULT_SHADOW_COLOUR,
xOffset: 3,
yOffset: 3,
blur: 5
},
highlight: {
unhighlightedItem: {
opacity: 0.6
}
}
},
axes: {
[CARTESIAN_AXIS_TYPE9.NUMBER]: {
nice: false,
gridLine: {
enabled: false
},
crosshair: {
enabled: false
},
label: {
enabled: false
}
},
[CARTESIAN_AXIS_TYPE9.CATEGORY]: {
line: {
enabled: false
}
}
}
};
// packages/ag-charts-enterprise/src/series/cone-funnel/coneFunnelSeries.ts
import {
_ModuleSupport as _ModuleSupport147
} from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection42 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/funnel/baseFunnelSeries.ts
import {
_ModuleSupport as _ModuleSupport145
} from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection41, SeriesZIndexMap } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/funnel/funnelConnector.ts
import { _ModuleSupport as _ModuleSupport143 } from "ag-charts-community";
import { SceneChangeDetection as SceneChangeDetection7, lineDistanceSquared } from "ag-charts-core";
var { BBox: BBox18, Path: Path10 } = _ModuleSupport143;
var delta = 1e-6;
function pointsEq([ax, ay], [bx, by]) {
return Math.abs(ax - bx) <= delta && Math.abs(ay - by) <= delta;
}
var FunnelConnector = class extends Path10 {
constructor() {
super(...arguments);
this.x0 = 0;
this.y0 = 0;
this.x1 = 0;
this.y1 = 0;
this.x2 = 0;
this.y2 = 0;
this.x3 = 0;
this.y3 = 0;
}
get midPoint() {
const { x0, y0, x1, y1, x2, y2, x3, y3 } = this;
return {
x: (x0 + x1 + x2 + x3) / 4,
y: (y0 + y1 + y2 + y3) / 4
};
}
distanceSquared(x, y) {
if (this.containsPoint(x, y))
return 0;
const { x0, y0, x1, y1, x2, y2, x3, y3 } = this;
return Math.min(
lineDistanceSquared(x, y, x0, y0, x1, y1, Infinity),
lineDistanceSquared(x, y, x1, y1, x2, y2, Infinity),
lineDistanceSquared(x, y, x2, y2, x3, y3, Infinity),
lineDistanceSquared(x, y, x3, y3, x0, y0, Infinity)
);
}
computeBBox() {
const { x0, y0, x1, y1, x2, y2, x3, y3 } = this;
const x = Math.min(x0, x1, x2, x3);
const width = Math.max(x0, x1, x2, x3) - x;
const y = Math.min(y0, y1, y2, y3);
const height = Math.max(y0, y1, y2, y3) - y;
return new BBox18(x, y, width, height);
}
updatePath() {
const { path, x0, y0, x1, y1, x2, y2, x3, y3 } = this;
const points = [
[x0, y0],
[x1, y1],
[x2, y2],
[x3, y3]
];
path.clear();
let start;
let current;
for (const p of points) {
if (start != null && pointsEq(start, p) || current != null && pointsEq(current, p)) {
continue;
}
const [x, y] = p;
if (start == null) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
start ?? (start = p);
current = p;
}
path.closePath();
}
};
__decorateClass([
SceneChangeDetection7()
], FunnelConnector.prototype, "x0", 2);
__decorateClass([
SceneChangeDetection7()
], FunnelConnector.prototype, "y0", 2);
__decorateClass([
SceneChangeDetection7()
], FunnelConnector.prototype, "x1", 2);
__decorateClass([
SceneChangeDetection7()
], FunnelConnector.prototype, "y1", 2);
__decorateClass([
SceneChangeDetection7()
], FunnelConnector.prototype, "x2", 2);
__decorateClass([
SceneChangeDetection7()
], FunnelConnector.prototype, "y2", 2);
__decorateClass([
SceneChangeDetection7()
], FunnelConnector.prototype, "x3", 2);
__decorateClass([
SceneChangeDetection7()
], FunnelConnector.prototype, "y3", 2);
// packages/ag-charts-enterprise/src/series/funnel/funnelUtil.ts
import { _ModuleSupport as _ModuleSupport144 } from "ag-charts-community";
var { NODE_UPDATE_STATE_TO_PHASE_MAPPING } = _ModuleSupport144;
function connectorStartingPosition(datum, _prevDatum, isVertical, _mode) {
const { x0, y0, x1, y1, x2, y2, x3, y3, opacity } = datum;
if (isVertical) {
return {
x0: (x0 + x3) / 2,
y0: (y0 + y3) / 2,
x1: (x1 + x2) / 2,
y1: (y1 + y2) / 2,
x2: (x1 + x2) / 2,
y2: (y1 + y2) / 2,
x3: (x0 + x3) / 2,
y3: (y0 + y3) / 2,
opacity
};
} else {
return {
x0: (x0 + x1) / 2,
y0: (y0 + y1) / 2,
x1: (x0 + x1) / 2,
y1: (y0 + y1) / 2,
x2: (x2 + x3) / 2,
y2: (y2 + y3) / 2,
x3: (x2 + x3) / 2,
y3: (y2 + y3) / 2,
opacity
};
}
}
function prepareConnectorAnimationFunctions(isVertical, mode) {
const isRemoved = (datum) => datum == null;
const fromFn = (connector, datum, status) => {
if (status === "updated" && isRemoved(datum)) {
status = "removed";
} else if (status === "updated" && isRemoved(connector.previousDatum)) {
status = "added";
}
let source;
if (status === "added" && connector.previousDatum == null && mode === "fade") {
source = { ...resetConnectorSelectionsFn(connector, datum), opacity: 0 };
} else if (status === "unknown" || status === "added") {
source = connectorStartingPosition(datum, connector.previousDatum, isVertical, mode);
} else {
source = {
x0: connector.x0,
y0: connector.y0,
x1: connector.x1,
y1: connector.y1,
x2: connector.x2,
y2: connector.y2,
x3: connector.x3,
y3: connector.y3,
opacity: connector.opacity
};
}
const phase = NODE_UPDATE_STATE_TO_PHASE_MAPPING[status];
return { ...source, phase };
};
const toFn = (connector, datum, status) => {
let source;
if (status === "removed" && connector.datum == null && mode === "fade") {
source = { ...resetConnectorSelectionsFn(connector, datum), opacity: 0 };
} else if (status === "removed" || isRemoved(datum)) {
source = connectorStartingPosition(datum, connector.previousDatum, isVertical, mode);
} else {
source = resetConnectorSelectionsFn(connector, datum);
}
return source;
};
return { fromFn, toFn };
}
function resetConnectorSelectionsFn(_node, datum) {
const { x0, y0, x1, y1, x2, y2, x3, y3, opacity } = datum;
return { x0, y0, x1, y1, x2, y2, x3, y3, opacity };
}
// packages/ag-charts-enterprise/src/series/funnel/baseFunnelSeries.ts
var {
SeriesNodePickMode: SeriesNodePickMode7,
valueProperty: valueProperty10,
keyProperty: keyProperty8,
updateLabelNode: updateLabelNode5,
SMALLEST_KEY_INTERVAL: SMALLEST_KEY_INTERVAL4,
LARGEST_KEY_INTERVAL: LARGEST_KEY_INTERVAL2,
diff: diff5,
fixNumericExtent: fixNumericExtent7,
seriesLabelFadeInAnimation: seriesLabelFadeInAnimation4,
resetMotion: resetMotion2,
resetLabelFn: resetLabelFn4,
animationValidation: animationValidation6,
computeBarFocusBounds: computeBarFocusBounds6,
Group: Group11,
Selection: Selection6,
PointerEvents: PointerEvents4,
motion: motion4,
checkCrisp: checkCrisp3,
createDatumId: createDatumId8
} = _ModuleSupport145;
var FunnelSeriesNodeEvent = class extends _ModuleSupport145.SeriesNodeEvent {
constructor(type, nativeEvent, datum, series) {
super(type, nativeEvent, datum, series);
this.xKey = series.properties.stageKey;
this.yKey = series.properties.valueKey;
}
};
var BaseFunnelSeries = class extends _ModuleSupport145.AbstractBarSeries {
constructor({
moduleCtx,
animationResetFns
}) {
super({
moduleCtx,
pickModes: [SeriesNodePickMode7.AXIS_ALIGNED, SeriesNodePickMode7.EXACT_SHAPE_MATCH],
propertyKeys: {
x: ["stageKey"],
y: ["valueKey"]
},
propertyNames: {
x: [],
y: []
},
categoryKey: "xValue",
datumSelectionGarbageCollection: false,
animationResetFns: {
datum: animationResetFns.datum,
label: resetLabelFn4
}
});
// @ts-expect-error xKey/yKey renamed
this.NodeEvent = FunnelSeriesNodeEvent;
this.connectorNodeGroup = this.contentGroup.appendChild(
new Group11({
name: `${this.id}-series-connectorNodes`,
zIndex: SeriesZIndexMap.BACKGROUND
})
);
this.connectorSelection = Selection6.select(
this.connectorNodeGroup,
() => this.connectionFactory()
);
this.connectorNodeGroup.pointerEvents = PointerEvents4.None;
}
get pickModeAxis() {
return "main-category";
}
setZIndex(zIndex) {
super.setZIndex(zIndex);
this.connectorNodeGroup.zIndex = [SeriesZIndexMap.BACKGROUND, zIndex];
return true;
}
isVertical() {
return !super.isVertical();
}
connectionFactory() {
return new FunnelConnector();
}
getKeyAxis(direction) {
if (direction === ChartAxisDirection41.X)
return this.properties.xKeyAxis;
if (direction === ChartAxisDirection41.Y)
return this.properties.yKeyAxis;
}
async processData(dataController) {
const { stageKey, valueKey } = this.properties;
const { visible, id: seriesId } = this;
const validation = (_value, _datum, index) => visible && this.ctx.legendManager.getItemEnabled({ seriesId, itemId: index });
const xScale = this.getCategoryAxis()?.scale;
const yScale = this.getValueAxis()?.scale;
const { isContinuousX, xScaleType, yScaleType } = this.getScaleInformation({ xScale, yScale });
const extraProps = [];
if (this.needsDataModelDiff() && this.processedData) {
extraProps.push(diff5(this.id, this.processedData));
}
if (!this.ctx.animationManager.isSkipped()) {
extraProps.push(animationValidation6());
}
const visibleProps = this.visible ? {} : { forceValue: 0 };
const allowNullKey = this.properties.allowNullKeys ?? false;
const { processedData } = await this.requestDataModel(dataController, this.data, {
props: [
keyProperty8(stageKey, xScaleType, { id: "xValue", allowNullKey }),
valueProperty10(valueKey, yScaleType, { id: `yValue`, ...visibleProps, validation, invalidValue: 0 }),
...isContinuousX ? [SMALLEST_KEY_INTERVAL4, LARGEST_KEY_INTERVAL2] : [],
...extraProps
],
groupByKeys: false
});
this.smallestDataInterval = processedData.reduced?.smallestKeyInterval;
this.largestDataInterval = processedData.reduced?.largestKeyInterval;
this.animationState.transition("updateData");
}
getSeriesDomain(direction) {
const {
processedData,
dataModel,
id: seriesId,
ctx: { legendManager }
} = this;
if (!processedData || !dataModel)
return { domain: [] };
const {
keys: [keys]
} = processedData.domain;
if (direction === this.getCategoryDirection()) {
const keyDef = dataModel.resolveProcessedDataDefById(this, `xValue`);
if (keyDef?.def.type === "key" && keyDef?.def.valueType === "category") {
if (!this.hasData)
return { domain: [] };
const domain = keys.filter((_key, index) => legendManager.getItemEnabled({ seriesId, itemId: index }));
const sortMetadata = dataModel.getKeySortMetadata(this, "xValue", processedData);
return { domain, sortMetadata };
}
return { domain: this.padBandExtent(keys) };
} else {
const yExtent = this.domainForClippedRange(direction, ["yValue"], "xValue");
const maxExtent = Math.max(...yExtent);
const fixedYExtent = [-maxExtent, maxExtent];
return { domain: fixNumericExtent7(fixedYExtent) };
}
}
getSeriesRange(_direction, _visibleRange) {
return [Number.NaN, Number.NaN];
}
createNodeData() {
const {
hasData,
data,
dataModel,
processedData,
id: seriesId,
ctx: { legendManager }
} = this;
const xAxis = this.getCategoryAxis();
const yAxis = this.getValueAxis();
if (!(hasData && data && xAxis && yAxis && dataModel && processedData?.type === "ungrouped")) {
return;
}
const xScale = xAxis.scale;
const yScale = yAxis.scale;
const barAlongX = this.getBarDirection() === ChartAxisDirection41.X;
const { stageKey, valueKey } = this.properties;
const itemId = `${valueKey}`;
const context = {
itemId,
nodeData: [],
labelData: [],
connectorData: [],
scales: this.calculateScaling(),
groupScale: this.getScaling(this.ctx.seriesStateManager.getGroupScale(this)),
visible: this.visible
};
const isVisible = this.visible;
if (!isVisible)
return context;
const xValues = dataModel.resolveKeysById(this, "xValue", processedData);
const yValues = dataModel.resolveColumnById(this, `yValue`, processedData);
const { groupOffset, barOffset, barWidth } = this.getBarDimensions();
const crisp = checkCrisp3(
xAxis?.scale,
xAxis?.visibleRange,
this.smallestDataInterval,
this.largestDataInterval
);
let previousConnection;
const rawData = processedData.dataSources.get(this.id)?.data ?? [];
for (const [datumIndex, datum] of rawData.entries()) {
const visible = isVisible && legendManager.getItemEnabled({ seriesId, itemId: datumIndex });
const xDatum = xValues[datumIndex];
if (xDatum === void 0 && !this.properties.allowNullKeys)
continue;
const xConverted = xScale.convert(xDatum);
if (!Number.isFinite(xConverted))
continue;
const x = Math.round(xConverted) + groupOffset + barOffset;
const yDatum = yValues[datumIndex];
const yNegative = Math.round(yScale.convert(-yDatum));
const yPositive = Math.round(yScale.convert(yDatum));
const style = this.getItemStyle({ datum, datumIndex }, false);
const barHeight = Math.max(style.strokeWidth ?? 0, Math.abs(yPositive - yNegative));
const rect = {
x: barAlongX ? Math.min(yPositive, yNegative) : x,
y: barAlongX ? x : Math.min(yPositive, yNegative),
width: barAlongX ? barHeight : barWidth,
height: barAlongX ? barWidth : barHeight
};
const nodeMidPoint = {
x: rect.x + rect.width / 2,
y: rect.y + rect.height / 2
};
const labelData = this.createLabelData({
datumIndex,
rect,
barAlongX,
yDatum,
datum,
visible
});
const nodeDatum = {
index: datumIndex,
series: this,
datum,
datumIndex,
xValue: xDatum,
yValue: yDatum,
xKey: stageKey,
yKey: valueKey,
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
midPoint: nodeMidPoint,
crisp,
label: labelData,
visible
};
context.nodeData.push(nodeDatum);
if (labelData != null) {
context.labelData.push(labelData);
}
if (previousConnection != null) {
const prevRect = previousConnection.rect;
const startNodeDatum = previousConnection.nodeDatum;
const startDatumIndex = previousConnection.datumIndex;
if (barAlongX) {
context.connectorData.push({
datum: startNodeDatum,
datumIndex: startDatumIndex,
x0: prevRect.x,
y0: prevRect.y + prevRect.height,
x1: prevRect.x + prevRect.width,
y1: prevRect.y + prevRect.height,
x2: rect.x + rect.width,
y2: rect.y,
x3: rect.x,
y3: rect.y,
opacity: 1
});
} else {
context.connectorData.push({
datum: startNodeDatum,
datumIndex: startDatumIndex,
x0: prevRect.x + prevRect.width,
y0: prevRect.y,
x1: rect.x,
y1: rect.y,
x2: rect.x,
y2: rect.y + rect.height,
x3: prevRect.x + prevRect.width,
y3: prevRect.y + prevRect.height,
opacity: 1
});
}
}
if (visible) {
previousConnection = {
itemId,
rect,
nodeDatum,
datumIndex
};
}
}
return context;
}
updateNodes(seriesHighlighted, nodeRefresh) {
super.updateNodes(seriesHighlighted, nodeRefresh);
const { connectorSelection } = this;
const connectorData = this.contextNodeData?.connectorData ?? [];
this.connectorSelection = this.updateConnectorSelection({ connectorSelection, connectorData });
this.updateConnectorNodes({ connectorSelection });
}
updateDatumSelection(opts) {
const { nodeData, datumSelection } = opts;
const data = nodeData ?? [];
return datumSelection.update(data, void 0, (datum) => this.getDatumId(datum));
}
updateConnectorSelection(opts) {
const { connectorData, connectorSelection } = opts;
return connectorSelection.update(
this.connectorEnabled() ? connectorData : [],
void 0,
(connector) => this.getDatumId(connector.datum)
);
}
updateConnectorNodes(opts) {
const fillBBox = this.getShapeFillBBox();
opts.connectorSelection.each((connector, datum) => {
const { fill, fillOpacity, stroke: stroke3, strokeOpacity, strokeWidth, lineDash, lineDashOffset } = this.connectorStyle(datum.datumIndex);
connector.setProperties(resetConnectorSelectionsFn(connector, datum));
connector.setStyleProperties(
{
fill,
stroke: stroke3,
fillOpacity,
strokeOpacity,
strokeWidth,
lineDash,
lineDashOffset
},
fillBBox
);
});
}
updateLabelSelection(opts) {
const labelData = this.properties.label.enabled ? opts.labelData : [];
return opts.labelSelection.update(labelData, (text2) => {
text2.pointerEvents = PointerEvents4.None;
});
}
updateLabelNodes(opts) {
const params = {
stageKey: this.properties.stageKey,
valueKey: this.properties.valueKey
};
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const { isHighlight = false, labelSelection } = opts;
labelSelection.each((textNode, datum) => {
const highlightStyle = this.getHighlightStyle(isHighlight, datum.datumIndex);
textNode.visible = datum.visible || isHighlight;
textNode.fillOpacity = highlightStyle.opacity ?? 1;
textNode.opacity = highlightStyle.opacity ?? 1;
updateLabelNode5(this, textNode, params, this.properties.label, datum, isHighlight, activeHighlight);
});
}
getHighlightLabelData(_labelData, highlightedItem) {
if (highlightedItem.label) {
return [{ ...highlightedItem.label }];
}
return void 0;
}
getTooltipContent(datumIndex) {
const { id: seriesId, dataModel, processedData, properties } = this;
const { stageKey, valueKey, tooltip, legendItemName } = properties;
const xAxis = this.getCategoryAxis();
const yAxis = this.getValueAxis();
if (!dataModel || !processedData || !xAxis || !yAxis)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const xValue = dataModel.resolveKeysById(this, "xValue", processedData)[datumIndex];
const yValue = dataModel.resolveColumnById(this, `yValue`, processedData)[datumIndex];
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (xValue === void 0 && !allowNullKeys)
return;
return this.formatTooltipWithContext(
tooltip,
{
symbol: this.legendItemSymbol(datumIndex),
data: [
{
label: this.getAxisValueText(xAxis, "tooltip", xValue, datum, stageKey, legendItemName),
value: this.getAxisValueText(yAxis, "tooltip", yValue, datum, valueKey, legendItemName)
}
]
},
{ seriesId, datum, title: stageKey, stageKey, valueKey, ...this.tooltipStyle(datum, datumIndex) }
);
}
resetAllAnimation(data) {
super.resetAllAnimation(data);
resetMotion2([this.connectorSelection], resetConnectorSelectionsFn);
}
animateEmptyUpdateReady({ labelSelection }) {
const { connectorSelection } = this;
const isVertical = this.isVertical();
const mode = "normal";
const connectorFns = prepareConnectorAnimationFunctions(isVertical, mode);
motion4.fromToMotion(this.id, "connectors", this.ctx.animationManager, [connectorSelection], connectorFns);
seriesLabelFadeInAnimation4(this, "labels", this.ctx.animationManager, labelSelection);
}
animateWaitingUpdateReady(data) {
const { labelSelection: labelSelections } = data;
this.ctx.animationManager.stopByAnimationGroupId(this.id);
seriesLabelFadeInAnimation4(this, "labels", this.ctx.animationManager, labelSelections);
}
getDatumId(datum) {
return createDatumId8(datum.xValue);
}
isLabelEnabled() {
return this.properties.label.enabled;
}
computeFocusBounds({ datumIndex }) {
return computeBarFocusBounds6(this, this.contextNodeData?.nodeData[datumIndex]);
}
legendItemSymbol(datumIndex) {
const { strokeWidth, fillOpacity, strokeOpacity, lineDash, lineDashOffset, fill, stroke: stroke3 } = this.properties.getStyle(datumIndex);
return {
marker: {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
}
};
}
getLegendData(legendType) {
const {
id: seriesId,
processedData,
dataModel,
ctx: { legendManager },
visible
} = this;
if (!dataModel || !processedData || legendType !== "category") {
return [];
}
const { showInLegend } = this.properties;
const xValues = dataModel.resolveKeysById(this, "xValue", processedData);
return (processedData.dataSources.get(this.id)?.data ?? []).map((datum, datumIndex) => {
const stageValue = xValues[datumIndex];
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (stageValue == null && !allowNullKeys)
return;
return {
legendType: "category",
id: seriesId,
datum,
itemId: datumIndex,
seriesId,
enabled: visible && legendManager.getItemEnabled({ seriesId, itemId: datumIndex }),
label: { text: String(stageValue) },
symbol: this.legendItemSymbol(datumIndex),
skipAnimations: true,
hideInLegend: !showInLegend
};
}).filter((datum) => datum != null);
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.label.itemStyler != null;
}
};
// packages/ag-charts-enterprise/src/series/cone-funnel/coneFunnelProperties.ts
import { _ModuleSupport as _ModuleSupport146 } from "ag-charts-community";
import { Property as Property70 } from "ag-charts-core";
var { Label: Label7, AbstractBarSeriesProperties: AbstractBarSeriesProperties5, makeSeriesTooltip: makeSeriesTooltip9, AxisLabel: AxisLabel3 } = _ModuleSupport146;
var ConeFunnelSeriesLabel = class extends Label7 {
constructor() {
super(...arguments);
this.spacing = 0;
}
};
__decorateClass([
Property70
], ConeFunnelSeriesLabel.prototype, "placement", 2);
__decorateClass([
Property70
], ConeFunnelSeriesLabel.prototype, "spacing", 2);
var ConeFunnelSeriesStageLabel = class extends AxisLabel3 {
};
__decorateClass([
Property70
], ConeFunnelSeriesStageLabel.prototype, "placement", 2);
var ConeFunnelProperties = class extends AbstractBarSeriesProperties5 {
constructor() {
super(...arguments);
this.fills = [];
this.fillOpacity = 1;
this.strokes = [];
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.label = new ConeFunnelSeriesLabel();
this.stageLabel = new ConeFunnelSeriesStageLabel();
this.tooltip = makeSeriesTooltip9();
}
getStyle(index) {
const { fills, strokes, fillOpacity, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = this;
return {
fill: fills[index],
fillOpacity,
stroke: strokes[index],
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
opacity: 1
};
}
};
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "stageKey", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "valueKey", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "fills", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "strokes", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "lineDash", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "label", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "stageLabel", 2);
__decorateClass([
Property70
], ConeFunnelProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/cone-funnel/coneFunnelUtil.ts
function resetLineSelectionsFn(_node, { x, y, width, height, opacity }) {
return { x1: x, y1: y, x2: x + width, y2: y + height, opacity: opacity ?? 1 };
}
// packages/ag-charts-enterprise/src/series/cone-funnel/coneFunnelSeries.ts
var { Line: Line5 } = _ModuleSupport147;
var ConeFunnelSeries = class extends BaseFunnelSeries {
constructor(moduleCtx) {
super({
moduleCtx,
animationResetFns: {
datum: resetLineSelectionsFn
}
});
this.properties = new ConeFunnelProperties();
}
get hasData() {
const {
id: seriesId,
ctx: { legendManager }
} = this;
const visibleItems = this.data?.data.reduce(
(accum, _, datumIndex) => accum + (legendManager.getItemEnabled({ seriesId, itemId: datumIndex }) ? 1 : 0),
0
);
return visibleItems != null && visibleItems > 1;
}
getBandScalePadding() {
return { inner: 1, outer: 0 };
}
connectorEnabled() {
return true;
}
getItemStyle({ datumIndex }, _isHighlight) {
return this.properties.getStyle(datumIndex);
}
connectorStyle(index) {
return this.properties.getStyle(index);
}
nodeFactory() {
return new Line5();
}
createLabelData({
datumIndex,
rect,
barAlongX,
yDatum,
datum,
visible
}) {
const { stageKey, valueKey, label } = this.properties;
const { spacing, placement } = label;
if (!label.enabled)
return;
let x;
let y;
let textAlign;
let textBaseline;
if (barAlongX) {
x = rect.x + rect.width / 2;
textAlign = "center";
switch (placement) {
case "before":
y = rect.y - spacing;
textBaseline = "bottom";
break;
case "after":
y = rect.y + rect.height + spacing;
textBaseline = "top";
break;
default:
y = rect.y + rect.height / 2;
textBaseline = "middle";
}
} else {
y = rect.y + rect.height / 2;
textBaseline = "middle";
switch (placement) {
case "before":
x = rect.x - spacing;
textAlign = "right";
break;
case "after":
x = rect.x + rect.width + spacing;
textAlign = "left";
break;
default:
x = rect.x + rect.width / 2;
textAlign = "center";
}
}
const yDomain = this.getSeriesDomain(ChartAxisDirection42.Y).domain;
const text2 = this.getLabelText(
yDatum,
datum,
valueKey,
"y",
yDomain,
label,
{ itemId: valueKey, value: yDatum, datum, stageKey, valueKey }
);
return {
x,
y,
textAlign,
textBaseline,
text: text2,
itemId: valueKey,
datum,
datumIndex,
series: this,
visible
};
}
updateDatumNodes(opts) {
const highlightStyle = this.getHighlightStyle(opts.isHighlight);
opts.datumSelection.each((line, datum) => {
line.setProperties(resetLineSelectionsFn(line, datum));
line.stroke = highlightStyle?.stroke;
line.strokeWidth = highlightStyle?.strokeWidth ?? 0;
line.strokeOpacity = highlightStyle?.strokeOpacity ?? 1;
line.lineDash = highlightStyle?.lineDash;
line.lineDashOffset = highlightStyle?.lineDashOffset ?? 0;
line.opacity = highlightStyle?.opacity ?? 1;
});
}
tooltipStyle(_datum, datumIndex) {
const { fill, stroke: stroke3, fillOpacity, strokeOpacity, strokeWidth, lineDash, lineDashOffset } = this.properties.getStyle(datumIndex);
return {
fill,
fillOpacity,
stroke: stroke3,
strokeOpacity,
strokeWidth,
lineDash,
lineDashOffset
};
}
hasItemStylers() {
return this.properties.label.itemStyler != null;
}
};
ConeFunnelSeries.className = "ConeFunnelSeries";
ConeFunnelSeries.type = "cone-funnel";
// packages/ag-charts-enterprise/src/series/cone-funnel/coneFunnelSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport148 } from "ag-charts-community";
import { commonSeriesOptionsDefs as commonSeriesOptionsDefs9, constant as constant9, required as required9, string as string11, without as without3 } from "ag-charts-core";
var { coneFunnelSeriesThemeableOptionsDef } = _ModuleSupport148;
var coneFunnelSeriesOptionsDef = {
...without3(commonSeriesOptionsDefs9, ["showInLegend"]),
...coneFunnelSeriesThemeableOptionsDef,
type: required9(constant9("cone-funnel")),
stageKey: required9(string11),
valueKey: required9(string11)
};
// packages/ag-charts-enterprise/src/series/cone-funnel/coneFunnelThemes.ts
import {
CARTESIAN_AXIS_TYPE as CARTESIAN_AXIS_TYPE10,
FILL_GRADIENT_LINEAR_SINGLE_DEFAULTS as FILL_GRADIENT_LINEAR_SINGLE_DEFAULTS2,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS8,
FILL_PATTERN_SINGLE_DEFAULTS as FILL_PATTERN_SINGLE_DEFAULTS2,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS7,
SAFE_RANGE2_OPERATION as SAFE_RANGE2_OPERATION2
} from "ag-charts-core";
var CONE_FUNNEL_SERIES_THEME = {
series: {
direction: "vertical",
fills: {
$applyCycle: [
{ $size: { $path: ["./data", { $path: "/data" }] } },
{
$if: [
{ $eq: [{ $palette: "type" }, "inbuilt"] },
{ $palette: "secondSequentialColors" },
SAFE_RANGE2_OPERATION2
]
},
{
$applySwitch: [
{ $path: ["/type", void 0, { $value: "$1" }] },
{ $value: "$1" },
["gradient", FILL_GRADIENT_LINEAR_SINGLE_DEFAULTS2],
["pattern", FILL_PATTERN_SINGLE_DEFAULTS2],
["image", FILL_IMAGE_DEFAULTS8]
]
}
]
},
strokes: {
$applyCycle: [
{ $size: { $path: ["./data", { $path: "/data" }] } },
{
$if: [
{ $eq: [{ $palette: "type" }, "inbuilt"] },
{ $palette: "secondSequentialColors" },
SAFE_RANGE2_OPERATION2
]
}
]
},
strokeWidth: { $isUserOption: ["./strokes/0", 2, 0] },
label: {
...LABEL_BOXING_DEFAULTS7,
enabled: true,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "textColor" },
placement: "before",
spacing: 4
},
tooltip: {
range: { $path: ["/tooltip/range", "nearest"] }
},
highlight: {
highlightedItem: {
stroke: `rgba(0, 0, 0, 0.4)`,
strokeWidth: 2
}
}
},
seriesArea: {
padding: {
top: 20,
bottom: 20
}
},
axes: {
[CARTESIAN_AXIS_TYPE10.NUMBER]: {
nice: false,
gridLine: {
enabled: false
},
crosshair: {
enabled: false
},
label: {
enabled: false
}
},
[CARTESIAN_AXIS_TYPE10.CATEGORY]: {
line: {
enabled: false
}
}
}
};
// packages/ag-charts-enterprise/src/series/cone-funnel/coneFunnelModule.ts
var ConeFunnelSeriesModule = {
type: "series",
name: "cone-funnel",
chartType: "cartesian",
enterprise: true,
solo: true,
version: VERSION31,
dependencies: [CartesianChartModule8],
options: coneFunnelSeriesOptionsDef,
defaultAxes: FUNNEL_SERIES_AXES,
themeTemplate: CONE_FUNNEL_SERIES_THEME,
create: (ctx) => new ConeFunnelSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/funnel/funnelModule.ts
import { CartesianChartModule as CartesianChartModule9, VERSION as VERSION32 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/series/funnel/funnelSeries.ts
import {
_ModuleSupport as _ModuleSupport150
} from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection43, mergeDefaults as mergeDefaults11 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/funnel/funnelProperties.ts
import { _ModuleSupport as _ModuleSupport149 } from "ag-charts-community";
import { BaseProperties as BaseProperties31, Property as Property71 } from "ag-charts-core";
var { Label: Label8, DropShadow: DropShadow4, AbstractBarSeriesProperties: AbstractBarSeriesProperties6, makeSeriesTooltip: makeSeriesTooltip10, AxisLabel: AxisLabel4 } = _ModuleSupport149;
var FunnelSeriesLabel = class extends Label8 {
};
var FunnelSeriesStageLabel = class extends AxisLabel4 {
};
__decorateClass([
Property71
], FunnelSeriesStageLabel.prototype, "placement", 2);
var FunnelDropOff = class extends BaseProperties31 {
constructor() {
super(...arguments);
this.enabled = true;
this.fill = void 0;
this.fillOpacity = 1;
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
}
getStyle() {
const { fill, stroke: stroke3, fillOpacity, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = this;
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
opacity: 1
};
}
};
__decorateClass([
Property71
], FunnelDropOff.prototype, "enabled", 2);
__decorateClass([
Property71
], FunnelDropOff.prototype, "fill", 2);
__decorateClass([
Property71
], FunnelDropOff.prototype, "fillOpacity", 2);
__decorateClass([
Property71
], FunnelDropOff.prototype, "stroke", 2);
__decorateClass([
Property71
], FunnelDropOff.prototype, "strokeWidth", 2);
__decorateClass([
Property71
], FunnelDropOff.prototype, "strokeOpacity", 2);
__decorateClass([
Property71
], FunnelDropOff.prototype, "lineDash", 2);
__decorateClass([
Property71
], FunnelDropOff.prototype, "lineDashOffset", 2);
var FunnelProperties = class extends AbstractBarSeriesProperties6 {
constructor() {
super(...arguments);
this.fills = [];
this.fillOpacity = 1;
this.strokes = [];
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.spacingRatio = 0;
this.dropOff = new FunnelDropOff();
this.shadow = new DropShadow4().set({ enabled: false });
this.label = new FunnelSeriesLabel();
this.stageLabel = new FunnelSeriesStageLabel();
this.tooltip = makeSeriesTooltip10();
}
getStyle(index) {
const { fills, strokes, fillOpacity, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = this;
return {
fill: fills[index],
fillOpacity,
stroke: strokes[index],
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
opacity: 1
};
}
};
__decorateClass([
Property71
], FunnelProperties.prototype, "stageKey", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "valueKey", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "fills", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "strokes", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "lineDash", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "spacingRatio", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "itemStyler", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "dropOff", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "shadow", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "label", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "stageLabel", 2);
__decorateClass([
Property71
], FunnelProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/funnel/funnelSeries.ts
var { resetBarSelectionsFn: resetBarSelectionsFn3, prepareBarAnimationFunctions: prepareBarAnimationFunctions3, midpointStartingBarPosition: midpointStartingBarPosition2, createDatumId: createDatumId9, Rect: Rect7, motion: motion5 } = _ModuleSupport150;
var FunnelSeries = class extends BaseFunnelSeries {
constructor(moduleCtx) {
super({
moduleCtx,
animationResetFns: {
datum: resetBarSelectionsFn3
}
});
this.properties = new FunnelProperties();
}
getBandScalePadding() {
return { inner: this.properties.spacingRatio, outer: 0 };
}
connectorEnabled() {
return this.properties.dropOff.enabled;
}
connectorStyle(index) {
return mergeDefaults11(this.properties.dropOff.getStyle(), this.properties.getStyle(index));
}
nodeFactory() {
return new Rect7();
}
createLabelData({
datumIndex,
rect,
yDatum,
datum,
visible
}) {
const { valueKey, stageKey, label } = this.properties;
if (!label.enabled)
return;
const yDomain = this.getSeriesDomain(ChartAxisDirection43.Y).domain;
const text2 = this.getLabelText(
yDatum,
datum,
valueKey,
"y",
yDomain,
label,
{ itemId: valueKey, value: yDatum, datum, stageKey, valueKey }
);
return {
x: rect.x + rect.width / 2,
y: rect.y + rect.height / 2,
textAlign: "center",
textBaseline: "middle",
text: text2,
itemId: stageKey,
datum,
datumIndex,
series: this,
visible
};
}
getItemStyle({ datum, datumIndex }, isHighlight) {
const { id: seriesId, properties } = this;
const { stageKey, valueKey, itemStyler } = properties;
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
const baseStyle = mergeDefaults11(highlightStyle, properties.getStyle(datumIndex));
let style = baseStyle;
if (itemStyler != null) {
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const overrides = this.cachedDatumCallback(
createDatumId9(datumIndex, isHighlight ? "highlight" : "node"),
() => {
const highlightStateString = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
return this.callWithContext(itemStyler, {
seriesId,
datum,
highlightState: highlightStateString,
stageKey,
valueKey,
...style
});
}
);
if (overrides) {
style = mergeDefaults11(overrides, style);
}
}
return style;
}
updateDatumNodes({
datumSelection,
isHighlight
}) {
const { contextNodeData } = this;
if (!contextNodeData) {
return;
}
const { shadow } = this.properties;
const categoryAlongX = this.getCategoryDirection() === ChartAxisDirection43.X;
const fillBBox = this.getShapeFillBBox();
datumSelection.each((rect, datum) => {
const style = this.getItemStyle(datum, isHighlight);
rect.setStyleProperties(style, fillBBox);
rect.visible = categoryAlongX ? datum.width > 0 : datum.height > 0;
rect.crisp = datum.crisp;
rect.fillShadow = shadow;
});
}
tooltipStyle(datum, datumIndex) {
return this.getItemStyle({ datum, datumIndex }, false);
}
animateEmptyUpdateReady(params) {
super.animateEmptyUpdateReady(params);
const { datumSelection } = params;
const isVertical = this.isVertical();
const mode = "normal";
const barFns = prepareBarAnimationFunctions3(midpointStartingBarPosition2(isVertical, mode), "unknown");
motion5.fromToMotion(this.id, "datums", this.ctx.animationManager, [datumSelection], barFns);
}
animateWaitingUpdateReady(data) {
super.animateWaitingUpdateReady(data);
const { datumSelection: datumSelections } = data;
const { processedData } = this;
const dataDiff = processedData?.reduced?.diff?.[this.id];
const fns = prepareBarAnimationFunctions3(midpointStartingBarPosition2(this.isVertical(), "fade"), "added");
motion5.fromToMotion(
this.id,
"datums",
this.ctx.animationManager,
[datumSelections],
fns,
(_, datum) => datum.xValue,
dataDiff
);
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.label.itemStyler != null;
}
};
FunnelSeries.className = "FunnelSeries";
FunnelSeries.type = "funnel";
// packages/ag-charts-enterprise/src/series/funnel/funnelSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport151 } from "ag-charts-community";
import { commonSeriesOptionsDefs as commonSeriesOptionsDefs10, constant as constant10, required as required10, string as string12, without as without4 } from "ag-charts-core";
var { funnelSeriesThemeableOptionsDef } = _ModuleSupport151;
var funnelSeriesOptionsDef = {
...funnelSeriesThemeableOptionsDef,
...without4(commonSeriesOptionsDefs10, ["showInLegend"]),
type: required10(constant10("funnel")),
stageKey: required10(string12),
valueKey: required10(string12)
};
// packages/ag-charts-enterprise/src/series/funnel/funnelModule.ts
var FunnelSeriesModule = {
type: "series",
name: "funnel",
chartType: "cartesian",
enterprise: true,
solo: true,
version: VERSION32,
dependencies: [CartesianChartModule9],
options: funnelSeriesOptionsDef,
defaultAxes: FUNNEL_SERIES_AXES,
themeTemplate: FUNNEL_SERIES_THEME,
create: (ctx) => new FunnelSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/linear-gauge/linearGaugeModule.ts
import { VERSION as VERSION34 } from "ag-charts-community";
import {
FONT_SIZE as FONT_SIZE2,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS8,
SAFE_RANGE2_OPERATION as SAFE_RANGE2_OPERATION3,
SAFE_STROKE_FILL_OPERATION,
linearGaugeSeriesOptionsDef as linearGaugeSeriesOptionsDef2
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/preset/gaugePresetModule.ts
import { VERSION as VERSION33 } from "ag-charts-community";
import {
commonChartOptionsDefs,
defined,
linearGaugeSeriesOptionsDef,
positiveNumber as positiveNumber9,
radialGaugeSeriesOptionsDef,
tooltipOptionsDefs,
typeUnion as typeUnion2,
undocumented as undocumented10,
without as without5
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/preset/gaugePreset.ts
import { mergeArrayDefaults, mergeDefaults as mergeDefaults12 } from "ag-charts-core";
function tooltipOptions(opts) {
const { enabled, mode, showArrow, range: range2, position, pagination, delay, wrapping, interaction, renderer, ...rest } = opts;
const seriesTooltipOptions = {
enabled,
showArrow,
range: range2,
position,
interaction,
renderer,
...rest
};
const chartTooltipOptions = {
mode,
pagination,
delay,
wrapping,
...rest
};
return { chartTooltipOptions, seriesTooltipOptions };
}
function radialGaugeOptions(opts) {
const {
animation,
background,
container,
contextMenu,
context,
footnote,
foreground,
height,
listeners,
locale,
minHeight,
minWidth,
overrideDevicePixelRatio,
padding: padding2,
subtitle,
theme,
title,
width,
type,
cursor,
nodeClickRange,
tooltip: tooltipInput,
value,
scale = {},
startAngle,
endAngle,
highlight,
segmentation,
bar,
needle,
targets,
outerRadius,
innerRadius,
outerRadiusRatio,
innerRadiusRatio,
cornerRadius,
cornerMode,
label,
secondaryLabel,
spacing,
...seriesRest
} = opts;
const hasTooltip = tooltipInput != null;
const tooltip = tooltipInput ?? {};
const { chartTooltipOptions, seriesTooltipOptions } = tooltipOptions(tooltip);
const seriesOpts = {
...seriesRest,
type,
cursor,
context,
nodeClickRange,
value,
scale,
startAngle,
endAngle,
highlight,
segmentation,
bar,
targets,
outerRadius,
innerRadius,
outerRadiusRatio,
innerRadiusRatio,
cornerRadius,
cornerMode,
label,
secondaryLabel,
spacing
};
if (hasTooltip) {
seriesOpts.tooltip = seriesTooltipOptions;
}
if (needle != null) {
seriesOpts.needle = { enabled: true, ...needle };
}
return {
animation,
background,
container,
contextMenu,
context,
footnote,
foreground,
height,
listeners,
locale,
minHeight,
minWidth,
overrideDevicePixelRatio,
padding: padding2,
subtitle,
theme,
title,
width,
...hasTooltip ? { tooltip: chartTooltipOptions } : {},
series: [seriesOpts]
};
}
function linearGaugeOptions(opts) {
const {
animation,
background,
container,
contextMenu,
context,
footnote,
foreground,
height,
listeners,
locale,
minHeight,
minWidth,
overrideDevicePixelRatio,
padding: padding2,
subtitle,
theme,
title,
width,
type,
cursor,
nodeClickRange,
tooltip: tooltipInput,
value,
scale = {},
direction = "vertical",
thickness,
highlight,
segmentation,
bar,
targets,
cornerRadius,
cornerMode,
label,
...seriesRest
} = opts;
const hasTooltip = tooltipInput != null;
const tooltip = tooltipInput ?? {};
const { chartTooltipOptions, seriesTooltipOptions } = tooltipOptions(tooltip);
const seriesOpts = {
...seriesRest,
type,
cursor,
nodeClickRange,
value,
scale,
direction,
thickness,
highlight,
segmentation,
bar,
targets,
cornerRadius,
cornerMode,
label
};
if (hasTooltip) {
seriesOpts.tooltip = seriesTooltipOptions;
}
return {
animation,
background,
container,
contextMenu,
context,
footnote,
foreground,
height,
listeners,
locale,
minHeight,
minWidth,
overrideDevicePixelRatio,
padding: padding2,
subtitle,
theme,
title,
width,
...hasTooltip ? { tooltip: chartTooltipOptions } : {},
series: [seriesOpts]
};
}
function applyThemeDefaults(opts, presetTheme) {
if (presetTheme == null)
return opts;
const { targets: targetsTheme, ...gaugeTheme } = presetTheme;
opts = mergeDefaults12(opts, gaugeTheme);
if (opts.targets != null && targetsTheme != null) {
if (opts.type === "radial-gauge") {
opts.targets = mergeArrayDefaults(opts.targets, targetsTheme);
} else {
opts.targets = mergeArrayDefaults(opts.targets, targetsTheme);
}
}
return opts;
}
function createGauge(opts, presetTheme) {
switch (opts.type) {
case "radial-gauge":
return radialGaugeOptions(applyThemeDefaults(opts, presetTheme));
case "linear-gauge":
return linearGaugeOptions(applyThemeDefaults(opts, presetTheme));
default:
return { series: [] };
}
}
// packages/ag-charts-enterprise/src/preset/gaugePresetModule.ts
var commonGaugeOptions = {
// Valid pass-through options
theme: defined,
container: defined,
animation: defined,
background: defined,
contextMenu: defined,
context: () => true,
listeners: defined,
locale: defined,
width: defined,
height: defined,
minWidth: defined,
minHeight: defined,
title: defined,
subtitle: defined,
footnote: defined,
padding: defined,
tooltip: {
...tooltipOptionsDefs,
...commonChartOptionsDefs.tooltip
}
};
commonGaugeOptions.overrideDevicePixelRatio = undocumented10(positiveNumber9);
commonGaugeOptions.foreground = undocumented10(defined);
var GaugePresetModule = {
type: "preset",
name: "gauge-preset",
enterprise: true,
version: VERSION33,
dependencies: [StandaloneChartModule],
options: typeUnion2(
{
"linear-gauge": {
...without5(linearGaugeSeriesOptionsDef, ["type"]),
...commonGaugeOptions
},
"radial-gauge": {
...without5(radialGaugeSeriesOptionsDef, ["type"]),
...commonGaugeOptions
}
},
"gauge options"
),
create: createGauge
};
// packages/ag-charts-enterprise/src/series/linear-gauge/linearGaugeSeries.ts
import {
_ModuleSupport as _ModuleSupport155
} from "ag-charts-community";
import {
StateMachine as StateMachine12,
cachedTextMeasurer as cachedTextMeasurer7,
easeOut as easeOut2,
findRangeExtent as findRangeExtent2,
isArray as isArray4,
measureTextSegments as measureTextSegments3,
mergeDefaults as mergeDefaults13,
tickFormat,
toRadians as toRadians4,
toTextString as toTextString3
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/gauge-util/datumUnion.ts
var DatumUnion = class {
*[Symbol.iterator]() {
const { node, datum } = this;
if (node && datum)
yield { node, datum };
}
nodes() {
return this.node ? [this.node] : [];
}
update(datumSelection, group, ctor, nodeUpdater) {
const nodes = datumSelection.nodes();
if (nodes.length === 0) {
this.node?.remove();
this.node = void 0;
} else {
if (this.node === void 0) {
this.node = new ctor();
this.node.fillOpacity = 0;
this.node.strokeOpacity = 0;
group.appendChild(this.node);
}
const first = nodes[0];
const last = nodes.toReversed().find((n) => n.datum.datum.value > n.datum.datum.segmentStart) ?? nodes.at(-1);
this.node.datum = this.datum = first.datum;
nodeUpdater(this.node, first, last);
}
}
};
// packages/ag-charts-enterprise/src/series/gauge-util/label.ts
import { isArray as isArray2 } from "ag-charts-core";
var fadeInFns = {
fromFn: () => ({ opacity: 0, phase: "initial" }),
toFn: () => ({ opacity: 1 })
};
function formatLabel(value, scale) {
if (value == null)
return "";
const { min, max } = scale;
const minLog10 = min === 0 ? 0 : Math.ceil(Math.log10(Math.abs(min)));
const maxLog10 = max === 0 ? 0 : Math.ceil(Math.log10(Math.abs(max)));
const dp = Math.max(2 - Math.max(minLog10, maxLog10), 0);
return value.toFixed(dp);
}
function getLabelText(seriesId, ctx, datum, valueOverride) {
if (datum.text != null)
return datum.text;
const value = valueOverride ?? datum.value;
let labelFormat;
if (datum?.formatter != null) {
labelFormat = formatWithContext(ctx, datum.formatter, { seriesId, datum: void 0, value });
}
return labelFormat == null || isArray2(labelFormat) ? labelFormat : String(labelFormat);
}
// packages/ag-charts-enterprise/src/series/gauge-util/lineMarker.ts
function lineMarker({ path, x, y, size }) {
path.moveTo(x, y - size / 2);
path.lineTo(x, y + size / 2);
}
// packages/ag-charts-enterprise/src/series/gauge-util/pick.ts
import { _ModuleSupport as _ModuleSupport152 } from "ag-charts-community";
import { clamp as clamp12, iterate } from "ag-charts-core";
function pickGaugeNearestDatum(self, point) {
const it = iterate(self.datumUnion.nodes(), self.targetSelection.nodes());
return self.pickNodeNearestDistantObject(point, it);
}
function pickGaugeFocus(self, opts) {
const others = [
{ data: self.contextNodeData?.nodeData, selection: self.datumUnion },
{ data: self.contextNodeData?.targetData, selection: self.targetSelection }
].filter((v) => v.data && v.data.length > 0);
const otherIndex = clamp12(0, opts.otherIndex + opts.otherIndexDelta, others.length - 1);
if (others.length === 0)
return;
const { data, selection } = others[otherIndex];
if (data == null || data.length === 0)
return;
const datumIndex = clamp12(0, opts.datumIndex, data.length - 1);
const datum = data[datumIndex];
for (const node of selection) {
if (node.datum === datum) {
const bounds = node.node;
return { bounds, clipFocusBox: true, datum, datumIndex, otherIndex };
}
}
}
function findGaugeNodeDatum(self, itemId) {
return _ModuleSupport152.findNodeDatumInArray(itemId, self.contextNodeData?.nodeData) ?? _ModuleSupport152.findNodeDatumInArray(itemId, self.contextNodeData?.targetData);
}
// packages/ag-charts-enterprise/src/series/linear-gauge/linearGaugeSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport153 } from "ag-charts-community";
import { BaseProperties as BaseProperties33, PropertiesArray as PropertiesArray7, Property as Property73 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/gauge-util/segmentation.ts
import { BaseProperties as BaseProperties32, Logger as Logger16, Property as Property72 } from "ag-charts-core";
var GaugeSegmentationIntervalProperties = class extends BaseProperties32 {
getSegments(scale, maxTicks) {
const { values, step, count } = this;
const d0 = Math.min(...scale.domain);
const d1 = Math.max(...scale.domain);
let ticks;
if (values != null) {
const segments = values.filter((v) => v > d0 && v < d1).sort((a, b) => a - b);
ticks = [d0, ...segments, d1];
} else if (step != null) {
const segments = [];
for (let i = d0; i < d1; i += step) {
segments.push(i);
}
segments.push(d1);
ticks = segments;
} else if (count == null) {
const segments = scale.ticks({
nice: [true, true],
interval: void 0,
tickCount: void 0,
minTickCount: 0,
maxTickCount: Infinity
})?.ticks?.filter((v) => v > d0 && v < d1);
ticks = segments == null ? void 0 : [d0, ...segments, d1];
} else {
const segments = count + 1;
ticks = Array.from({ length: segments + 1 }, (_, i) => i / segments * (d1 - d0) + d0);
}
if (ticks != null && ticks.length > maxTicks) {
Logger16.warnOnce(
`the configured segmentation results in more than 1 item per pixel, ignoring. Supply a segmentation configuration that results in larger segments or omit this configuration`
);
ticks = void 0;
}
ticks ?? (ticks = [d0, d1]);
return ticks;
}
};
__decorateClass([
Property72
], GaugeSegmentationIntervalProperties.prototype, "values", 2);
__decorateClass([
Property72
], GaugeSegmentationIntervalProperties.prototype, "step", 2);
__decorateClass([
Property72
], GaugeSegmentationIntervalProperties.prototype, "count", 2);
var GaugeSegmentationProperties = class extends BaseProperties32 {
constructor() {
super(...arguments);
this.enabled = false;
this.interval = new GaugeSegmentationIntervalProperties();
this.spacing = 0;
}
};
__decorateClass([
Property72
], GaugeSegmentationProperties.prototype, "enabled", 2);
__decorateClass([
Property72
], GaugeSegmentationProperties.prototype, "interval", 2);
__decorateClass([
Property72
], GaugeSegmentationProperties.prototype, "spacing", 2);
// packages/ag-charts-enterprise/src/series/linear-gauge/linearGaugeSeriesProperties.ts
var { makeSeriesTooltip: makeSeriesTooltip11, SeriesProperties: SeriesProperties2, Label: Label9, AxisLabel: AxisLabel5, getColorStops } = _ModuleSupport153;
var LinearGaugeDefaultTargetLabelProperties = class extends Label9 {
};
__decorateClass([
Property73
], LinearGaugeDefaultTargetLabelProperties.prototype, "spacing", 2);
var LinearGaugeTargetProperties = class extends BaseProperties33 {
constructor() {
super(...arguments);
this.value = 0;
this.label = new LinearGaugeDefaultTargetLabelProperties();
}
getStyle(defaultTarget) {
const {
fill = defaultTarget.fill ?? "black",
fillOpacity = defaultTarget.fillOpacity ?? 1,
stroke: stroke3 = defaultTarget.stroke ?? "black",
strokeWidth = defaultTarget.strokeWidth ?? 0,
strokeOpacity = defaultTarget.strokeOpacity ?? 1,
lineDash = defaultTarget.lineDash ?? [0],
lineDashOffset = defaultTarget.lineDashOffset ?? 0
} = this;
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
};
}
};
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "text", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "value", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "shape", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "placement", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "spacing", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "size", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "rotation", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "fill", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "stroke", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "lineDash", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property73
], LinearGaugeTargetProperties.prototype, "label", 2);
var LinearGaugeBarProperties = class extends BaseProperties33 {
constructor() {
super(...arguments);
this.enabled = true;
this.thicknessRatio = 1;
this.fills = new PropertiesArray7(_ModuleSupport153.StopProperties);
this.fillMode = "continuous";
this.fillOpacity = 1;
this.stroke = "black";
this.strokeWidth = 0;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
}
getStyle(defaultColorRange, horizontal, scale) {
const { fill, fills, fillMode, fillOpacity, stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = this;
const barFill = fill ?? createLinearGradient(fills, fillMode, defaultColorRange, scale, horizontal);
return {
fill: barFill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
};
}
};
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "enabled", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "thickness", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "thicknessRatio", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "fills", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "fillMode", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "fill", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "stroke", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "lineDash", 2);
__decorateClass([
Property73
], LinearGaugeBarProperties.prototype, "lineDashOffset", 2);
var LinearGaugeScaleIntervalProperties = class extends BaseProperties33 {
constructor() {
super(...arguments);
this.values = void 0;
this.step = void 0;
this.minSpacing = 0;
this.maxSpacing = 1e3;
}
};
__decorateClass([
Property73
], LinearGaugeScaleIntervalProperties.prototype, "values", 2);
__decorateClass([
Property73
], LinearGaugeScaleIntervalProperties.prototype, "step", 2);
__decorateClass([
Property73
], LinearGaugeScaleIntervalProperties.prototype, "minSpacing", 2);
__decorateClass([
Property73
], LinearGaugeScaleIntervalProperties.prototype, "maxSpacing", 2);
var LinearGaugeScaleLabelProperties = class extends AxisLabel5 {
constructor() {
super(...arguments);
this.placement = void 0;
}
};
__decorateClass([
Property73
], LinearGaugeScaleLabelProperties.prototype, "placement", 2);
var LinearGaugeScaleProperties = class extends BaseProperties33 {
constructor() {
super(...arguments);
this.min = 0;
this.max = 1;
this.fills = new PropertiesArray7(_ModuleSupport153.StopProperties);
this.fillMode = "continuous";
this.fillOpacity = 1;
this.stroke = "black";
this.strokeWidth = 0;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.defaultFill = "black";
this.interval = new LinearGaugeScaleIntervalProperties();
this.label = new LinearGaugeScaleLabelProperties();
}
getStyle(barEnabled, defaultColorRange, horizontal, scale) {
const {
fill,
fills,
defaultFill,
fillMode,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
} = this;
const scaleFill = fill ?? (barEnabled && fills.length === 0 ? defaultFill : void 0) ?? createLinearGradient(fills, fillMode, defaultColorRange, scale, horizontal);
return {
fill: scaleFill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
};
}
};
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "min", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "max", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "fills", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "fillMode", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "fill", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "stroke", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "lineDash", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "defaultFill", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "interval", 2);
__decorateClass([
Property73
], LinearGaugeScaleProperties.prototype, "label", 2);
var LinearGaugeLabelProperties = class extends AutoSizedLabel {
constructor() {
super(...arguments);
this.placement = "inside-center";
this.avoidCollisions = true;
}
};
__decorateClass([
Property73
], LinearGaugeLabelProperties.prototype, "text", 2);
__decorateClass([
Property73
], LinearGaugeLabelProperties.prototype, "placement", 2);
__decorateClass([
Property73
], LinearGaugeLabelProperties.prototype, "avoidCollisions", 2);
var LinearGaugeSeriesProperties = class extends SeriesProperties2 {
constructor() {
super(...arguments);
this.value = 0;
this.segmentation = new GaugeSegmentationProperties();
this.defaultColorRange = [];
this.targets = new PropertiesArray7(LinearGaugeTargetProperties);
this.defaultTarget = new LinearGaugeTargetProperties();
this.defaultScale = new LinearGaugeScaleProperties();
this.direction = "vertical";
this.thickness = 1;
this.cornerRadius = 0;
this.cornerMode = "container";
this.margin = 0;
this.scale = new LinearGaugeScaleProperties();
this.bar = new LinearGaugeBarProperties();
this.label = new LinearGaugeLabelProperties();
this.tooltip = makeSeriesTooltip11();
}
};
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "value", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "segmentation", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "defaultColorRange", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "targets", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "defaultTarget", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "defaultScale", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "direction", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "thickness", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "cornerRadius", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "cornerMode", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "margin", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "scale", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "bar", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "label", 2);
__decorateClass([
Property73
], LinearGaugeSeriesProperties.prototype, "tooltip", 2);
function createLinearGradient(fills, fillMode, defaultColorRange, scale, horizontal) {
const colorStops = getColorStops(fills, defaultColorRange, scale.domain, fillMode);
return {
type: "gradient",
gradient: "linear",
colorSpace: "oklch",
colorStops,
rotation: horizontal ? 90 : 0,
bounds: "series"
};
}
// packages/ag-charts-enterprise/src/series/linear-gauge/linearGaugeUtil.ts
import { _ModuleSupport as _ModuleSupport154 } from "ag-charts-community";
import { cachedTextMeasurer as cachedTextMeasurer6, isArray as isArray3, measureTextSegments as measureTextSegments2, toPlainText as toPlainText6, toTextString as toTextString2 } from "ag-charts-core";
var { BBox: BBox19 } = _ModuleSupport154;
function datumRect(datum) {
const { x0, y0, x1, y1, horizontalInset, verticalInset } = datum;
const x = Math.min(x0, x1) + horizontalInset;
const y = Math.min(y0, y1) + verticalInset;
const width = Math.max(Math.abs(x1 - x0) - 2 * horizontalInset, 0);
const height = Math.max(Math.abs(y1 - y0) - 2 * verticalInset, 0);
return { x, y, width, height };
}
function clipBBoxVisibility(datum, clipBBox) {
if (clipBBox == null)
return true;
const rect = datumRect(datum);
const delta3 = 1e-6;
const x0 = rect.x + delta3;
const y0 = rect.y + delta3;
const x1 = rect.x + rect.width - delta3;
const y1 = rect.y + rect.height - delta3;
const clipX0 = clipBBox.x;
const clipX1 = clipBBox.x + clipBBox.width;
const clipY0 = clipBBox.y;
const clipY1 = clipBBox.y + clipBBox.height;
return Math.max(x0, clipX0) <= Math.min(x1, clipX1) && Math.max(y0, clipY0) <= Math.min(y1, clipY1);
}
function hasClipBBox(datum) {
const { clipX0, clipX1, clipY0, clipY1 } = datum;
return clipX0 != null && clipX1 != null || clipY0 != null && clipY1 != null;
}
function computeClipBBox(datum) {
if (!hasClipBBox(datum))
return;
const { x0, y0, x1, y1 } = datum;
const { x, y, width, height } = datumRect(datum);
let { clipX0, clipX1, clipY0, clipY1 } = datum;
if (clipX0 == null || clipX1 == null) {
clipX0 = x0;
clipX1 = x1;
}
if (clipY0 == null || clipY1 == null) {
clipY0 = y0;
clipY1 = y1;
}
const clipX = Math.min(clipX0, clipX1);
const clipY = Math.min(clipY0, clipY1);
const clipWidth = Math.abs(clipX1 - clipX0);
const clipHeight = Math.abs(clipY1 - clipY0);
clipX0 = Math.max(x, clipX);
clipY0 = Math.max(y, clipY);
clipX1 = Math.min(x + width, clipX + clipWidth);
clipY1 = Math.min(y + height, clipY + clipHeight);
return new BBox19(
Math.min(clipX0, clipX1),
Math.min(clipY0, clipY1),
Math.abs(clipX1 - clipX0),
Math.abs(clipY1 - clipY0)
);
}
function prepareLinearGaugeSeriesAnimationFunctions(initialLoad, horizontal) {
const phase = initialLoad ? "initial" : "update";
const node = {
fromFn(sect, datum) {
const previousDatum = sect.previousDatum;
let { x0, y0, x1, y1, clipX0, clipY0, clipX1, clipY1 } = previousDatum ?? datum;
const { horizontalInset, verticalInset } = datum;
const previousHadClipBBox = previousDatum != null && hasClipBBox(previousDatum);
const nextHasClipBBox = hasClipBBox(datum);
if (previousHadClipBBox && nextHasClipBBox) {
} else if (!previousHadClipBBox && nextHasClipBBox) {
({ x0, y0, x1, y1, clipX0, clipY0, clipX1, clipY1 } = datum);
if (initialLoad) {
if (horizontal) {
clipX1 = datum.clipX0;
} else {
clipY1 = datum.clipY0;
}
}
} else if (previousHadClipBBox && !nextHasClipBBox) {
({ x0, y0, x1, y1 } = datum);
clipX0 = void 0;
clipY0 = void 0;
clipX1 = void 0;
clipY1 = void 0;
} else if (initialLoad) {
if (horizontal) {
x1 = x0;
} else {
y1 = y0;
}
}
return { x0, y0, x1, y1, clipX0, clipY0, clipX1, clipY1, horizontalInset, verticalInset, phase };
},
toFn(_sect, datum) {
const { x0, y0, x1, y1, clipX0, clipY0, clipX1, clipY1, horizontalInset, verticalInset } = datum;
return { x0, y0, x1, y1, clipX0, clipY0, clipX1, clipY1, horizontalInset, verticalInset };
},
applyFn(rect, params) {
rect.setProperties(resetLinearGaugeSeriesResetRectFunction(rect, params));
}
};
return { node };
}
function resetLinearGaugeSeriesResetRectFunction(_node, datum) {
const { x, y, width, height } = datumRect(datum);
const clipBBox = computeClipBBox(datum);
const visible = clipBBoxVisibility(datum, clipBBox);
return { x, y, width, height, clipBBox, visible };
}
var horizontalTextAligns = {
["Before" /* Before */]: "right",
["Center" /* Center */]: "center",
["After" /* After */]: "left"
};
var verticalTextBaselines = {
["Before" /* Before */]: "top",
["Center" /* Center */]: "middle",
["After" /* After */]: "bottom"
};
var horizontalAlignFactors = {
["Before" /* Before */]: -1,
["Center" /* Center */]: -0.5,
["After" /* After */]: 0
};
var verticalAlignFactors2 = {
["Before" /* Before */]: 0,
["Center" /* Center */]: -0.5,
["After" /* After */]: -1
};
function formatLinearGaugeLabels(series, ctx, selection, opts, bboxes, datumOverrides) {
const { seriesRect, gaugeRect, barRect } = bboxes;
const { padding: padding2, horizontal } = opts;
selection.each((label, labelDatum) => {
const labelText = getLabelText(series.id, ctx, labelDatum, datumOverrides?.label);
let boundingWidth;
let boundingHeight;
if (labelDatum.placement === "outside-start") {
if (horizontal) {
boundingWidth = gaugeRect.x;
boundingHeight = seriesRect.height;
} else {
boundingWidth = seriesRect.width;
boundingHeight = seriesRect.height - (gaugeRect.y + gaugeRect.height);
}
} else if (labelDatum.placement === "outside-end") {
if (horizontal) {
boundingWidth = seriesRect.width - (gaugeRect.x + gaugeRect.width);
boundingHeight = seriesRect.height;
} else {
boundingWidth = seriesRect.width;
boundingHeight = gaugeRect.y;
}
} else if (labelDatum.avoidCollisions) {
boundingWidth = gaugeRect.width;
boundingHeight = gaugeRect.height;
}
let layout;
if (labelText == null) {
return;
} else if (boundingWidth != null && boundingHeight != null) {
const sizeFittingHeight = () => ({
width: boundingWidth,
height: boundingHeight,
meta: null
});
const labelMeta = formatSingleLabel(toPlainText6(labelText), labelDatum, { padding: padding2 }, sizeFittingHeight);
layout = labelMeta?.[0];
} else {
const measurer3 = cachedTextMeasurer6(labelDatum);
const { width, height } = isArray3(labelText) ? measureTextSegments2(labelText, labelDatum) : measurer3.measureLines(toTextString2(labelText));
layout = {
text: labelText,
fontSize: labelDatum.fontSize,
lineHeight: labelDatum.lineHeight ?? measurer3.lineHeight(),
width,
height
};
}
if (layout == null) {
label.visible = false;
return;
}
const scale0 = horizontal ? gaugeRect.x : gaugeRect.y + gaugeRect.height;
const scale1 = horizontal ? gaugeRect.x + gaugeRect.width : gaugeRect.y;
const bar0 = horizontal ? barRect.x : barRect.y + barRect.height;
const bar1 = horizontal ? barRect.x + barRect.width : barRect.y;
const offset = labelDatum.spacing * (horizontal ? 1 : -1);
let bounds0;
let bounds1;
let s;
let align;
switch (labelDatum.placement) {
case "outside-start":
bounds0 = -Infinity;
bounds1 = Infinity;
s = scale0 - offset;
align = "Before" /* Before */;
break;
case "outside-end":
bounds0 = -Infinity;
bounds1 = Infinity;
s = scale1 + offset;
align = "After" /* After */;
break;
case "inside-start":
bounds0 = scale0;
bounds1 = bar1;
s = scale0 + offset;
align = "After" /* After */;
break;
case "inside-end":
bounds0 = bar1;
bounds1 = scale1;
s = scale1 - offset;
align = "Before" /* Before */;
break;
case "inside-center":
bounds0 = scale0;
bounds1 = scale1;
s = (scale0 + scale1) / 2;
align = "Center" /* Center */;
break;
case "bar-inside":
bounds0 = bar0;
bounds1 = bar1;
s = (bar0 + bar1) / 2;
align = "Center" /* Center */;
break;
case "bar-inside-end":
bounds0 = bar0;
bounds1 = bar1;
s = bar1 - offset;
align = "Before" /* Before */;
break;
case "bar-outside-end":
bounds0 = bar1;
bounds1 = scale1;
s = bar1 + offset;
align = "After" /* After */;
break;
case "bar-end":
bounds0 = -Infinity;
bounds1 = Infinity;
s = bar1;
align = "Center" /* Center */;
break;
}
const x = horizontal ? s : gaugeRect.x + gaugeRect.width / 2;
const y = horizontal ? gaugeRect.y + gaugeRect.height / 2 : s;
let s0;
let s1;
if (horizontal) {
s0 = x + horizontalAlignFactors[align] * layout.width;
s1 = s0 + layout.width;
} else {
s0 = y + verticalAlignFactors2[align] * layout.height;
s1 = s0 + layout.height;
}
const inside = Math.min(s0, s1) >= Math.min(bounds0, bounds1) && Math.max(s0, s1) <= Math.max(bounds0, bounds1);
if (labelDatum.avoidCollisions && !inside) {
label.visible = false;
return;
}
label.visible = true;
label.text = layout.text;
label.fontSize = layout.fontSize;
label.lineHeight = layout.lineHeight;
label.textAlign = horizontal ? horizontalTextAligns[align] : "center";
label.textBaseline = horizontal ? "middle" : verticalTextBaselines[align];
label.x = x;
label.y = y;
});
}
// packages/ag-charts-enterprise/src/series/linear-gauge/linearGaugeSeries.ts
var {
fromToMotion: fromToMotion2,
resetMotion: resetMotion3,
SeriesNodePickMode: SeriesNodePickMode8,
createDatumId: createDatumId10,
BBox: BBox20,
Group: Group12,
PointerEvents: PointerEvents5,
Selection: Selection7,
Rect: Rect8,
Text: Text3,
TransformableText: TransformableText2,
Marker: Marker3,
LinearScale: LinearScale4,
generateTicks: generateTicks2,
NiceMode
} = _ModuleSupport155;
var horizontalTargetPlacementRotation = {
before: 180,
middle: 0,
after: 0
};
var verticalTargetPlacementRotation = {
before: 90,
middle: 0,
after: -90
};
var LinearGaugeSeries = class extends _ModuleSupport155.Series {
constructor(moduleCtx) {
super({
moduleCtx,
pickModes: [SeriesNodePickMode8.EXACT_SHAPE_MATCH, SeriesNodePickMode8.NEAREST_NODE]
});
this.properties = new LinearGaugeSeriesProperties();
this.seriesRect = BBox20.NaN;
this.gaugeRect = BBox20.NaN;
this.scale = new LinearScale4();
this.originX = 0;
this.originY = 0;
this.scaleGroup = this.contentGroup.appendChild(new Group12({ name: "scaleGroup" }));
this.itemGroup = this.contentGroup.appendChild(new Group12({ name: "itemGroup" }));
this.itemTargetGroup = this.contentGroup.appendChild(new Group12({ name: "itemTargetGroup" }));
this.itemTargetLabelGroup = this.contentGroup.appendChild(new Group12({ name: "itemTargetLabelGroup" }));
this.itemLabelGroup = this.contentGroup.appendChild(new Group12({ name: "itemLabelGroup" }));
this.highlightTargetGroup = this.highlightGroup.appendChild(
new Group12({ name: "itemTargetLabelGroup" })
);
this.tickGroup = this.contentGroup.appendChild(new Group12({ name: "tickGroup" }));
this.scaleSelection = Selection7.select(
this.scaleGroup,
() => this.nodeFactory()
);
this.datumSelection = Selection7.select(
this.itemGroup,
() => this.nodeFactory()
);
this.targetSelection = Selection7.select(
this.itemTargetGroup,
() => this.markerFactory()
);
this.targetLabelSelection = Selection7.select(this.itemTargetLabelGroup, Text3);
this.labelSelection = Selection7.select(
this.itemLabelGroup,
Text3
);
this.highlightTargetSelection = Selection7.select(this.highlightTargetGroup, () => this.markerFactory());
this.tickSelection = Selection7.select(this.tickGroup, TransformableText2);
this.datumUnion = new DatumUnion();
this.animationState = new StateMachine12("empty", {
empty: {
update: {
target: "ready",
action: () => this.animateEmptyUpdateReady()
},
reset: "empty",
skip: "ready"
},
ready: {
updateData: "waiting",
clear: "clearing",
resize: () => this.animateReadyResize(),
reset: "empty",
skip: "ready"
},
waiting: {
update: {
target: "ready",
action: () => this.animateWaitingUpdateReady()
},
reset: "empty",
skip: "ready"
},
clearing: {
update: {
target: "empty"
},
reset: "empty",
skip: "ready"
}
});
this.scaleGroup.pointerEvents = PointerEvents5.None;
this.tickGroup.pointerEvents = PointerEvents5.None;
}
get range() {
return this.horizontal ? [0, this.gaugeRect.width] : [0, this.gaugeRect.height];
}
get horizontal() {
return this.properties.direction === "horizontal";
}
get hasData() {
return true;
}
nodeFactory() {
const rect = new Rect8();
rect.crisp = true;
return rect;
}
markerFactory() {
return new Marker3();
}
processData() {
this.nodeDataRefresh = true;
this.animationState.transition("updateData");
}
formatLabel(value) {
return formatLabel(value, this.properties.scale);
}
getShapeFillBBox() {
const { properties, originX, originY, horizontal, scale } = this;
const { thickness } = properties;
const length = findRangeExtent2(scale.range);
const bbox = new BBox20(originX, originY, horizontal ? length : thickness, horizontal ? thickness : length);
return {
axis: bbox,
series: bbox
};
}
getTargets() {
const { properties } = this;
const defaultTarget = properties.defaultTarget;
return Array.from(properties.targets).map((target) => {
const {
text: text2 = defaultTarget.text,
value = defaultTarget.value ?? 0,
shape = defaultTarget.shape ?? "triangle",
rotation = defaultTarget.rotation ?? 0,
placement = defaultTarget.placement ?? "middle",
spacing = defaultTarget.spacing ?? 0,
size = defaultTarget.size ?? 0
} = target;
const {
enabled: labelEnabled = defaultTarget.label.enabled,
color: labelColor = defaultTarget.label.color ?? "black",
fontStyle: labelFontStyle = defaultTarget.label.fontStyle ?? "normal",
fontWeight: labelFontWeight = defaultTarget.label.fontWeight ?? "normal",
fontSize: labelFontSize = defaultTarget.label.fontSize,
fontFamily: labelFontFamily = defaultTarget.label.fontFamily,
spacing: labelSpacing = defaultTarget.label.spacing ?? 0
} = target.label;
return {
text: text2,
value,
shape,
placement,
spacing,
size,
rotation,
label: {
enabled: labelEnabled,
color: labelColor,
fontStyle: labelFontStyle,
fontWeight: labelFontWeight,
fontSize: labelFontSize,
fontFamily: labelFontFamily,
spacing: labelSpacing
},
style: target.getStyle(defaultTarget)
};
});
}
getTargetPoint(target) {
const { properties, originX, originY, horizontal, scale, gaugeRect } = this;
const { thickness } = properties;
const { value, placement, spacing, size } = target;
const mainOffset = scale.convert(value);
let crossOffset;
switch (placement) {
case "before":
crossOffset = -(spacing + size / 2);
break;
case "after":
crossOffset = thickness + spacing + size / 2;
break;
default:
crossOffset = thickness / 2;
break;
}
return {
x: originX + gaugeRect.x + (horizontal ? mainOffset : crossOffset),
y: originY + gaugeRect.y + (horizontal ? crossOffset : mainOffset)
};
}
getTargetLabel(target) {
const { size, placement, label } = target;
const { spacing, color: fill, fontStyle, fontWeight, fontSize, fontFamily } = label;
const lineHeight = void 0;
const offset = size / 2 + spacing;
let textAlign;
let textBaseline;
let offsetX = 0;
let offsetY = 0;
if (this.horizontal) {
textAlign = "center";
if (placement === "after") {
textBaseline = "top";
offsetY = offset;
} else {
textBaseline = "bottom";
offsetY = -offset;
}
} else {
textBaseline = "middle";
if (placement === "before") {
textAlign = "right";
offsetX = -offset;
} else {
textAlign = "left";
offsetX = offset;
}
}
return {
offsetX,
offsetY,
fill,
textAlign,
textBaseline,
fontStyle,
fontWeight,
fontSize,
fontFamily,
lineHeight
};
}
labelDatum(label, value) {
const {
placement,
avoidCollisions,
spacing,
text: text2,
color: fill,
fontSize,
minimumFontSize,
fontStyle,
fontWeight,
fontFamily,
lineHeight,
wrapping,
overflowStrategy,
formatter = (params) => this.formatLabel(params.value)
} = label;
return {
placement,
avoidCollisions,
spacing,
text: text2,
value,
fill,
fontSize,
minimumFontSize,
fontStyle,
fontWeight,
fontFamily,
lineHeight,
wrapping,
overflowStrategy,
formatter
};
}
verticalLabelInset() {
const { label } = this.properties;
const measurer3 = cachedTextMeasurer7(label);
const lines = label.text?.split("\n");
const labelSize = (label.lineHeight ?? measurer3.lineHeight()) * (lines?.length ?? 1);
return label.spacing + labelSize;
}
horizontalLabelInset() {
const { scale, properties } = this;
const { scale: scaleProps, label } = properties;
const lines = label.text?.split("\n");
const measurer3 = cachedTextMeasurer7(label);
const ticks = scaleProps.interval.values ?? scale.ticks({
nice: [false, false],
interval: scaleProps.interval.step,
minTickCount: 0,
maxTickCount: 6,
tickCount: 5
})?.ticks ?? [];
const linesOrTicks = lines ?? ticks?.map((tick) => getLabelText(this.id, this.ctx, this.labelDatum(label, tick)) ?? "");
const labelSize = linesOrTicks.reduce((accum, text2) => {
const { width } = isArray4(text2) ? measureTextSegments3(text2, label) : measurer3.measureLines(toTextString3(text2));
return Math.max(accum, width);
}, 0);
return label.spacing + labelSize;
}
tickFormatter(domain, ticks) {
const { format, formatter } = this.properties.scale.label;
let tickFormatter;
if (format != null) {
tickFormatter = tickFormat(ticks, typeof format === "string" ? format : void 0);
}
return (value, index) => {
let r = void 0;
if (formatter) {
r ?? (r = formatWithContext(this.ctx, formatter, { value, index, domain, boundSeries: void 0 }));
}
r ?? (r = tickFormatter?.(value));
return r ?? this.formatLabel(value);
};
}
createNodeData() {
const { id: seriesId, properties, horizontal, scale, seriesRect } = this;
const {
value,
segmentation,
thickness,
cornerRadius,
cornerMode,
bar,
scale: scaleProps,
label,
defaultColorRange,
defaultScale
} = properties;
scale.domain = [scaleProps.min, scaleProps.max];
scale.range = horizontal ? [0, seriesRect.width] : [seriesRect.height, 0];
let axisRotation;
let sideFlag;
if (horizontal) {
sideFlag = 1;
axisRotation = Math.PI / -2;
} else if (scaleProps.label.placement === "before") {
sideFlag = 1;
axisRotation = 0;
} else {
sideFlag = -1;
axisRotation = 0;
}
let x0;
let x1;
let y0;
let y1;
if (horizontal) {
x0 = 0;
x1 = seriesRect.width;
y0 = (seriesRect.height - thickness) / 2;
y1 = y0 + thickness;
if (label.placement === "outside-start") {
x0 += this.horizontalLabelInset();
} else if (label.placement === "outside-end") {
x1 -= this.horizontalLabelInset();
}
} else {
x0 = (seriesRect.width - thickness) / 2;
x1 = x0 + thickness;
y1 = 0;
y0 = seriesRect.height;
if (label.placement === "outside-start") {
y0 -= this.verticalLabelInset();
} else if (label.placement === "outside-end") {
y1 += this.verticalLabelInset();
}
}
this.gaugeRect = new BBox20(Math.min(x0, x1), Math.min(y0, y1), Math.abs(x1 - x0), Math.abs(y1 - y0));
const originX = 0;
const originY = 0;
scale.domain = [scaleProps.min, scaleProps.max];
scale.range = horizontal ? [x0, x1] : [y0, y1];
const scaleLabel = mergeDefaults13({ parallel: horizontal }, scaleProps.label, defaultScale.label);
const {
tickData: { ticks: tickData }
} = generateTicks2({
scale,
label: scaleLabel,
interval: scaleProps.interval,
tickFormatter: (domain, ticks) => this.tickFormatter(domain, ticks),
domain: scale.domain,
range: this.range,
reverse: false,
primaryTickCount: void 0,
defaultTickMinSpacing: 0,
visibleRange: [0, 1],
niceMode: [NiceMode.Off, NiceMode.Off],
labelOffset: 0,
axisRotation,
sideFlag
});
const isReversed = false;
const targets = this.getTargets();
const nodeData = [];
const targetData = [];
const labelData = [];
const scaleData = [];
const [m0, m1] = scale.range;
const mainAxisSize = Math.abs(m1 - m0);
const containerX = horizontal ? scale.convert(value) : x1;
const containerY = horizontal ? y1 : scale.convert(value);
const inset = segmentation.enabled ? segmentation.spacing / 2 : 0;
const horizontalInset = horizontal ? inset : 0;
const verticalInset = horizontal ? 0 : inset;
const barThickness = Math.min(bar.thickness ?? Math.round(bar.thicknessRatio * thickness), thickness);
const barInset = -(thickness - barThickness) / 2;
const barXInset = horizontal ? 0 : barInset;
const barYInset = horizontal ? barInset : 0;
const cornersOnAllItems = cornerMode === "item";
const maxTicks = Math.ceil(mainAxisSize);
let segments = segmentation.enabled ? segmentation.interval.getSegments(scale, maxTicks) : void 0;
const barStyle = bar.getStyle(defaultColorRange, horizontal, scale);
const scaleStyle = scaleProps.getStyle(bar.enabled, defaultColorRange, horizontal, scale);
if (segments == null && cornersOnAllItems) {
const segmentStart = Math.min(...scale.domain);
const segmentEnd = Math.max(...scale.domain);
const datum = { value, segmentStart, segmentEnd };
if (bar.enabled) {
const barAppliedCornerRadius = Math.min(cornerRadius, barThickness / 2, mainAxisSize / 2);
const barCornerInset = barAppliedCornerRadius * (isReversed ? -1 : 1);
const barCornerXInset = horizontal ? barCornerInset : 0;
const barCornerYInset = horizontal ? 0 : barCornerInset;
nodeData.push({
series: this,
itemId: `value`,
datum,
datumIndex: { type: 0 /* Node */ },
type: 0 /* Node */,
x0: originX + x0 - barCornerXInset - barXInset,
y0: originY + y0 - barCornerYInset - barYInset,
x1: originX + containerX + barCornerXInset + barXInset,
y1: originY + containerY + barCornerYInset + barYInset,
clipX0: void 0,
clipY0: void 0,
clipX1: void 0,
clipY1: void 0,
topLeftCornerRadius: cornerRadius,
topRightCornerRadius: cornerRadius,
bottomRightCornerRadius: cornerRadius,
bottomLeftCornerRadius: cornerRadius,
horizontalInset,
verticalInset,
style: barStyle
});
}
const scaleAppliedCornerRadius = Math.min(cornerRadius, thickness / 2, mainAxisSize / 2);
const scaleCornerInset = scaleAppliedCornerRadius * (isReversed ? -1 : 1);
const scaleCornerXInset = horizontal ? scaleCornerInset : 0;
const scaleCornerYInset = horizontal ? 0 : scaleCornerInset;
scaleData.push({
series: this,
itemId: `scale`,
datum,
datumIndex: { type: 0 /* Node */ },
type: 0 /* Node */,
x0: originX + x0 - scaleCornerXInset,
y0: originY + y0 - scaleCornerYInset,
x1: originX + x1 + scaleCornerXInset,
y1: originY + y1 + scaleCornerYInset,
clipX0: void 0,
clipY0: void 0,
clipX1: void 0,
clipY1: void 0,
topLeftCornerRadius: cornerRadius,
topRightCornerRadius: cornerRadius,
bottomRightCornerRadius: cornerRadius,
bottomLeftCornerRadius: cornerRadius,
horizontalInset,
verticalInset,
style: scaleStyle
});
} else {
segments ?? (segments = scale.domain);
const clipX0 = originX + x0 - barXInset;
const clipY0 = originY + y0 - barYInset;
const clipX1 = originX + containerX + barXInset;
const clipY1 = originY + containerY + barYInset;
for (let i = 0; i < segments.length - 1; i += 1) {
const segmentStart = segments[i + 0];
const segmentEnd = segments[i + 1];
const datum = { value, segmentStart, segmentEnd };
const isStart = i === 0;
const isEnd = i === segments.length - 2;
const itemStart = scale.convert(segmentStart);
const itemEnd = scale.convert(segmentEnd);
const startCornerRadius = cornersOnAllItems || isStart ? cornerRadius : 0;
const endCornerRadius = cornersOnAllItems || isEnd ? cornerRadius : 0;
const topLeftCornerRadius = horizontal ? startCornerRadius : endCornerRadius;
const topRightCornerRadius = endCornerRadius;
const bottomRightCornerRadius = horizontal ? endCornerRadius : startCornerRadius;
const bottomLeftCornerRadius = startCornerRadius;
if (bar.enabled) {
nodeData.push({
series: this,
itemId: `value-${i}`,
datum,
datumIndex: { type: 0 /* Node */ },
type: 0 /* Node */,
x0: originX + (horizontal ? itemStart : x0),
y0: originY + (horizontal ? y0 : itemStart),
x1: originX + (horizontal ? itemEnd : x1),
y1: originY + (horizontal ? y1 : itemEnd),
clipX0,
clipY0,
clipX1,
clipY1,
topLeftCornerRadius,
topRightCornerRadius,
bottomRightCornerRadius,
bottomLeftCornerRadius,
horizontalInset,
verticalInset,
style: barStyle
});
}
scaleData.push({
series: this,
itemId: `scale-${i}`,
datum,
datumIndex: { type: 0 /* Node */ },
type: 0 /* Node */,
x0: originX + (horizontal ? itemStart : x0),
y0: originY + (horizontal ? y0 : itemStart),
x1: originX + (horizontal ? itemEnd : x1),
y1: originY + (horizontal ? y1 : itemEnd),
clipX0: void 0,
clipY0: void 0,
clipX1: void 0,
clipY1: void 0,
topLeftCornerRadius,
topRightCornerRadius,
bottomRightCornerRadius,
bottomLeftCornerRadius,
horizontalInset,
verticalInset,
style: scaleStyle
});
}
}
for (const dataArray of [scaleData, nodeData]) {
for (const datum of dataArray) {
const dx0 = datum.clipX0 ?? datum.x0;
const dx1 = datum.clipX1 ?? datum.x1;
const dy0 = datum.clipY0 ?? datum.y0;
const dy1 = datum.clipY1 ?? datum.y1;
datum.midPoint = { x: (dx0 + dx1) / 2, y: (dy0 + dy1) / 2 };
}
}
if (label.enabled) {
labelData.push(this.labelDatum(label, value));
}
const targetPlacementRotation2 = horizontal ? horizontalTargetPlacementRotation : verticalTargetPlacementRotation;
for (let i = 0; i < targets.length; i += 1) {
const target = targets[i];
const { value: targetValue, text: text2, shape, size, style } = target;
const targetPoint = this.getTargetPoint(target);
const targetRotation = toRadians4(target.rotation + targetPlacementRotation2[target.placement]);
targetData.push({
series: this,
itemId: `target-${i}`,
midPoint: targetPoint,
datum: { value: targetValue },
datumIndex: { type: 1 /* Target */, index: i },
type: 1 /* Target */,
value: targetValue,
text: text2,
x: targetPoint.x,
y: targetPoint.y,
shape,
size,
rotation: targetRotation,
label: this.getTargetLabel(target),
style
});
}
return {
itemId: seriesId,
nodeData,
tickData,
targetData,
labelData,
scaleData
};
}
findNodeDatum(itemId) {
return findGaugeNodeDatum(this, itemId);
}
updateSelections(resize) {
if (this.nodeDataRefresh || resize) {
this.contextNodeData = this.createNodeData();
this.nodeDataRefresh = false;
}
}
highlightDatum(node) {
if (node?.series === this && node.type === 1 /* Target */) {
return node;
}
}
update({ seriesRect }) {
const {
datumSelection,
labelSelection,
targetSelection,
targetLabelSelection,
scaleSelection,
highlightTargetSelection,
tickSelection
} = this;
this.seriesRect = seriesRect ?? BBox20.NaN;
const resize = this.checkResize(seriesRect);
this.updateSelections(resize);
this.contentGroup.visible = this.visible;
this.contentGroup.opacity = this.getOpacity();
const nodeData = this.contextNodeData?.nodeData ?? [];
const labelData = this.contextNodeData?.labelData ?? [];
const targetData = this.contextNodeData?.targetData ?? [];
const scaleData = this.contextNodeData?.scaleData ?? [];
const tickData = this.contextNodeData?.tickData ?? [];
const highlightTargetDatum = this.highlightDatum(this.ctx.highlightManager.getActiveHighlight());
this.scaleSelection = this.updateScaleSelection({ scaleData, scaleSelection });
this.updateScaleNodes({ scaleSelection });
this.targetSelection = this.updateTargetSelection({ targetData, targetSelection });
this.updateTargetNodes({ targetSelection, isHighlight: false });
this.targetLabelSelection = this.updateTargetLabelSelection({ targetData, targetLabelSelection });
this.updateTargetLabelNodes({ targetLabelSelection });
this.datumSelection = this.updateDatumSelection({ nodeData, datumSelection });
this.updateDatumNodes({ datumSelection });
this.labelSelection = this.updateLabelSelection({ labelData, labelSelection });
this.updateLabelNodes({ labelSelection });
this.highlightTargetSelection = this.updateTargetSelection({
targetData: highlightTargetDatum == null ? [] : [highlightTargetDatum],
targetSelection: highlightTargetSelection
});
this.updateTargetNodes({ targetSelection: highlightTargetSelection, isHighlight: true });
this.tickSelection = this.updateTickSelection({ tickData, tickSelection });
this.updateTickNodes({ tickSelection });
if (resize) {
this.animationState.transition("resize");
}
this.animationState.transition("update");
}
updateDatumSelection(opts) {
return opts.datumSelection.update(opts.nodeData, void 0, (datum) => {
return createDatumId10(opts.nodeData.length, datum.itemId);
});
}
updateDatumNodes(opts) {
const { datumSelection } = opts;
const { ctx } = this;
const animationDisabled = ctx.animationManager.isSkipped();
const fillBBox = this.getShapeFillBBox();
datumSelection.each((rect, datum) => {
const { topLeftCornerRadius, topRightCornerRadius, bottomRightCornerRadius, bottomLeftCornerRadius } = datum;
rect.setStyleProperties(datum.style, fillBBox);
rect.topLeftCornerRadius = topLeftCornerRadius;
rect.topRightCornerRadius = topRightCornerRadius;
rect.bottomRightCornerRadius = bottomRightCornerRadius;
rect.bottomLeftCornerRadius = bottomLeftCornerRadius;
rect.pointerEvents = this.properties.bar.enabled ? _ModuleSupport155.PointerEvents.All : _ModuleSupport155.PointerEvents.None;
if (animationDisabled || rect.previousDatum == null) {
rect.setProperties(resetLinearGaugeSeriesResetRectFunction(rect, datum));
}
});
const { horizontal } = this;
this.datumUnion.update(datumSelection, this.itemGroup, _ModuleSupport155.Rect, (node, first, last) => {
const left = Math.min(first.x, last.x);
const right = Math.max(first.x + first.width, last.x + last.width);
const top = Math.min(first.y, last.y);
const bottom = Math.max(first.y + first.height, last.y + last.height);
const width = right - left;
const height = bottom - top;
node.pointerEvents = _ModuleSupport155.PointerEvents.None;
node.x = left;
node.y = top;
node.width = width;
node.height = height;
node.topLeftCornerRadius = horizontal ? first.topLeftCornerRadius : last.topLeftCornerRadius;
node.topRightCornerRadius = last.topRightCornerRadius;
node.bottomRightCornerRadius = horizontal ? last.bottomRightCornerRadius : first.bottomRightCornerRadius;
node.bottomLeftCornerRadius = first.bottomLeftCornerRadius;
const firstClipBBox = first.clipBBox;
const lastClipBBox = last.clipBBox ?? firstClipBBox;
if (firstClipBBox && lastClipBBox) {
node.clipBBox = BBox20.merge([firstClipBBox, lastClipBBox]).intersection(
horizontal ? new BBox20(left, -Infinity, width, Infinity) : new BBox20(-Infinity, top, Infinity, height)
);
} else {
node.clipBBox = void 0;
}
});
}
updateScaleSelection(opts) {
return opts.scaleSelection.update(opts.scaleData, void 0, (datum) => {
return createDatumId10(opts.scaleData.length, datum.itemId);
});
}
updateScaleNodes(opts) {
const { scaleSelection } = opts;
const fillBBox = this.getShapeFillBBox();
scaleSelection.each((rect, datum) => {
const { topLeftCornerRadius, topRightCornerRadius, bottomRightCornerRadius, bottomLeftCornerRadius } = datum;
rect.setStyleProperties(datum.style, fillBBox);
rect.setProperties(resetLinearGaugeSeriesResetRectFunction(rect, datum));
rect.topLeftCornerRadius = topLeftCornerRadius;
rect.topRightCornerRadius = topRightCornerRadius;
rect.bottomRightCornerRadius = bottomRightCornerRadius;
rect.bottomLeftCornerRadius = bottomLeftCornerRadius;
rect.setProperties(resetLinearGaugeSeriesResetRectFunction(rect, datum));
});
}
updateTargetSelection(opts) {
return opts.targetSelection.update(opts.targetData, void 0, (target) => target.itemId);
}
updateTargetNodes(opts) {
const { targetSelection, isHighlight } = opts;
targetSelection.each((target, datum) => {
const { x, y, shape, size, rotation } = datum;
const style = this.getTargetStyle(isHighlight, datum);
target.setStyleProperties(style);
target.size = size;
target.shape = shape === "line" ? lineMarker : shape;
target.translationX = x;
target.translationY = y;
target.rotation = rotation;
});
}
getTargetStyle(isHighlight, { datumIndex, style }) {
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
return mergeDefaults13(highlightStyle, {
...style,
opacity: 1
});
}
updateTargetLabelSelection(opts) {
return opts.targetLabelSelection.update(opts.targetData);
}
updateTargetLabelNodes(opts) {
const { targetLabelSelection } = opts;
targetLabelSelection.each((label, target) => {
const { x, y, text: text2 } = target;
const { offsetX, offsetY, fill, fontStyle, fontWeight, fontSize, fontFamily, textAlign, textBaseline } = target.label;
label.visible = true;
label.x = x + offsetX;
label.y = y + offsetY;
label.text = text2;
label.fill = fill;
label.fontStyle = fontStyle;
label.fontWeight = fontWeight;
label.fontSize = fontSize;
label.fontFamily = fontFamily;
label.textAlign = textAlign;
label.textBaseline = textBaseline;
});
}
updateTickSelection(opts) {
return opts.tickSelection.update(opts.tickData, void 0, (datum) => datum.tickId);
}
updateTickNodes(opts) {
const { gaugeRect, properties } = this;
const defaultScale = properties.defaultScale;
const {
enabled,
color: color7,
fontFamily = defaultScale.label.fontFamily,
fontSize = defaultScale.label.fontSize,
fontStyle,
fontWeight = defaultScale.label.fontWeight,
spacing
} = properties.scale.label;
let { placement } = properties.scale.label;
const rotation = toRadians4(properties.scale.label.rotation ?? 0);
let textAlign;
let textBaseline;
let textX;
let textY;
if (this.horizontal) {
placement ?? (placement = "after");
textAlign = "center";
textBaseline = placement === "before" ? "bottom" : "top";
textY = this.originY + gaugeRect.y + (placement === "before" ? -spacing : gaugeRect.height + spacing);
} else {
placement ?? (placement = "before");
textAlign = placement === "before" ? "end" : "start";
textBaseline = "middle";
textX = this.originX + gaugeRect.x + (placement === "before" ? -spacing : gaugeRect.width + spacing);
}
opts.tickSelection.each((label, datum) => {
if (!enabled) {
label.visible = false;
return;
}
const x = textX ?? datum.translation;
const y = textY ?? datum.translation;
label.visible = true;
label.text = datum.tickLabel;
label.fill = color7;
label.fontFamily = fontFamily;
label.fontSize = fontSize;
label.fontStyle = fontStyle;
label.fontWeight = fontWeight;
label.textBaseline = textBaseline;
label.textAlign = textAlign;
label.x = x;
label.y = y;
label.rotationCenterX = x;
label.rotationCenterY = y;
label.rotation = rotation;
});
}
updateLabelSelection(opts) {
return opts.labelSelection.update(opts.labelData, void 0, (_datum) => "primary");
}
updateLabelNodes(opts) {
const { labelSelection } = opts;
const animationDisabled = this.ctx.animationManager.isSkipped();
labelSelection.each((label, datum) => {
label.fill = datum.fill;
label.fontStyle = datum.fontStyle;
label.fontWeight = datum.fontWeight;
label.fontFamily = datum.fontFamily;
});
if (animationDisabled || this.labelsHaveExplicitText()) {
this.formatLabelText();
}
}
labelsHaveExplicitText() {
for (const { datum } of this.labelSelection) {
if (datum.text == null) {
return false;
}
}
return true;
}
formatLabelText(datum) {
const { labelSelection, horizontal, scale, seriesRect, gaugeRect } = this;
const { x, y, width, height } = gaugeRect;
const value = datum?.label ?? this.properties.value;
let barRect;
if (horizontal) {
const xValue = scale.convert(value);
barRect = new BBox20(x, y, xValue - x, height);
} else {
const yValue = scale.convert(value);
barRect = new BBox20(x, yValue, width, height - yValue);
}
const bboxes = { seriesRect, gaugeRect, barRect };
const { margin: padding2 } = this.properties;
formatLinearGaugeLabels(this, this.ctx, labelSelection, { padding: padding2, horizontal }, bboxes, datum);
}
resetAllAnimation() {
this.ctx.animationManager.stopByAnimationGroupId(this.id);
resetMotion3([this.datumSelection], resetLinearGaugeSeriesResetRectFunction);
this.formatLabelText();
}
resetAnimation(phase) {
if (phase === "initial") {
this.animationState.transition("reset");
} else if (phase === "ready") {
this.animationState.transition("skip");
}
}
animateLabelText(params = {}) {
const { animationManager } = this.ctx;
let labelFrom = 0;
let labelTo = 0;
this.labelSelection.each((label, datum) => {
label.opacity = 1;
labelFrom = label.previousDatum?.value ?? params.from ?? datum.value;
labelTo = datum.value;
});
if (this.labelsHaveExplicitText()) {
} else if (labelFrom === labelTo) {
this.formatLabelText({ label: labelTo });
} else {
const animationId = `${this.id}_labels`;
animationManager.animate({
id: animationId,
groupId: "label",
from: { label: labelFrom },
to: { label: labelTo },
phase: params.phase ?? "update",
ease: easeOut2,
onUpdate: (datum) => this.formatLabelText(datum),
onStop: () => this.formatLabelText({ label: labelTo })
});
}
}
animateEmptyUpdateReady() {
const { animationManager } = this.ctx;
const { node } = prepareLinearGaugeSeriesAnimationFunctions(true, this.horizontal);
fromToMotion2(this.id, "node", animationManager, [this.datumSelection], node, (_sector, datum) => datum.itemId);
fromToMotion2(this.id, "label", animationManager, [this.labelSelection], fadeInFns, () => "primary");
this.animateLabelText({ from: 0, phase: "initial" });
}
animateWaitingUpdateReady() {
const { animationManager } = this.ctx;
const { node } = prepareLinearGaugeSeriesAnimationFunctions(false, this.horizontal);
fromToMotion2(this.id, "node", animationManager, [this.datumSelection], node, (_sector, datum) => datum.itemId);
this.animateLabelText();
}
animateReadyResize() {
this.resetAllAnimation();
}
getSeriesDomain() {
return { domain: [0, 1] };
}
dataCount() {
return Number.NaN;
}
getSeriesRange() {
return [Number.NaN, Number.NaN];
}
getLegendData() {
return [];
}
getTooltipContent(datumIndex) {
const { id: seriesId, properties } = this;
const { tooltip } = properties;
if (datumIndex == null)
return;
let value;
let text2;
let fallbackLabel;
if (datumIndex.type === 0 /* Node */) {
value = properties.value;
text2 = properties.label.text;
fallbackLabel = this.ctx.localeManager.t("ariaLabelGaugeValue");
} else {
({ value, text: text2 } = properties.targets[datumIndex.index]);
fallbackLabel = this.ctx.localeManager.t("ariaLabelGaugeTarget");
}
if (value == null)
return;
return this.formatTooltipWithContext(
tooltip,
{
data: [{ label: text2, fallbackLabel, value: this.formatLabel(value) }]
},
{ seriesId, title: void 0, datum: void 0, value }
);
}
pickNodeClosestDatum(point) {
return pickGaugeNearestDatum(this, point);
}
pickFocus(opts) {
return pickGaugeFocus(this, opts);
}
getCaptionText() {
return this.formatLabel(this.properties.value);
}
getCategoryValue(_datumIndex) {
return;
}
datumIndexForCategoryValue(_categoryValue) {
return;
}
hasItemStylers() {
return this.properties.label.itemStyler != null;
}
};
LinearGaugeSeries.className = "LinearGaugeSeries";
LinearGaugeSeries.type = "linear-gauge";
// packages/ag-charts-enterprise/src/series/linear-gauge/linearGaugeModule.ts
var themeTemplate2 = {
minWidth: 200,
minHeight: 200,
tooltip: {
enabled: false
},
series: {
thickness: 50,
defaultColorRange: {
$if: [
{ $eq: [{ $palette: "type" }, "inbuilt"] },
{ $interpolate: [{ $palette: "secondDivergingColors" }, 5] },
SAFE_RANGE2_OPERATION3
]
},
scale: {
// @ts-expect-error undocumented option
defaultFill: { $path: ["/1", { $palette: "fill" }, { $palette: "hierarchyColors" }] },
// TODO: mix backgroundColor and foregroundColor?
stroke: { $path: ["/2", SAFE_STROKE_FILL_OPERATION, { $palette: "hierarchyColors" }] },
// TODO: mix backgroundColor and foregroundColor?
strokeWidth: { $isUserOption: ["./stroke", 2, 0] },
label: {
spacing: 11
}
},
bar: {
strokeWidth: { $isUserOption: ["./stroke", 2, 0] }
},
segmentation: {
enabled: false,
interval: {},
spacing: 1
},
defaultTarget: {
fill: { $ref: "foregroundColor" },
stroke: { $ref: "foregroundColor" },
size: 10,
shape: "triangle",
placement: "after",
spacing: 5,
label: {
enabled: true,
fontWeight: { $ref: "fontWeight" },
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
color: { $ref: "textColor" },
spacing: 5
}
},
defaultScale: {
label: {
fontWeight: { $ref: "fontWeight" },
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
color: { $ref: "textColor" }
}
},
label: {
...LABEL_BOXING_DEFAULTS8,
enabled: false,
placement: "inside-start",
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
fontSize: { $rem: 2 },
minimumFontSize: FONT_SIZE2.SMALL,
spacing: 18,
color: { $ref: "chartBackgroundColor" }
},
margin: 4,
tooltip: {
range: { $path: ["/tooltip/range", 10] }
}
}
};
var LinearGaugeModule = {
type: "series",
name: "linear-gauge",
chartType: "standalone",
enterprise: true,
dependencies: [GaugePresetModule],
version: VERSION34,
options: linearGaugeSeriesOptionsDef2,
themeTemplate: themeTemplate2,
create: (ctx) => new LinearGaugeSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/map-line/mapLineModule.ts
import { VERSION as VERSION36 } from "ag-charts-community";
import {
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS9,
MULTI_SERIES_HIGHLIGHT_STYLE as MULTI_SERIES_HIGHLIGHT_STYLE4,
SAFE_RANGE2_OPERATION as SAFE_RANGE2_OPERATION4,
SAFE_STROKE_FILL_OPERATION as SAFE_STROKE_FILL_OPERATION2
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/charts/topologyChartModule.ts
import { VERSION as VERSION35, _ModuleSupport as _ModuleSupport157 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/charts/topologyChart.ts
import { _ModuleSupport as _ModuleSupport156 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection44, Property as Property74, createId as createId7 } from "ag-charts-core";
var { Chart: Chart2, MercatorScale } = _ModuleSupport156;
function isTopologySeries(series) {
return series.type === "map-shape" || series.type === "map-line" || series.type === "map-marker" || series.type === "map-shape-background" || series.type === "map-line-background";
}
var TopologyChart = class extends Chart2 {
constructor(options, resources) {
super(options, resources);
this.xAxis = { id: createId7(_ModuleSupport156.Axis), direction: ChartAxisDirection44.X };
this.yAxis = { id: createId7(_ModuleSupport156.Axis), direction: ChartAxisDirection44.Y };
this.ctx.zoomManager.setAxes([this.xAxis, this.yAxis]);
}
getChartType() {
return "topology";
}
updateData() {
super.updateData();
const options = this.getOptions();
if (this.topology !== options.topology) {
this.topology = options.topology;
}
const { topology } = this;
for (const series of this.series) {
if (isTopologySeries(series)) {
series.setChartTopology(topology);
}
}
}
performLayout(ctx) {
const { seriesRoot, annotationRoot } = this;
const seriesRect = ctx.layoutBox.clone().shrink(this.seriesArea.getPadding());
this.seriesRect = seriesRect;
this.animationRect = seriesRect;
const mapSeries = this.series;
const combinedBbox = mapSeries.reduce((combined, series) => {
if (!series.visible)
return combined;
const bbox = series.topologyBounds;
if (bbox == null)
return combined;
if (combined == null)
return bbox;
return combined.merge(bbox);
}, void 0);
let scale;
if (combinedBbox != null) {
const { lon0, lat0, lon1, lat1 } = combinedBbox;
const domain = [
[lon0, lat0],
[lon1, lat1]
];
const bounds = MercatorScale.bounds(domain);
const { width, height } = seriesRect;
const viewBoxScale = Math.min(width / bounds.width, height / bounds.height);
const viewBoxWidth = bounds.width * viewBoxScale;
const viewBoxHeight = bounds.height * viewBoxScale;
const viewBoxOriginX = (width - viewBoxWidth) / 2;
const viewBoxOriginY = (height - viewBoxHeight) / 2;
const x0 = viewBoxOriginX;
const y0 = viewBoxOriginY;
const x1 = viewBoxOriginX + viewBoxWidth;
const y1 = viewBoxOriginY + viewBoxHeight;
const xZoom = this.ctx.zoomManager.getAxisZoom(this.xAxis.id);
const yZoom = this.ctx.zoomManager.getAxisZoom(this.yAxis.id);
const xSpan = (x1 - x0) / (xZoom.max - xZoom.min);
const xStart = x0 - xSpan * xZoom.min;
const ySpan = (y1 - y0) / (1 - yZoom.min - (1 - yZoom.max));
const yStart = y0 - ySpan * (1 - yZoom.max);
scale = new MercatorScale(domain, [
[xStart, yStart],
[xStart + xSpan, yStart + ySpan]
]);
}
for (const series of mapSeries) {
series.scale = scale;
}
const seriesVisible = this.series.some((s) => s.visible);
seriesRoot.visible = seriesVisible;
for (const group of [seriesRoot, annotationRoot]) {
group.translationX = Math.floor(seriesRect.x);
group.translationY = Math.floor(seriesRect.y);
group.setClipRect(seriesRect.clone());
}
this.ctx.layoutManager.emitLayoutComplete(ctx, {
series: { visible: seriesVisible, rect: seriesRect, paddedRect: ctx.layoutBox }
});
}
};
TopologyChart.className = "TopologyChart";
TopologyChart.type = "topology";
__decorateClass([
Property74
], TopologyChart.prototype, "topology", 2);
// packages/ag-charts-enterprise/src/charts/topologyChartModule.ts
var { topologyChartOptionsDefs } = _ModuleSupport157;
var TopologyChartModule = {
type: "chart",
name: "topology",
enterprise: true,
version: VERSION35,
options: topologyChartOptionsDefs,
create(options, resources) {
return new TopologyChart(options, resources);
}
};
// packages/ag-charts-enterprise/src/series/map-util/mapThemeDefaults.ts
import { deepClone as deepClone3, jsonWalk } from "ag-charts-core";
var MAP_THEME_DEFAULTS = {
zoom: {
axes: "xy",
anchorPointX: "pointer",
anchorPointY: "pointer",
buttons: {
// @ts-expect-error undocumented options
anchorPointX: "middle",
anchorPointY: "middle"
}
},
legend: {
enabled: false
}
};
function applyMapPalette(object) {
const clone = deepClone3(object);
jsonWalk(clone, (value) => {
if (typeof value === "object" && "$palette" in value) {
value["$mapPalette"] = value["$palette"];
delete value["$palette"];
}
});
return clone;
}
// packages/ag-charts-enterprise/src/series/map-line/mapLineSeries.ts
import { _ModuleSupport as _ModuleSupport162 } from "ag-charts-community";
import { Logger as Logger17, cachedTextMeasurer as cachedTextMeasurer8, mergeDefaults as mergeDefaults14 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/map-util/geoGeometry.ts
import { _ModuleSupport as _ModuleSupport158 } from "ag-charts-community";
import { SceneChangeDetection as SceneChangeDetection8, SceneObjectChangeDetection, objectsEqual as objectsEqual2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/map-util/lineStringUtil.ts
var delta2 = 1e-9;
function lineSegmentDistanceToPointSquared(a, b, x, y) {
const [ax, ay] = a;
const [bx, by] = b;
const abx = bx - ax;
const aby = by - ay;
const l = abx * abx + aby * aby;
let x0;
let y0;
if (Math.abs(l) < delta2) {
x0 = ax;
y0 = ay;
} else {
let t = ((x - ax) * abx + (y - ay) * aby) / l;
t = Math.max(0, Math.min(1, t));
x0 = ax + t * (bx - ax);
y0 = ay + t * (by - ay);
}
const dx2 = x - x0;
const dy2 = y - y0;
return dx2 * dx2 + dy2 * dy2;
}
function lineStringDistance(lineString, x, y) {
let minDistanceSquared = Infinity;
let p0 = lineString.at(-1);
for (const p1 of lineString) {
minDistanceSquared = Math.min(minDistanceSquared, lineSegmentDistanceToPointSquared(p0, p1, x, y));
p0 = p1;
}
return Math.sqrt(minDistanceSquared);
}
function lineStringLength(lineSegment) {
let [x0, y0] = lineSegment[0];
let totalDistance = 0;
for (let i = 1; i < lineSegment.length; i += 1) {
const [x1, y1] = lineSegment[i];
const distance = Math.hypot(x1 - x0, y1 - y0);
totalDistance += distance;
x0 = x1;
y0 = y1;
}
return totalDistance;
}
function lineStringCenter(lineSegment) {
if (lineSegment.length === 0)
return;
const targetDistance = lineStringLength(lineSegment) / 2;
let [x0, y0] = lineSegment[0];
let totalDistance = 0;
for (let i = 1; i < lineSegment.length; i += 1) {
const [x1, y1] = lineSegment[i];
const segmentDistance = Math.hypot(x1 - x0, y1 - y0);
const nextDistance = totalDistance + segmentDistance;
if (nextDistance > targetDistance) {
const ratio8 = (targetDistance - totalDistance) / segmentDistance;
const point = [x0 + (x1 - x0) * ratio8, y0 + (y1 - y0) * ratio8];
const angle = Math.atan2(y1 - y0, x1 - x0);
return { point, angle };
}
totalDistance = nextDistance;
x0 = x1;
y0 = y1;
}
}
// packages/ag-charts-enterprise/src/series/map-util/lonLatBbox.ts
var LonLatBBox = class _LonLatBBox {
constructor(lon0, lat0, lon1, lat1) {
this.lon0 = lon0;
this.lat0 = lat0;
this.lon1 = lon1;
this.lat1 = lat1;
}
extend(lon0, lat0, lon1, lat1) {
this.lon0 = Math.min(this.lon0, lon0);
this.lat0 = Math.min(this.lat0, lat0);
this.lon1 = Math.max(this.lon1, lon1);
this.lat1 = Math.max(this.lat1, lat1);
return this;
}
merge(other) {
return this.extend(other.lon0, other.lat0, other.lon1, other.lat1);
}
static extend(into, lon0, lat0, lon1, lat1) {
return into ? into.extend(lon0, lat0, lon1, lat1) : new _LonLatBBox(lon0, lat0, lon1, lat1);
}
};
// packages/ag-charts-enterprise/src/series/map-util/polygonUtil.ts
function polygonBbox(polygon, into) {
for (const coordinates of polygon) {
const [lon, lat] = coordinates;
into = LonLatBBox.extend(into, lon, lat, lon, lat);
}
return into;
}
function polygonCentroid(polygon) {
if (polygon.length === 0)
return;
let x = 0;
let y = 0;
let k = 0;
let [x0, y0] = polygon.at(-1);
for (const [x1, y1] of polygon) {
const c = x0 * y1 - x1 * y0;
k += c;
x += (x0 + x1) * c;
y += (y0 + y1) * c;
x0 = x1;
y0 = y1;
}
k *= 3;
return [x / k, y / k];
}
function polygonDistance(polygons, x, y) {
let inside = false;
let minDistanceSquared = Infinity;
for (const polygon of polygons) {
let p0 = polygon.at(-1);
let [x0, y0] = p0;
for (const p1 of polygon) {
const [x1, y1] = p1;
if (y1 > y !== y0 > y && x < (x0 - x1) * (y - y1) / (y0 - y1) + x1) {
inside = !inside;
}
minDistanceSquared = Math.min(minDistanceSquared, lineSegmentDistanceToPointSquared(p0, p1, x, y));
p0 = p1;
x0 = x1;
y0 = y1;
}
}
return (inside ? -1 : 1) * Math.sqrt(minDistanceSquared);
}
// packages/ag-charts-enterprise/src/series/map-util/geoGeometry.ts
var { Path: Path11, ExtendedPath2D: ExtendedPath2D5, BBox: BBox21 } = _ModuleSupport158;
var GeoGeometry = class extends Path11 {
constructor() {
super(...arguments);
this.projectedGeometry = void 0;
this.renderMode = 3 /* All */;
// Keep non-filled shapes separate so we don't fill them
this.strokePath = new ExtendedPath2D5();
}
computeBBox() {
if (this.dirtyPath || this.isDirtyPath()) {
this.updatePath();
this.dirtyPath = false;
}
return this.bbox?.clone();
}
updatePath() {
const { projectedGeometry } = this;
this.strokePath.clear();
this.path.clear();
this.bbox = projectedGeometry == null ? void 0 : this.drawGeometry(projectedGeometry, void 0);
}
drawPath(ctx) {
super.drawPath(ctx);
this.renderStroke(ctx, this.strokePath.getPath2D());
}
containsPoint(x, y) {
const { projectedGeometry } = this;
if (projectedGeometry == null)
return false;
if (!this.getBBox().containsPoint(x, y))
return false;
return this.geometryDistance(projectedGeometry, x, y) <= 0;
}
distanceSquared(x, y) {
const { projectedGeometry } = this;
if (projectedGeometry == null)
return Infinity;
const distance = this.geometryDistance(projectedGeometry, x, y);
return distance > 0 ? distance * distance : 0;
}
geometryDistance(geometry, x, y) {
const { renderMode, strokeWidth } = this;
const drawPolygons = (renderMode & 1 /* Polygons */) !== 0;
const drawLines = (renderMode & 2 /* Lines */) !== 0;
const minStrokeDistance = Math.max(strokeWidth / 2, 1) + 1;
switch (geometry.type) {
case "GeometryCollection":
return geometry.geometries.reduce(
(minDistance, g) => Math.min(minDistance, this.geometryDistance(g, x, y)),
Infinity
);
case "MultiPolygon":
return drawPolygons ? geometry.coordinates.reduce(
(minDistance, polygon) => Math.min(minDistance, Math.max(polygonDistance(polygon, x, y), 0)),
Infinity
) : Infinity;
case "Polygon":
return drawPolygons ? Math.max(polygonDistance(geometry.coordinates, x, y), 0) : Infinity;
case "MultiLineString":
return drawLines ? geometry.coordinates.reduce((minDistance, lineString) => {
return Math.min(
minDistance,
Math.max(lineStringDistance(lineString, x, y) - minStrokeDistance, 0)
);
}, Infinity) : Infinity;
case "LineString":
return drawLines ? Math.max(lineStringDistance(geometry.coordinates, x, y) - minStrokeDistance, 0) : Infinity;
case "MultiPoint":
case "Point":
default:
return Infinity;
}
}
shouldDrawPolygons() {
return (this.renderMode & 1 /* Polygons */) !== 0;
}
shouldDrawLines() {
return (this.renderMode & 2 /* Lines */) !== 0;
}
drawGeometryCollection(geometries, bbox) {
for (const g of geometries) {
bbox = this.drawGeometry(g, bbox);
}
return bbox;
}
drawMultiPolygon(coordinates, bbox) {
if (!this.shouldDrawPolygons())
return bbox;
for (const polygon of coordinates) {
bbox = this.drawPolygon(this.path, polygon, bbox);
}
return bbox;
}
drawSinglePolygon(coordinates, bbox) {
if (!this.shouldDrawPolygons())
return bbox;
return this.drawPolygon(this.path, coordinates, bbox);
}
drawMultiLineString(coordinates, bbox) {
if (!this.shouldDrawLines())
return bbox;
for (const lineString of coordinates) {
bbox = this.drawLineString(this.strokePath, lineString, bbox, false);
}
return bbox;
}
drawSingleLineString(coordinates, bbox) {
if (!this.shouldDrawLines())
return bbox;
return this.drawLineString(this.strokePath, coordinates, bbox, false);
}
drawGeometry(geometry, bbox) {
switch (geometry.type) {
case "GeometryCollection":
return this.drawGeometryCollection(geometry.geometries, bbox);
case "MultiPolygon":
return this.drawMultiPolygon(geometry.coordinates, bbox);
case "Polygon":
return this.drawSinglePolygon(geometry.coordinates, bbox);
case "MultiLineString":
return this.drawMultiLineString(geometry.coordinates, bbox);
case "LineString":
return this.drawSingleLineString(geometry.coordinates, bbox);
case "Point":
case "MultiPoint":
return bbox;
}
}
drawPolygon(path, polygons, bbox) {
if (polygons.length < 1)
return bbox;
bbox = this.drawLineString(path, polygons[0], bbox, true);
for (let i = 1; i < polygons.length; i += 1) {
const enclave = polygons[i];
this.drawLineString(path, enclave, void 0, true);
}
return bbox;
}
drawLineString(path, coordinates, bbox, isClosed) {
if (coordinates.length < 2)
return bbox;
const end = isClosed ? coordinates.length - 1 : coordinates.length;
for (let i = 0; i < end; i += 1) {
const [x, y] = coordinates[i];
if (i === 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
if (bbox == null) {
bbox = new BBox21(x, y, 0, 0);
} else {
const { x: x0, y: y0 } = bbox;
const x1 = x0 + bbox.width;
const y1 = y0 + bbox.height;
bbox.x = Math.min(x0, x);
bbox.y = Math.min(y0, y);
bbox.width = Math.max(x1, x) - bbox.x;
bbox.height = Math.max(y1, y) - bbox.y;
}
}
if (isClosed) {
path.closePath();
}
return bbox;
}
};
__decorateClass([
SceneObjectChangeDetection({ equals: objectsEqual2 })
], GeoGeometry.prototype, "projectedGeometry", 2);
__decorateClass([
SceneChangeDetection8()
], GeoGeometry.prototype, "renderMode", 2);
// packages/ag-charts-enterprise/src/series/map-util/geometryUtil.ts
import "ag-charts-community";
import "ag-charts-core";
function calculatePolygonArea(polygon) {
const bbox = polygonBbox(polygon[0], void 0);
if (bbox == null)
return 0;
return Math.abs(bbox.lat1 - bbox.lat0) * Math.abs(bbox.lon1 - bbox.lon0);
}
function findLargestByMetric(items, metric) {
let maxValue;
let maxItem;
for (const item of items) {
const value = metric(item);
if (value == null)
continue;
if (maxValue == null || value > maxValue) {
maxValue = value;
maxItem = item;
}
}
return maxItem;
}
function geometryBbox(geometry, into) {
if (geometry.bbox != null) {
const [lon0, lat0, lon1, lat1] = geometry.bbox;
into = LonLatBBox.extend(into, lon0, lat0, lon1, lat1);
return into;
}
switch (geometry.type) {
case "GeometryCollection":
for (const g of geometry.geometries) {
into = geometryBbox(g, into);
}
break;
case "MultiPolygon":
for (const c of geometry.coordinates) {
if (c.length > 0) {
into = polygonBbox(c[0], into);
}
}
break;
case "Polygon":
if (geometry.coordinates.length > 0) {
into = polygonBbox(geometry.coordinates[0], into);
}
break;
case "MultiLineString":
for (const c of geometry.coordinates) {
into = polygonBbox(c, into);
}
break;
case "LineString":
into = polygonBbox(geometry.coordinates, into);
break;
case "MultiPoint":
for (const p of geometry.coordinates) {
const [lon, lat] = p;
into = LonLatBBox.extend(into, lon, lat, lon, lat);
}
break;
case "Point": {
const [lon, lat] = geometry.coordinates;
into = LonLatBBox.extend(into, lon, lat, lon, lat);
break;
}
}
return into;
}
function largestPolygon(geometry) {
switch (geometry.type) {
case "Polygon":
return geometry.coordinates;
case "MultiPolygon":
return findLargestByMetric(geometry.coordinates, calculatePolygonArea);
case "GeometryCollection": {
const polygons = geometry.geometries.map(largestPolygon).filter((p) => p != null);
return findLargestByMetric(polygons, calculatePolygonArea);
}
case "MultiLineString":
case "LineString":
case "MultiPoint":
case "Point":
return;
}
}
function largestLineString(geometry) {
switch (geometry.type) {
case "LineString":
return geometry.coordinates;
case "MultiLineString":
return findLargestByMetric(geometry.coordinates, lineStringLength);
case "GeometryCollection": {
const lineStrings = geometry.geometries.map(largestLineString).filter((l) => l != null);
return findLargestByMetric(lineStrings, lineStringLength);
}
case "MultiPolygon":
case "Polygon":
case "MultiPoint":
case "Point":
return;
}
}
function containsType(geometry, type) {
if (geometry == null)
return false;
switch (geometry.type) {
case "GeometryCollection":
return geometry.geometries.some((g) => containsType(g, type));
case "MultiPolygon":
case "Polygon":
return (type & 1 /* Polygon */) !== 0;
case "MultiLineString":
case "LineString":
return (type & 2 /* LineString */) !== 0;
case "MultiPoint":
case "Point":
return (type & 4 /* Point */) !== 0;
}
}
function projectGeometry(geometry, scale) {
switch (geometry.type) {
case "GeometryCollection":
return {
type: "GeometryCollection",
geometries: geometry.geometries.map((g) => projectGeometry(g, scale))
};
case "Polygon":
return {
type: "Polygon",
coordinates: projectPolygon(geometry.coordinates, scale)
};
case "MultiPolygon":
return {
type: "MultiPolygon",
coordinates: projectMultiPolygon(geometry.coordinates, scale)
};
case "MultiLineString":
return {
type: "MultiLineString",
coordinates: projectPolygon(geometry.coordinates, scale)
};
case "LineString":
return {
type: "LineString",
coordinates: projectLineString(geometry.coordinates, scale)
};
case "MultiPoint":
return {
type: "MultiPoint",
coordinates: projectLineString(geometry.coordinates, scale)
};
case "Point":
return {
type: "Point",
coordinates: scale.convert(geometry.coordinates)
};
}
}
function projectMultiPolygon(multiPolygon, scale) {
return multiPolygon.map((polygon) => projectPolygon(polygon, scale));
}
function projectPolygon(polygon, scale) {
return polygon.map((lineString) => projectLineString(lineString, scale));
}
function projectLineString(lineString, scale) {
return lineString.map((lonLat) => scale.convert(lonLat));
}
// packages/ag-charts-enterprise/src/series/map-util/mapUtil.ts
function prepareMapMarkerAnimationFunctions() {
const fromFn = (marker, _datum, status) => {
if (status === "removed") {
return { scalingX: 1, scalingY: 1 };
} else if (marker.previousDatum == null) {
return { scalingX: 0, scalingY: 0 };
}
return { scalingX: marker.scalingX, scalingY: marker.scalingY };
};
const toFn = (_marker, _datum, status) => {
if (status === "removed") {
return { scalingX: 0, scalingY: 0 };
}
return { scalingX: 1, scalingY: 1 };
};
return { fromFn, toFn };
}
function findFocusedGeoGeometry(series, opts) {
const datum = series.contextNodeData?.nodeData[opts.datumIndex];
if (datum === void 0)
return void 0;
for (const node of series.datumSelection.nodes()) {
if (node.datum === datum) {
return node;
}
}
return void 0;
}
// packages/ag-charts-enterprise/src/series/map-util/topologySeries.ts
import { _ModuleSupport as _ModuleSupport160 } from "ag-charts-community";
var TopologySeriesProperties = class extends _ModuleSupport160.SeriesProperties {
};
var TopologySeries = class extends _ModuleSupport160.DataModelSeries {
constructor(options) {
super(options);
this.cleanup.register(
this.ctx.eventsHub.on("data:update", () => {
}),
this.ctx.eventsHub.on("legend:item-click", (event) => {
this.onLegendItemClick(event);
}),
this.ctx.eventsHub.on("legend:item-double-click", (event) => {
this.onLegendItemDoubleClick(event);
})
);
}
getSeriesDomain() {
return { domain: [Number.NaN, Number.NaN] };
}
getSeriesRange() {
return [Number.NaN, Number.NaN];
}
getHighlightedDatum() {
let highlightedDatum = this.ctx.highlightManager?.getActiveHighlight();
const { legendItemName } = this.properties;
const matchingLegendItemName = legendItemName != null && highlightedDatum?.datum == null && legendItemName === highlightedDatum?.legendItemName;
if (highlightedDatum != null && (highlightedDatum.series !== this && !matchingLegendItemName || highlightedDatum.datum == null)) {
highlightedDatum = void 0;
}
return highlightedDatum;
}
};
// packages/ag-charts-enterprise/src/series/map-line/mapLineSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport161 } from "ag-charts-community";
import { Property as Property75 } from "ag-charts-core";
var { SeriesProperties: SeriesProperties3, makeSeriesTooltip: makeSeriesTooltip12, Label: Label10 } = _ModuleSupport161;
var MapLineSeriesProperties = class extends SeriesProperties3 {
constructor() {
super(...arguments);
this.topology = void 0;
this.idKey = "";
this.topologyIdKey = "name";
this.idName = void 0;
this.labelKey = void 0;
this.labelName = void 0;
this.colorRange = void 0;
this.maxStrokeWidth = void 0;
this.stroke = "black";
this.strokeOpacity = 1;
this.strokeWidth = 0;
this.lineDash = [0];
this.lineDashOffset = 0;
this.label = new Label10();
this.tooltip = makeSeriesTooltip12();
}
getStyle() {
const { stroke: stroke3, strokeOpacity, strokeWidth, lineDash, lineDashOffset } = this;
return {
stroke: stroke3,
strokeOpacity,
strokeWidth,
lineDash,
lineDashOffset,
opacity: 1
};
}
};
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "topology", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "title", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "legendItemName", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "idKey", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "topologyIdKey", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "idName", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "labelKey", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "labelName", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "sizeKey", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "sizeName", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "colorKey", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "colorName", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "sizeDomain", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "colorRange", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "maxStrokeWidth", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "stroke", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "label", 2);
__decorateClass([
Property75
], MapLineSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/map-line/mapLineSeries.ts
var {
getMissCount: getMissCount2,
getLabelStyles: getLabelStyles2,
createDatumId: createDatumId11,
SeriesNodePickMode: SeriesNodePickMode9,
valueProperty: valueProperty11,
ColorScale: ColorScale2,
LinearScale: LinearScale5,
Selection: Selection8,
Text: Text4,
Transformable: Transformable3
} = _ModuleSupport162;
var MapLineSeries = class extends TopologySeries {
constructor(moduleCtx) {
super({
moduleCtx,
categoryKey: void 0,
propertyKeys: {
size: ["colorKey"],
color: ["colorKey"],
label: ["labelKey"]
},
propertyNames: {
size: ["sizeName"],
color: ["colorName"],
label: ["labelName"]
},
pickModes: [SeriesNodePickMode9.EXACT_SHAPE_MATCH, SeriesNodePickMode9.NEAREST_NODE],
usesPlacedLabels: true
});
this.properties = new MapLineSeriesProperties();
this._chartTopology = void 0;
this.colorScale = new ColorScale2();
this.sizeScale = new LinearScale5();
this.datumSelection = Selection8.select(
this.contentGroup,
() => this.nodeFactory()
);
this.labelSelection = Selection8.select(this.labelGroup, Text4);
this.highlightDatumSelection = Selection8.select(
this.highlightNodeGroup,
() => this.nodeFactory()
);
this.highlightLabelSelection = Selection8.select(this.highlightLabelGroup, Text4);
this.placedLabelData = [];
this._previousDatumMidPoint = void 0;
}
getNodeData() {
return this.contextNodeData?.nodeData;
}
get topology() {
return this.properties.topology ?? this._chartTopology;
}
get hasData() {
return super.hasData && this.topology != null;
}
renderToOffscreenCanvas() {
return true;
}
setZIndex(zIndex) {
super.setZIndex(zIndex);
this.contentGroup.zIndex = [1 /* ShapeLine */, zIndex];
this.highlightGroup.zIndex = [4 /* ShapeLineHighlight */, zIndex];
return true;
}
setChartTopology(topology) {
this._chartTopology = topology;
if (this.topology === topology) {
this.nodeDataRefresh = true;
}
}
isLabelEnabled() {
return this.properties.labelKey != null && this.properties.label.enabled;
}
nodeFactory() {
const geoGeometry = new GeoGeometry();
geoGeometry.renderMode = 2 /* Lines */;
geoGeometry.lineJoin = "round";
geoGeometry.lineCap = "round";
return geoGeometry;
}
async processData(dataController) {
if (this.data == null)
return;
const { data, topology, sizeScale, colorScale } = this;
const { topologyIdKey, idKey, sizeKey, colorKey, labelKey, sizeDomain, colorRange } = this.properties;
const featureById = /* @__PURE__ */ new Map();
for (const feature of topology?.features.values() ?? []) {
const property = feature.properties?.[topologyIdKey];
if (property == null || !containsType(feature.geometry, 2 /* LineString */))
continue;
featureById.set(property, feature);
}
const sizeScaleType = this.sizeScale.type;
const colorScaleType = this.colorScale.type;
const mercatorScaleType = this.scale?.type;
const { dataModel, processedData } = await this.requestDataModel(dataController, data, {
props: [
valueProperty11(idKey, mercatorScaleType, { id: "idValue", includeProperty: false }),
valueProperty11(idKey, mercatorScaleType, {
id: "featureValue",
includeProperty: false,
processor: () => (datum) => featureById.get(datum)
}),
...labelKey == null ? [] : [valueProperty11(labelKey, "category", { id: "labelValue" })],
...sizeKey == null ? [] : [valueProperty11(sizeKey, sizeScaleType, { id: "sizeValue" })],
...colorKey == null ? [] : [valueProperty11(colorKey, colorScaleType, { id: "colorValue" })]
]
});
const featureValues = dataModel.resolveColumnById(this, `featureValue`, processedData);
this.topologyBounds = featureValues.reduce((current, feature) => {
const geometry = feature?.geometry;
if (geometry == null)
return current;
return geometryBbox(geometry, current);
}, void 0);
if (sizeKey != null) {
const sizeIdx = dataModel.resolveProcessedDataIndexById(this, `sizeValue`);
const processedSize = processedData.domain.values[sizeIdx] ?? [];
sizeScale.domain = sizeDomain ?? processedSize;
}
if (colorRange != null && this.isColorScaleValid()) {
const colorKeyIdx = dataModel.resolveProcessedDataIndexById(this, "colorValue");
colorScale.domain = processedData.domain.values[colorKeyIdx];
colorScale.range = colorRange;
colorScale.update();
}
if (topology == null) {
Logger17.warnOnce(`no topology was provided for [MapLineSeries]; nothing will be rendered.`);
}
}
isColorScaleValid() {
const { colorKey } = this.properties;
if (!colorKey) {
return false;
}
const { dataModel, processedData } = this;
if (!dataModel || !processedData) {
return false;
}
const colorIdx = dataModel.resolveProcessedDataIndexById(this, "colorValue");
const dataCount = processedData.input.count;
const missCount = getMissCount2(this, processedData.defs.values[colorIdx].missing);
const colorDataMissing = dataCount === 0 || dataCount === missCount;
return !colorDataMissing;
}
getLabelDatum(datum, datumIndex, idValue, labelValue, projectedGeometry, measurer3) {
if (labelValue == null || projectedGeometry == null || idValue == null)
return;
const lineString = largestLineString(projectedGeometry);
if (lineString == null)
return;
const { idKey, idName, sizeKey, sizeName, colorKey, colorName, labelKey, labelName, label } = this.properties;
if (labelKey == null || !label.enabled)
return;
const labelText = this.getLabelText(
labelValue,
datum,
labelKey,
"label",
[],
label,
{
value: labelValue,
datum,
idKey,
idName,
sizeKey,
sizeName,
colorKey,
colorName,
labelKey,
labelName
}
);
if (labelText == null)
return;
const labelSize = measurer3.measureLines(String(labelText));
const labelCenter = lineStringCenter(lineString);
if (labelCenter == null)
return;
const [x, y] = labelCenter.point;
const { width, height } = labelSize;
return {
point: { x, y, size: 0 },
label: { width, height, text: labelText },
anchor: void 0,
placement: void 0,
datumIndex,
idValue
};
}
resolveColumn(key, columnId, processedData) {
if (key == null || this.dataModel == null)
return void 0;
return this.dataModel.resolveColumnById(this, columnId, processedData);
}
resolveLineDataColumns(processedData) {
const { sizeKey, colorKey, labelKey } = this.properties;
return {
idValues: this.dataModel.resolveColumnById(this, "idValue", processedData),
featureValues: this.dataModel.resolveColumnById(this, "featureValue", processedData),
labelValues: this.resolveColumn(labelKey, "labelValue", processedData),
sizeValues: this.resolveColumn(sizeKey, "sizeValue", processedData),
colorValues: this.resolveColumn(colorKey, "colorValue", processedData)
};
}
prepareProjectedLineGeometries(idValues, featureValues, processedData) {
const projectedGeometries = /* @__PURE__ */ new Map();
for (const [datumIndex] of processedData.dataSources.get(this.id)?.data.entries() ?? []) {
const id = idValues[datumIndex];
const geometry = featureValues[datumIndex]?.geometry;
const projectedGeometry = geometry != null && this.scale != null ? projectGeometry(geometry, this.scale) : void 0;
if (id != null && projectedGeometry != null) {
projectedGeometries.set(id, projectedGeometry);
}
}
return projectedGeometries;
}
warnMissingGeometries(missingGeometries) {
if (missingGeometries.length === 0)
return;
const missingGeometriesCap = 10;
if (missingGeometries.length > missingGeometriesCap) {
const excessItems = missingGeometries.length - missingGeometriesCap;
missingGeometries.length = missingGeometriesCap;
missingGeometries.push(`(+${excessItems} more)`);
}
Logger17.warnOnce(`some data items do not have matches in the provided topology`, missingGeometries);
}
createNodeData() {
const { id: seriesId, dataModel, processedData, sizeScale, properties } = this;
const { label, legendItemName, colorKey } = properties;
if (dataModel == null || processedData == null)
return;
if (!this.visible) {
return { itemId: seriesId, nodeData: [], labelData: [] };
}
const columns = this.resolveLineDataColumns(processedData);
const maxStrokeWidth = properties.maxStrokeWidth ?? properties.strokeWidth;
sizeScale.range = [Math.min(properties.strokeWidth, maxStrokeWidth), maxStrokeWidth];
const measurer3 = cachedTextMeasurer8(label);
const projectedGeometries = this.prepareProjectedLineGeometries(
columns.idValues,
columns.featureValues,
processedData
);
const nodeData = [];
const labelData = [];
const missingGeometries = [];
const rawData = processedData.dataSources.get(this.id)?.data ?? [];
for (const [datumIndex, datum] of rawData.entries()) {
const dataValues = {
idValue: columns.idValues[datumIndex],
colorValue: columns.colorValues?.[datumIndex],
sizeValue: columns.sizeValues?.[datumIndex],
labelValue: columns.labelValues?.[datumIndex]
};
const projectedGeometry = projectedGeometries.get(dataValues.idValue);
if (projectedGeometry == null) {
missingGeometries.push(dataValues.idValue);
}
if (colorKey != null && dataValues.colorValue == null) {
continue;
}
const labelDatum = this.getLabelDatum(
datum,
datumIndex,
dataValues.idValue,
dataValues.labelValue,
projectedGeometry,
measurer3
);
if (labelDatum != null) {
labelData.push(labelDatum);
}
nodeData.push({
series: this,
datum,
datumIndex,
...dataValues,
projectedGeometry,
legendItemName,
style: this.getItemStyle(
{ datumIndex, datum, colorValue: dataValues.colorValue, sizeValue: dataValues.sizeValue },
false
)
});
}
this.warnMissingGeometries(missingGeometries);
return {
itemId: seriesId,
nodeData,
labelData
};
}
updateSelections() {
if (this.nodeDataRefresh) {
this.contextNodeData = this.createNodeData();
this.nodeDataRefresh = false;
}
}
update() {
const { datumSelection, highlightDatumSelection } = this;
this.updateSelections();
this.contentGroup.visible = this.visible;
this.labelGroup.visible = this.visible;
const drawingMode = this.ctx.chartService.highlight?.drawingMode ?? "overlay";
const highlightedDatum = this.getHighlightedDatum();
const nodeData = this.contextNodeData?.nodeData ?? [];
this.datumSelection = this.updateDatumSelection({ nodeData, datumSelection });
this.updateDatumStyles({ datumSelection, isHighlight: false });
this.updateDatumNodes({ datumSelection, isHighlight: false, drawingMode: "overlay" });
this.highlightDatumSelection = this.updateDatumSelection({
nodeData: highlightedDatum == null ? [] : [highlightedDatum],
datumSelection: highlightDatumSelection
});
this.updateDatumStyles({ datumSelection: highlightDatumSelection, isHighlight: true });
this.updateDatumNodes({ datumSelection: highlightDatumSelection, isHighlight: true, drawingMode });
this.updateLabelNodes({ labelSelection: this.labelSelection, isHighlight: false });
this.updateHighlightLabelSelection(highlightedDatum);
}
updateDatumSelection(opts) {
return opts.datumSelection.update(opts.nodeData, void 0, (datum) => createDatumId11(datum.idValue));
}
getItemStyle({ datumIndex = 0, datum, colorValue, sizeValue }, isHighlight) {
const { properties, colorScale, sizeScale } = this;
const { colorRange, itemStyler } = properties;
const baseStyle = properties.getStyle();
if (colorValue != null) {
baseStyle.stroke = this.isColorScaleValid() ? colorScale.convert(colorValue) : colorRange?.[0] ?? properties.stroke;
}
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
const style = mergeDefaults14(highlightStyle, baseStyle);
if (sizeValue != null) {
style.strokeWidth = sizeScale.convert(sizeValue, { clamp: true });
}
let overrides;
if (itemStyler != null) {
overrides = this.cachedDatumCallback(createDatumId11(datumIndex, isHighlight ? "highlight" : "node"), () => {
const params = this.makeItemStylerParams(datum, datumIndex, isHighlight, style);
return this.callWithContext(itemStyler, params);
});
}
return overrides ? mergeDefaults14(style, overrides) : style;
}
makeItemStylerParams(datum, datumIndex, isHighlight, style) {
const { id: seriesId } = this;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightState = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
return {
seriesId,
datum,
highlightState,
...style
};
}
updateDatumStyles({
datumSelection,
isHighlight
}) {
datumSelection.each((_, nodeDatum) => {
nodeDatum.style = this.getItemStyle(nodeDatum, isHighlight);
});
}
updateDatumNodes({
datumSelection,
drawingMode
}) {
datumSelection.each((geoGeometry, nodeDatum) => {
const { projectedGeometry, style } = nodeDatum;
if (projectedGeometry == null) {
geoGeometry.visible = false;
geoGeometry.projectedGeometry = void 0;
return;
}
geoGeometry.visible = true;
geoGeometry.projectedGeometry = projectedGeometry;
geoGeometry.setProperties(style);
geoGeometry.drawingMode = drawingMode;
});
}
updatePlacedLabelData(labelData) {
this.placedLabelData = labelData;
this.labelSelection = this.labelSelection.update(labelData, (text2) => {
text2.pointerEvents = _ModuleSupport162.PointerEvents.None;
});
this.updateLabelNodes({ labelSelection: this.labelSelection, isHighlight: false });
this.updateHighlightLabelSelection();
}
updateLabelNodes({
isHighlight,
labelSelection
}) {
const { properties } = this;
const activeHighlight = this.getHighlightedDatum();
labelSelection.each((label, placedLabel) => {
const { x, y, width, height, text: text2, datum: labelDatum } = placedLabel;
const style = getLabelStyles2(this, void 0, properties, properties.label, isHighlight, activeHighlight);
const { color: fill, fontStyle, fontWeight, fontSize, fontFamily } = style;
label.visible = true;
label.x = x + width / 2;
label.y = y + height / 2;
label.text = text2;
label.fill = fill;
label.fontStyle = fontStyle;
label.fontWeight = fontWeight;
label.fontSize = fontSize;
label.fontFamily = fontFamily;
label.textAlign = "center";
label.textBaseline = "middle";
const datumIndex = labelDatum?.datumIndex;
label.fillOpacity = this.getHighlightStyle(isHighlight, datumIndex).opacity ?? 1;
label.setBoxing(style);
});
}
updateHighlightLabelSelection(highlightedDatum = this.getHighlightedDatum()) {
const highlightId = highlightedDatum?.idValue;
const highlightLabels = highlightId == null || !this.isLabelEnabled() ? [] : this.placedLabelData.filter((label) => label.datum.idValue === highlightId);
this.highlightLabelSelection = this.highlightLabelSelection.update(highlightLabels);
if (highlightLabels.length === 0) {
this.highlightLabelSelection.cleanup();
}
this.updateLabelNodes({ labelSelection: this.highlightLabelSelection, isHighlight: true });
}
resetAnimation() {
}
getLabelData() {
if (!this.isLabelEnabled())
return [];
return this.contextNodeData?.labelData ?? [];
}
pickNodeClosestDatum({ x, y }) {
let minDistanceSquared = Infinity;
let minDatum;
this.datumSelection.each((node, datum) => {
const distanceSquared = node.distanceSquared(x, y);
if (distanceSquared < minDistanceSquared) {
minDistanceSquared = distanceSquared;
minDatum = datum;
}
});
return minDatum == null ? void 0 : { datum: minDatum, distance: Math.sqrt(minDistanceSquared) };
}
datumMidPoint(datum) {
const { _previousDatumMidPoint } = this;
if (_previousDatumMidPoint?.datum === datum) {
return _previousDatumMidPoint.point;
}
const projectedGeometry = datum.projectedGeometry;
const lineString = projectedGeometry == null ? void 0 : largestLineString(projectedGeometry);
const center = lineString == null ? void 0 : lineStringCenter(lineString)?.point;
const point = center == null ? void 0 : { x: center[0], y: center[1] };
this._previousDatumMidPoint = { datum, point };
return point;
}
legendItemSymbol(datumIndex) {
const { dataModel, processedData, properties } = this;
const { strokeWidth, strokeOpacity, lineDash } = properties;
let { stroke: stroke3 } = properties;
if (datumIndex != null && this.isColorScaleValid()) {
const colorValues = dataModel.resolveColumnById(this, "colorValue", processedData);
const colorValue = colorValues[datumIndex];
if (colorValue != null) {
stroke3 = this.colorScale.convert(colorValue);
}
}
return {
marker: {
fill: void 0,
fillOpacity: 0,
stroke: void 0,
strokeWidth: 0,
strokeOpacity: 0,
lineDash: [0],
lineDashOffset: 0,
enabled: false
},
line: {
enabled: true,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash
}
};
}
getLegendData(legendType) {
const { processedData, dataModel } = this;
if (processedData == null || dataModel == null)
return [];
const { id: seriesId, visible } = this;
const { title, legendItemName, idKey, idName, colorKey, colorRange, showInLegend } = this.properties;
if (legendType === "gradient" && colorKey != null && colorRange != null) {
const colorDomain = processedData.domain.values[dataModel.resolveProcessedDataIndexById(this, "colorValue")];
const legendDatum = {
legendType: "gradient",
enabled: visible,
seriesId,
series: this.getFormatterContext("color"),
colorRange,
colorDomain
};
return [legendDatum];
} else if (legendType === "category") {
const legendDatum = {
legendType: "category",
id: seriesId,
itemId: seriesId,
seriesId,
enabled: visible,
label: { text: legendItemName ?? title ?? idName ?? idKey },
symbol: this.legendItemSymbol(),
legendItemName,
hideInLegend: !showInLegend
};
return [legendDatum];
} else {
return [];
}
}
getTooltipContent(datumIndex) {
const {
id: seriesId,
dataModel,
processedData,
properties,
ctx: { formatManager }
} = this;
const {
idKey,
idName,
colorKey,
colorName,
sizeKey,
sizeName,
labelKey,
labelName,
title,
legendItemName,
tooltip
} = properties;
if (!dataModel || !processedData)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const idValues = dataModel.resolveColumnById(this, `idValue`, processedData);
const sizeValue = sizeKey == null ? void 0 : dataModel.resolveColumnById(this, `sizeValue`, processedData)[datumIndex];
const colorValue = colorKey == null ? void 0 : dataModel.resolveColumnById(this, `colorValue`, processedData)[datumIndex];
if (colorKey != null && colorValue == null) {
return;
}
const data = [];
if (this.isLabelEnabled() && labelKey != null && labelKey !== idKey) {
const labelValue = dataModel.resolveColumnById(this, `labelValue`, processedData)[datumIndex];
const content = formatManager.format(this.callWithContext.bind(this), {
type: "category",
value: labelValue,
datum,
seriesId,
legendItemName,
key: labelKey,
source: "tooltip",
property: "label",
domain: [],
boundSeries: this.getFormatterContext("label")
});
data.push({ label: labelName, fallbackLabel: labelKey, value: content ?? labelValue });
}
if (sizeValue != null && sizeKey != null) {
const domain = dataModel.getDomain(this, `sizeValue`, "value", processedData).domain;
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: sizeValue,
datum,
seriesId,
legendItemName,
key: sizeKey,
source: "tooltip",
property: "size",
domain,
boundSeries: this.getFormatterContext("size"),
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: sizeName, fallbackLabel: sizeKey, value: content ?? String(sizeValue) });
}
if (colorValue != null && colorKey != null) {
const domain = dataModel.getDomain(this, `colorValue`, "value", processedData).domain;
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: colorValue,
datum,
seriesId,
legendItemName,
key: colorKey,
source: "tooltip",
property: "color",
domain,
boundSeries: this.getFormatterContext("color"),
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: colorName, fallbackLabel: colorKey, value: content ?? String(colorValue) });
}
const format = this.getItemStyle({ datumIndex, datum, colorValue, sizeValue }, false);
return this.formatTooltipWithContext(
tooltip,
{
heading: idValues[datumIndex],
title: title ?? legendItemName,
symbol: this.legendItemSymbol(datumIndex),
data
},
{
seriesId,
datum,
title,
idKey,
idName,
colorKey,
colorName,
sizeKey,
sizeName,
labelKey,
labelName,
...format
}
);
}
computeFocusBounds(opts) {
const geometry = findFocusedGeoGeometry(this, opts);
return geometry ? Transformable3.toCanvas(this.contentGroup, geometry.getBBox()) : void 0;
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.label.itemStyler != null;
}
};
MapLineSeries.className = "MapLineSeries";
MapLineSeries.type = "map-line";
// packages/ag-charts-enterprise/src/series/map-line/mapLineSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport163 } from "ag-charts-community";
import {
and as and3,
arrayLength as arrayLength2,
arrayOf as arrayOf3,
color as color4,
commonSeriesOptionsDefs as commonSeriesOptionsDefs11,
constant as constant11,
geoJson,
required as required11,
string as string13,
undocumented as undocumented11,
without as without6
} from "ag-charts-core";
var { mapLineSeriesThemeableOptionsDef } = _ModuleSupport163;
var mapLineSeriesOptionsDef = {
...without6(commonSeriesOptionsDefs11, ["highlightStyle", "highlight"]),
...mapLineSeriesThemeableOptionsDef,
type: required11(constant11("map-line")),
idKey: required11(string13),
sizeKey: string13,
colorKey: string13,
labelKey: string13,
idName: string13,
sizeName: string13,
colorName: string13,
labelName: string13,
topology: geoJson,
topologyIdKey: string13,
legendItemName: string13,
title: string13
};
mapLineSeriesOptionsDef.colorRange = undocumented11(and3(arrayOf3(color4), arrayLength2(1)));
// packages/ag-charts-enterprise/src/series/map-line/mapLineModule.ts
var MapLineSeriesModule = {
type: "series",
name: "map-line",
chartType: "topology",
enterprise: true,
version: VERSION36,
dependencies: [TopologyChartModule],
options: mapLineSeriesOptionsDef,
themeTemplate: {
...MAP_THEME_DEFAULTS,
series: {
stroke: applyMapPalette(SAFE_STROKE_FILL_OPERATION2),
colorRange: {
$if: [
{ $eq: [{ $mapPalette: "type" }, "inbuilt"] },
{ $mapPalette: "divergingColors" },
applyMapPalette(SAFE_RANGE2_OPERATION4)
]
},
strokeWidth: 1,
maxStrokeWidth: 3,
lineDash: [0],
lineDashOffset: 0,
label: {
...LABEL_BOXING_DEFAULTS9,
enabled: true,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "textColor" }
},
highlight: applyMapPalette(MULTI_SERIES_HIGHLIGHT_STYLE4)
},
tooltip: {
range: "exact"
}
},
create: (ctx) => new MapLineSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/map-line-background/mapLineBackgroundModule.ts
import { VERSION as VERSION37 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/series/map-line-background/mapLineBackgroundSeries.ts
import { _ModuleSupport as _ModuleSupport165 } from "ag-charts-community";
import { Logger as Logger18 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/map-line-background/mapLineBackgroundSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport164 } from "ag-charts-community";
import { Property as Property76 } from "ag-charts-core";
var { SeriesProperties: SeriesProperties4, makeSeriesTooltip: makeSeriesTooltip13 } = _ModuleSupport164;
var MapLineBackgroundSeriesProperties = class extends SeriesProperties4 {
constructor() {
super(...arguments);
this.topology = void 0;
this.stroke = "black";
this.strokeOpacity = 1;
this.strokeWidth = 0;
this.lineDash = [0];
this.lineDashOffset = 0;
this.tooltip = makeSeriesTooltip13();
}
};
__decorateClass([
Property76
], MapLineBackgroundSeriesProperties.prototype, "topology", 2);
__decorateClass([
Property76
], MapLineBackgroundSeriesProperties.prototype, "stroke", 2);
__decorateClass([
Property76
], MapLineBackgroundSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property76
], MapLineBackgroundSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property76
], MapLineBackgroundSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
Property76
], MapLineBackgroundSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property76
], MapLineBackgroundSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/map-line-background/mapLineBackgroundSeries.ts
var { createDatumId: createDatumId12, Group: Group13, Selection: Selection9, PointerEvents: PointerEvents6 } = _ModuleSupport165;
var MapLineBackgroundSeries = class extends TopologySeries {
constructor(moduleCtx) {
super({
moduleCtx,
categoryKey: void 0,
pickModes: []
});
this.properties = new MapLineBackgroundSeriesProperties();
this._chartTopology = void 0;
this.itemGroup = this.contentGroup.appendChild(new Group13({ name: "itemGroup" }));
this.datumSelection = Selection9.select(
this.itemGroup,
() => this.nodeFactory()
);
this.itemGroup.pointerEvents = PointerEvents6.None;
}
getNodeData() {
return this.contextNodeData?.nodeData;
}
get topology() {
return this.properties.topology ?? this._chartTopology;
}
get focusable() {
return false;
}
setOptionsData() {
}
setChartData() {
}
get hasData() {
return false;
}
renderToOffscreenCanvas() {
return true;
}
setChartTopology(topology) {
this._chartTopology = topology;
if (this.topology === topology) {
this.nodeDataRefresh = true;
}
}
setZIndex(zIndex) {
super.setZIndex(zIndex);
this.contentGroup.zIndex = [0 /* ShapeLineBackground */, zIndex, 0];
this.highlightGroup.zIndex = [0 /* ShapeLineBackground */, zIndex, 1];
return true;
}
nodeFactory() {
const geoGeometry = new GeoGeometry();
geoGeometry.renderMode = 2 /* Lines */;
geoGeometry.lineJoin = "round";
geoGeometry.lineCap = "round";
geoGeometry.pointerEvents = PointerEvents6.None;
return geoGeometry;
}
processData() {
const { topology } = this;
this.topologyBounds = topology?.features.reduce((current, feature) => {
const geometry = feature.geometry;
if (geometry == null)
return current;
return geometryBbox(geometry, current);
}, void 0);
if (topology == null) {
Logger18.warnOnce(`no topology was provided for [MapShapeBackgroundSeries]; nothing will be rendered.`);
}
}
createNodeData() {
const { id: seriesId, topology, scale, properties } = this;
if (topology == null)
return;
const { stroke: stroke3, strokeOpacity, lineDash, lineDashOffset, strokeWidth } = properties;
const nodeData = [];
const labelData = [];
for (const [index, feature] of topology.features.entries()) {
const { geometry } = feature;
const projectedGeometry = geometry != null && scale != null ? projectGeometry(geometry, scale) : void 0;
if (projectedGeometry == null)
continue;
nodeData.push({
series: this,
datum: feature,
datumIndex: 0,
index,
projectedGeometry,
style: { stroke: stroke3, strokeOpacity, lineDash, lineDashOffset, strokeWidth }
});
}
return {
itemId: seriesId,
nodeData,
labelData
};
}
updateSelections() {
if (this.nodeDataRefresh) {
this.contextNodeData = this.createNodeData();
this.nodeDataRefresh = false;
}
}
update() {
const { datumSelection } = this;
this.updateSelections();
this.contentGroup.visible = this.visible;
this.labelGroup.visible = this.visible;
const { nodeData = [] } = this.contextNodeData ?? {};
this.datumSelection = this.updateDatumSelection({ nodeData, datumSelection });
this.updateDatumNodes({ datumSelection });
}
updateDatumSelection(opts) {
return opts.datumSelection.update(opts.nodeData, void 0, (datum) => createDatumId12(datum.index));
}
updateDatumNodes(opts) {
const { datumSelection } = opts;
datumSelection.each((geoGeometry, datum) => {
const { projectedGeometry } = datum;
if (projectedGeometry == null) {
geoGeometry.visible = false;
geoGeometry.projectedGeometry = void 0;
return;
}
geoGeometry.visible = true;
geoGeometry.projectedGeometry = projectedGeometry;
geoGeometry.setProperties(datum.style);
});
}
resetAnimation() {
}
getLegendData() {
return [];
}
getTooltipContent(_seriesDatum) {
return;
}
computeFocusBounds(_opts) {
return void 0;
}
hasItemStylers() {
return false;
}
};
MapLineBackgroundSeries.className = "MapLineBackgroundSeries";
MapLineBackgroundSeries.type = "map-line-background";
// packages/ag-charts-enterprise/src/series/map-line-background/mapLineBackgroundSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport166 } from "ag-charts-community";
import { constant as constant12, geoJson as geoJson2, required as required12 } from "ag-charts-core";
var { mapLineBackgroundSeriesThemeableOptionsDef } = _ModuleSupport166;
var mapLineBackgroundSeriesOptionsDef = {
...mapLineBackgroundSeriesThemeableOptionsDef,
type: required12(constant12("map-line-background")),
topology: geoJson2
};
// packages/ag-charts-enterprise/src/series/map-line-background/mapLineBackgroundModule.ts
var MapLineBackgroundSeriesModule = {
type: "series",
name: "map-line-background",
chartType: "topology",
enterprise: true,
version: VERSION37,
dependencies: [TopologyChartModule],
options: mapLineBackgroundSeriesOptionsDef,
themeTemplate: {
...MAP_THEME_DEFAULTS,
series: {
stroke: { $path: ["/1", { $mapPalette: "stroke" }, { $mapPalette: "secondHierarchyColors" }] },
strokeWidth: 1,
lineDash: [0],
lineDashOffset: 0
}
},
create: (ctx) => new MapLineBackgroundSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/map-marker/mapMarkerModule.ts
import { VERSION as VERSION38 } from "ag-charts-community";
import {
FILL_GRADIENT_RADIAL_REVERSED_DEFAULTS as FILL_GRADIENT_RADIAL_REVERSED_DEFAULTS2,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS9,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS5,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS10,
MULTI_SERIES_HIGHLIGHT_STYLE as MULTI_SERIES_HIGHLIGHT_STYLE5,
SAFE_RANGE2_OPERATION as SAFE_RANGE2_OPERATION5,
ValidationError,
validate
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/map-marker/mapMarkerSeries.ts
import { _ModuleSupport as _ModuleSupport169 } from "ag-charts-community";
import {
Logger as Logger19,
StateMachine as StateMachine13,
cachedTextMeasurer as cachedTextMeasurer9,
mergeDefaults as mergeDefaults15
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/map-util/polygonPointSearch.ts
import { insertListItemsSorted } from "ag-charts-core";
function polygonPointSearch(polygons, precision, valueFn) {
const bbox = polygonBbox(polygons[0], void 0);
if (bbox == null)
return;
const boundingXCenter = (bbox.lon0 + bbox.lon1) / 2;
const boundingYCenter = (bbox.lat0 + bbox.lat1) / 2;
const boundingWidth = Math.abs(bbox.lon1 - bbox.lon0);
const boundingHeight = Math.abs(bbox.lat1 - bbox.lat0);
const centroid = polygonCentroid(polygons[0]);
const [cx, cy] = centroid;
const centroidDistanceToPolygon = -polygonDistance(polygons, cx, cy);
let bestResult;
const cellValue = (distanceToPolygon, distanceToCentroid) => {
const centroidDriftFactor = 0.5;
const centroidDrift = Math.max(distanceToCentroid - centroidDistanceToPolygon, 0);
return distanceToPolygon - centroidDriftFactor * centroidDrift;
};
const createLabelPlacement = (x2, y2, stride) => {
const { distance: distance2, maxDistance } = valueFn(polygons, x2, y2, stride);
const distanceToCentroid = Math.hypot(cx - x2, cy - y2);
const maxXTowardsCentroid = Math.min(Math.max(cx, x2 - stride / 2), x2 + stride / 2);
const maxYTowardsCentroid = Math.min(Math.max(cy, y2 - stride / 2), y2 + stride / 2);
const minDistanceToCentroid = Math.hypot(cx - maxXTowardsCentroid, cy - maxYTowardsCentroid);
const value = cellValue(distance2, distanceToCentroid);
const maxValue = cellValue(maxDistance, minDistanceToCentroid);
return { distance: distance2, maxDistance, value, maxValue, x: x2, y: y2, stride };
};
const appendLabelPlacement = (into, x2, y2, stride) => {
const labelPlacement = createLabelPlacement(x2, y2, stride);
if (labelPlacement.maxDistance >= 0) {
into.push(labelPlacement);
}
};
const initialStride = Math.min(boundingWidth, boundingHeight) / 2;
let queue = {
value: createLabelPlacement(boundingXCenter, boundingYCenter, initialStride),
next: null
};
while (queue != null) {
const item = queue.value;
const { distance: distance2, value, maxValue, x: x2, y: y2, stride } = item;
queue = queue.next;
if (distance2 > 0 && (bestResult == null || value > bestResult.value)) {
bestResult = item;
}
if (bestResult != null && maxValue - bestResult.value <= precision) {
continue;
}
const nextStride = stride / 2;
const newLabelPlacements = [];
appendLabelPlacement(newLabelPlacements, x2 - nextStride, y2 - nextStride, nextStride);
appendLabelPlacement(newLabelPlacements, x2 + nextStride, y2 - nextStride, nextStride);
appendLabelPlacement(newLabelPlacements, x2 - nextStride, y2 + nextStride, nextStride);
appendLabelPlacement(newLabelPlacements, x2 + nextStride, y2 + nextStride, nextStride);
newLabelPlacements.sort(labelPlacementCmp);
queue = insertListItemsSorted(queue, newLabelPlacements, labelPlacementCmp);
}
if (bestResult == null)
return;
const { distance, x, y } = bestResult;
return { x, y, distance };
}
var labelPlacementCmp = (a, b) => b.maxValue - a.maxValue;
// packages/ag-charts-enterprise/src/series/map-util/markerUtil.ts
function polygonMarkerCenter(polygons, precision) {
const result = polygonPointSearch(polygons, precision, (p, x2, y2, stride) => {
const distance = -polygonDistance(p, x2, y2);
const maxDistance = distance + stride * Math.SQRT2;
return { distance, maxDistance };
});
if (result == null)
return;
const { x, y } = result;
return [x, y];
}
function markerPositions(geometry, precision) {
let center;
switch (geometry.type) {
case "GeometryCollection":
return geometry.geometries.flatMap((g) => markerPositions(g, precision));
case "MultiPoint":
return geometry.coordinates;
case "Point":
return [geometry.coordinates];
case "MultiPolygon": {
const polygon = largestPolygon(geometry);
center = polygon == null ? void 0 : polygonMarkerCenter(polygon, precision);
break;
}
case "Polygon": {
const polygon = geometry.coordinates;
center = polygon == null ? void 0 : polygonMarkerCenter(polygon, precision);
break;
}
case "MultiLineString": {
const lineString = largestLineString(geometry);
center = lineString == null ? void 0 : lineStringCenter(lineString)?.point;
break;
}
case "LineString": {
const lineString = geometry.coordinates;
center = lineStringCenter(lineString)?.point;
break;
}
}
return center == null ? [] : [center];
}
// packages/ag-charts-enterprise/src/series/map-util/shapeFillBBox.ts
import { _ModuleSupport as _ModuleSupport167 } from "ag-charts-community";
var { BBox: BBox22 } = _ModuleSupport167;
function getTopologyShapeFillBBox(scale) {
if (!scale)
return;
const { range: range2 } = scale;
const x = range2[0][0];
const y = range2[0][1];
const width = range2[1][0] - x;
const height = range2[1][1] - y;
const bbox = new BBox22(x, y, width, height);
return {
series: bbox,
axis: bbox
};
}
// packages/ag-charts-enterprise/src/series/map-marker/mapMarkerSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport168 } from "ag-charts-community";
import { Property as Property77 } from "ag-charts-core";
var { SeriesProperties: SeriesProperties5, makeSeriesTooltip: makeSeriesTooltip14, Label: Label11 } = _ModuleSupport168;
var MapMarkerSeriesLabel = class extends Label11 {
constructor() {
super(...arguments);
this.placement = "bottom";
}
};
__decorateClass([
Property77
], MapMarkerSeriesLabel.prototype, "placement", 2);
var MapMarkerSeriesProperties = class extends SeriesProperties5 {
constructor() {
super(...arguments);
this.topology = void 0;
this.idKey = void 0;
this.topologyIdKey = "name";
this.idName = void 0;
this.latitudeKey = void 0;
this.latitudeName = void 0;
this.longitudeKey = void 0;
this.longitudeName = void 0;
this.labelKey = void 0;
this.labelName = void 0;
this.colorRange = void 0;
this.shape = "circle";
this.size = 6;
this.fill = "black";
this.fillOpacity = 1;
this.stroke = "black";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.label = new MapMarkerSeriesLabel();
this.tooltip = makeSeriesTooltip14();
}
getStyle() {
const { size, shape, fill, fillOpacity, stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = this;
return {
size,
shape,
fill,
fillOpacity,
opacity: 1,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
};
}
};
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "topology", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "title", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "legendItemName", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "idKey", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "topologyIdKey", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "idName", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "latitudeKey", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "latitudeName", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "longitudeKey", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "longitudeName", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "labelKey", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "labelName", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "sizeKey", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "sizeName", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "colorKey", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "colorName", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "colorRange", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "shape", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "size", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "maxSize", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "sizeDomain", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "fill", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "stroke", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "label", 2);
__decorateClass([
Property77
], MapMarkerSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/map-marker/mapMarkerSeries.ts
var {
fromToMotion: fromToMotion3,
getMissCount: getMissCount3,
createDatumId: createDatumId13,
SeriesNodePickMode: SeriesNodePickMode10,
valueProperty: valueProperty12,
computeMarkerFocusBounds: computeMarkerFocusBounds2,
ColorScale: ColorScale3,
LinearScale: LinearScale6,
Group: Group14,
Selection: Selection10,
Text: Text5,
Marker: Marker4,
getLabelStyles: getLabelStyles3
} = _ModuleSupport169;
var MapMarkerSeries = class extends TopologySeries {
constructor(moduleCtx) {
super({
moduleCtx,
categoryKey: void 0,
propertyKeys: {
size: ["colorKey"],
color: ["colorKey"],
label: ["labelKey"]
},
propertyNames: {
size: ["sizeName"],
color: ["colorName"],
label: ["labelName"]
},
pickModes: [SeriesNodePickMode10.EXACT_SHAPE_MATCH, SeriesNodePickMode10.NEAREST_NODE],
usesPlacedLabels: true
});
this.properties = new MapMarkerSeriesProperties();
this._chartTopology = void 0;
this.colorScale = new ColorScale3();
this.sizeScale = new LinearScale6();
this.markerGroup = this.contentGroup.appendChild(new Group14({ name: "markerGroup" }));
this.labelSelection = Selection10.select(this.labelGroup, Text5, false);
this.highlightLabelSelection = Selection10.select(this.highlightLabelGroup, Text5, false);
this.markerSelection = Selection10.select(
this.markerGroup,
Marker4,
false
);
this.highlightMarkerSelection = Selection10.select(this.highlightNodeGroup, Marker4);
this.placedLabelData = [];
this.animationState = new StateMachine13(
"empty",
{
empty: {
update: {
target: "ready",
action: () => this.animateMarkers()
},
reset: "empty",
skip: "ready"
},
ready: {
updateData: "waiting",
clear: "clearing",
resize: () => this.resetAllAnimation(),
reset: "empty",
skip: "ready"
},
waiting: {
update: {
target: "ready",
action: () => this.animateMarkers()
},
// chart.ts transitions to updateData on zoom change
resize: {
target: "ready",
action: () => this.resetAllAnimation()
},
reset: "empty",
skip: "ready"
},
clearing: {
update: {
target: "empty",
action: () => this.resetAllAnimation()
},
reset: "empty",
skip: "ready"
}
},
() => this.checkProcessedDataAnimatable()
);
}
getNodeData() {
return this.contextNodeData?.nodeData;
}
get topology() {
return this.properties.topology ?? this._chartTopology;
}
get hasData() {
const hasLatLon = this.properties.latitudeKey != null && this.properties.longitudeKey != null;
return super.hasData && (this.topology != null || hasLatLon);
}
renderToOffscreenCanvas() {
return true;
}
setChartTopology(topology) {
this._chartTopology = topology;
if (this.topology === topology) {
this.nodeDataRefresh = true;
}
}
setZIndex(zIndex) {
super.setZIndex(zIndex);
this.contentGroup.zIndex = [2 /* Marker */, zIndex];
this.highlightGroup.zIndex = [3 /* MarkerHighlight */, zIndex];
return true;
}
isLabelEnabled() {
return this.properties.labelKey != null && this.properties.label.enabled;
}
async processData(dataController) {
if (this.data == null)
return;
const { data, sizeScale, colorScale } = this;
const { topologyIdKey, idKey, latitudeKey, longitudeKey, sizeKey, colorKey, labelKey, sizeDomain, colorRange } = this.properties;
const featureById = this.buildFeatureMap(topologyIdKey);
const sizeScaleType = this.sizeScale.type;
const colorScaleType = this.colorScale.type;
const mercatorScaleType = this.scale?.type;
const hasLatLon = latitudeKey != null && longitudeKey != null;
const { dataModel, processedData } = await this.requestDataModel(dataController, data, {
props: [
...idKey == null ? [] : [
valueProperty12(idKey, mercatorScaleType, { id: "idValue", includeProperty: false }),
valueProperty12(idKey, mercatorScaleType, {
id: "featureValue",
includeProperty: false,
processor: () => (datum) => featureById.get(datum)
})
],
...hasLatLon ? [
valueProperty12(latitudeKey, mercatorScaleType, { id: "latValue" }),
valueProperty12(longitudeKey, mercatorScaleType, { id: "lonValue" })
] : [],
...labelKey ? [valueProperty12(labelKey, "category", { id: "labelValue" })] : [],
...sizeKey ? [valueProperty12(sizeKey, sizeScaleType, { id: "sizeValue" })] : [],
...colorKey ? [valueProperty12(colorKey, colorScaleType, { id: "colorValue" })] : []
]
});
const featureValues = idKey == null ? void 0 : dataModel.resolveColumnById(this, `featureValue`, processedData);
const latValues = hasLatLon ? dataModel.resolveColumnById(this, `latValue`, processedData) : void 0;
const lonValues = hasLatLon ? dataModel.resolveColumnById(this, `lonValue`, processedData) : void 0;
this.topologyBounds = processedData.dataSources.get(this.id)?.data.reduce((current, _datum, datumIndex) => {
const feature = featureValues?.[datumIndex];
const geometry = feature?.geometry;
if (geometry != null) {
current = geometryBbox(geometry, current);
}
if (latValues != null && lonValues != null) {
const lon = lonValues[datumIndex];
const lat = latValues[datumIndex];
current = LonLatBBox.extend(current, lon, lat, lon, lat);
}
return current;
}, void 0);
if (sizeKey != null) {
const sizeIdx = dataModel.resolveProcessedDataIndexById(this, `sizeValue`);
const processedSize = processedData.domain.values[sizeIdx] ?? [];
sizeScale.domain = sizeDomain ?? processedSize;
}
if (colorRange != null && this.isColorScaleValid()) {
const colorKeyIdx = dataModel.resolveProcessedDataIndexById(this, "colorValue");
colorScale.domain = processedData.domain.values[colorKeyIdx];
colorScale.range = colorRange;
colorScale.update();
}
this.animationState.transition("updateData");
}
isColorScaleValid() {
const { colorKey } = this.properties;
if (!colorKey) {
return false;
}
const { dataModel, processedData } = this;
if (!dataModel || !processedData) {
return false;
}
const colorIdx = dataModel.resolveProcessedDataIndexById(this, "colorValue");
const dataCount = processedData.input.count;
const missCount = getMissCount3(this, processedData.defs.values[colorIdx].missing);
const colorDataMissing = dataCount === 0 || dataCount === missCount;
return !colorDataMissing;
}
getLabelDatum(node, labelValue, measurer3) {
if (labelValue == null)
return;
const {
idKey,
idName,
latitudeKey,
latitudeName,
longitudeKey,
longitudeName,
sizeKey,
sizeName,
colorKey,
colorName,
labelKey,
labelName,
label,
shape
} = this.properties;
if (labelKey == null || !label.enabled)
return;
const { datum, datumIndex, index, idValue, lonValue, latValue, point } = node;
const { placement } = label;
const labelText = this.getLabelText(
labelValue,
datum,
labelKey,
"label",
[],
label,
{
value: labelValue,
datum,
idKey,
idName,
latitudeKey,
latitudeName,
longitudeKey,
longitudeName,
sizeKey,
sizeName,
colorKey,
colorName,
labelKey,
labelName
}
);
if (labelText == null)
return;
const { width, height } = measurer3.measureLines(String(labelText));
const anchor = Marker4.anchor(shape);
return {
point: { x: point.x, y: point.y, size: point.size },
label: { width, height, text: labelText },
anchor,
placement,
datumIndex,
datumId: createDatumId13(index, idValue, lonValue, latValue)
};
}
resolveColumn(key, columnId, processedData) {
if (key == null || this.dataModel == null)
return void 0;
return this.dataModel.resolveColumnById(this, columnId, processedData);
}
resolveDataColumns(processedData) {
const { idKey, latitudeKey, longitudeKey, sizeKey, colorKey, labelKey } = this.properties;
const hasLatLon = latitudeKey != null && longitudeKey != null;
return {
idValues: this.resolveColumn(idKey, "idValue", processedData),
featureValues: this.resolveColumn(idKey, "featureValue", processedData),
latValues: hasLatLon ? this.resolveColumn(latitudeKey, "latValue", processedData) : void 0,
lonValues: hasLatLon ? this.resolveColumn(longitudeKey, "lonValue", processedData) : void 0,
labelValues: this.resolveColumn(labelKey, "labelValue", processedData),
sizeValues: this.resolveColumn(sizeKey, "sizeValue", processedData),
colorValues: this.resolveColumn(colorKey, "colorValue", processedData)
};
}
prepareProjectedGeometries(idValues, featureValues, processedData) {
if (idValues == null || featureValues == null || this.scale == null)
return void 0;
const projectedGeometries = /* @__PURE__ */ new Map();
for (const [datumIndex] of processedData.dataSources.get(this.id)?.data.entries() ?? []) {
const id = idValues[datumIndex];
const geometry = featureValues[datumIndex]?.geometry;
const projectedGeometry = geometry == null ? void 0 : projectGeometry(geometry, this.scale);
if (id != null && projectedGeometry != null) {
projectedGeometries.set(id, projectedGeometry);
}
}
return projectedGeometries;
}
calculateMarkerSize(sizeValue) {
return sizeValue == null ? this.properties.size : this.sizeScale.convert(sizeValue, { clamp: true });
}
buildNodeDatum(datum, datumIndex, index, point, dataValues) {
return {
series: this,
datum,
datumIndex,
index,
...dataValues,
point,
midPoint: { x: point.x, y: point.y },
legendItemName: this.properties.legendItemName,
style: this.getMarkerItemStyle(
{ datumIndex, datum, colorValue: dataValues.colorValue, sizeValue: dataValues.sizeValue },
false
)
};
}
createNodeFromLatLon(datum, datumIndex, lonValue, latValue, dataValues, size, measurer3) {
if (this.scale == null) {
throw new Error("Scale is required for createNodeFromLatLon");
}
const [x, y] = this.scale.convert([lonValue, latValue]);
const point = { x, y, size };
const node = this.buildNodeDatum(datum, datumIndex, -1, point, dataValues);
const label = this.getLabelDatum(node, dataValues.labelValue, measurer3) ?? void 0;
return { node, label };
}
createNodesFromGeometry(datum, datumIndex, geometry, dataValues, size, measurer3) {
const nodes = [];
const labels = [];
for (const [index, [x, y]] of markerPositions(geometry, 1).entries()) {
const point = { x, y, size };
const node = this.buildNodeDatum(datum, datumIndex, index, point, dataValues);
nodes.push(node);
const label = this.getLabelDatum(node, dataValues.labelValue, measurer3);
if (label) {
labels.push(label);
}
}
return { nodes, labels };
}
warnMissingGeometries(missingGeometries) {
if (missingGeometries.length === 0)
return;
const missingGeometriesCap = 10;
if (missingGeometries.length > missingGeometriesCap) {
const excessItems = missingGeometries.length - missingGeometriesCap;
missingGeometries.length = missingGeometriesCap;
missingGeometries.push(`(+${excessItems} more)`);
}
Logger19.warnOnce(`some data items do not have matches in the provided topology`, missingGeometries);
}
buildFeatureMap(topologyIdKey) {
const featureById = /* @__PURE__ */ new Map();
for (const feature of this.topology?.features.values() ?? []) {
const property = feature.properties?.[topologyIdKey];
if (property != null) {
featureById.set(property, feature);
}
}
return featureById;
}
createNodeData() {
const { id: seriesId, dataModel, processedData, sizeScale, properties, scale } = this;
const { label } = properties;
if (dataModel == null || processedData == null || scale == null)
return;
if (!this.visible) {
return { itemId: seriesId, nodeData: [], labelData: [] };
}
const columns = this.resolveDataColumns(processedData);
const markerMaxSize = properties.maxSize ?? properties.size;
sizeScale.range = [Math.min(properties.size, markerMaxSize), markerMaxSize];
const measurer3 = cachedTextMeasurer9(label);
const projectedGeometries = this.prepareProjectedGeometries(
columns.idValues,
columns.featureValues,
processedData
);
const nodeData = [];
const labelData = [];
const missingGeometries = [];
const rawData = processedData.dataSources.get(this.id)?.data ?? [];
for (const [datumIndex, datum] of rawData.entries()) {
const dataValues = {
idValue: columns.idValues?.[datumIndex],
lonValue: columns.lonValues?.[datumIndex],
latValue: columns.latValues?.[datumIndex],
colorValue: columns.colorValues?.[datumIndex],
sizeValue: columns.sizeValues?.[datumIndex],
labelValue: columns.labelValues?.[datumIndex]
};
const size = this.calculateMarkerSize(dataValues.sizeValue);
const projectedGeometry = dataValues.idValue == null ? void 0 : projectedGeometries?.get(dataValues.idValue);
if (dataValues.idValue != null && projectedGeometries != null && projectedGeometry == null) {
missingGeometries.push(dataValues.idValue);
}
if (dataValues.lonValue != null && dataValues.latValue != null) {
const result = this.createNodeFromLatLon(
datum,
datumIndex,
dataValues.lonValue,
dataValues.latValue,
dataValues,
size,
measurer3
);
nodeData.push(result.node);
if (result.label)
labelData.push(result.label);
} else if (projectedGeometry != null) {
const result = this.createNodesFromGeometry(
datum,
datumIndex,
projectedGeometry,
dataValues,
size,
measurer3
);
nodeData.push(...result.nodes);
labelData.push(...result.labels);
}
}
this.warnMissingGeometries(missingGeometries);
return {
itemId: seriesId,
nodeData,
labelData
};
}
updateSelections() {
if (this.nodeDataRefresh) {
this.contextNodeData = this.createNodeData();
this.nodeDataRefresh = false;
}
}
checkScaleChange() {
if (this.previousScale === this.scale)
return false;
this.previousScale = this.scale;
return true;
}
update({ seriesRect }) {
const resize = this.checkResize(seriesRect);
const scaleChange = this.checkScaleChange();
const { markerSelection, highlightMarkerSelection } = this;
const drawingMode = this.ctx.chartService.highlight?.drawingMode ?? "overlay";
this.updateSelections();
this.contentGroup.visible = this.visible;
this.labelGroup.visible = this.visible;
const highlightedDatum = this.getHighlightedDatum();
const nodeData = this.contextNodeData?.nodeData ?? [];
this.markerSelection = this.updateMarkerSelection({ markerData: nodeData, markerSelection });
this.updateMarkerNodes({ markerSelection, isHighlight: false, highlightedDatum, drawingMode: "overlay" });
this.highlightMarkerSelection = this.updateMarkerSelection({
markerData: highlightedDatum == null ? [] : [highlightedDatum],
markerSelection: highlightMarkerSelection
});
this.updateMarkerNodes({
markerSelection: highlightMarkerSelection,
isHighlight: true,
highlightedDatum,
drawingMode
});
this.updateLabelNodes({ labelSelection: this.labelSelection, isHighlight: false });
this.updateHighlightLabelSelection(highlightedDatum);
if (scaleChange || resize) {
this.animationState.transition("resize");
}
this.animationState.transition("update");
}
updatePlacedLabelData(labelData) {
this.placedLabelData = labelData;
this.labelSelection = this.labelSelection.update(labelData, (text2) => {
text2.pointerEvents = _ModuleSupport169.PointerEvents.None;
});
this.updateLabelNodes({ labelSelection: this.labelSelection, isHighlight: false });
this.updateHighlightLabelSelection();
}
updateLabelNodes({
isHighlight,
labelSelection
}) {
const { properties } = this;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
labelSelection.each((label, placedLabel) => {
const { x, y, width, height, text: text2, datum: labelDatum } = placedLabel;
const style = getLabelStyles3(
this,
void 0,
properties,
properties.label,
isHighlight,
activeHighlight
);
const { color: fill, fontStyle, fontWeight, fontSize, fontFamily } = style;
label.visible = true;
label.x = x + width / 2;
label.y = y + height / 2;
label.text = text2;
label.fill = fill;
label.fontStyle = fontStyle;
label.fontWeight = fontWeight;
label.fontSize = fontSize;
label.fontFamily = fontFamily;
label.textAlign = "center";
label.textBaseline = "middle";
const datumIndex = labelDatum?.datumIndex;
label.fillOpacity = this.getHighlightStyle(isHighlight, datumIndex).opacity ?? 1;
label.setBoxing(style);
});
}
getHighlightedLabelId(highlightedDatum = this.getHighlightedDatum()) {
if (highlightedDatum == null)
return void 0;
return createDatumId13(
highlightedDatum.index,
highlightedDatum.idValue,
highlightedDatum.lonValue,
highlightedDatum.latValue
);
}
updateHighlightLabelSelection(highlightedDatum = this.getHighlightedDatum()) {
const highlightId = this.getHighlightedLabelId(highlightedDatum);
const highlightLabels = highlightId == null || !this.isLabelEnabled() ? [] : this.placedLabelData.filter((label) => label.datum.datumId === highlightId);
this.highlightLabelSelection = this.highlightLabelSelection.update(highlightLabels);
if (highlightLabels.length === 0) {
this.highlightLabelSelection.cleanup();
this.highlightLabelGroup.visible = false;
return;
}
this.highlightLabelGroup.visible = true;
this.updateLabelNodes({
labelSelection: this.highlightLabelSelection,
isHighlight: true
});
}
updateMarkerSelection(opts) {
const { markerData, markerSelection } = opts;
return markerSelection.update(
markerData,
void 0,
(datum) => createDatumId13(datum.index, datum.idValue, datum.lonValue, datum.latValue)
);
}
getMarkerItemStyle({ datumIndex, datum, colorValue, sizeValue }, isHighlight) {
const { properties, colorScale, sizeScale } = this;
const { colorRange, itemStyler } = properties;
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
const baseStyle = mergeDefaults15(highlightStyle, properties.getStyle());
if (!isHighlight && colorValue != null) {
baseStyle.fill = this.isColorScaleValid() ? colorScale.convert(colorValue) : colorRange?.[0] ?? baseStyle.fill;
}
if (sizeValue != null) {
baseStyle.size = sizeScale.convert(sizeValue, { clamp: true });
}
let style = baseStyle;
if (itemStyler != null && datumIndex != null) {
const overrides = this.cachedDatumCallback(
createDatumId13(datumIndex, isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(datum, datumIndex, isHighlight, style);
return this.callWithContext(itemStyler, params);
}
);
if (overrides) {
style = mergeDefaults15(overrides, baseStyle);
}
}
return style;
}
makeItemStylerParams(datum, datumIndex, isHighlight, style) {
const { id: seriesId } = this;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightState = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum,
highlightState,
...style,
fill
};
}
updateMarkerNodes(opts) {
const { markerSelection, isHighlight, highlightedDatum, drawingMode } = opts;
const fillBBox = getTopologyShapeFillBBox(this.scale);
markerSelection.each((marker, markerDatum) => {
const { datum, point } = markerDatum;
const style = this.getMarkerItemStyle(markerDatum, isHighlight);
marker.shape = style.shape;
marker.size = style.size;
marker.setStyleProperties(style, fillBBox);
marker.x = point.x;
marker.y = point.y;
marker.scalingCenterX = point.x;
marker.scalingCenterY = point.y;
marker.zIndex = !isHighlight && highlightedDatum != null && datum === highlightedDatum.datum ? 1 : 0;
marker.drawingMode = drawingMode;
});
}
isProcessedDataAnimatable() {
return true;
}
resetAnimation(phase) {
if (phase === "initial") {
this.animationState.transition("reset");
} else if (phase === "ready") {
this.animationState.transition("skip");
}
}
resetAllAnimation() {
this.ctx.animationManager.stopByAnimationGroupId(this.id);
this.ctx.animationManager.skipCurrentBatch();
this.labelSelection.cleanup();
this.markerSelection.cleanup();
this.highlightMarkerSelection.cleanup();
this.highlightLabelSelection.cleanup();
this.highlightLabelGroup.visible = false;
this.placedLabelData = [];
}
animateMarkers() {
const { animationManager } = this.ctx;
const fns = prepareMapMarkerAnimationFunctions();
fromToMotion3(this.id, "markers", animationManager, [this.markerSelection, this.highlightMarkerSelection], fns);
}
getLabelData() {
if (!this.isLabelEnabled())
return [];
return this.contextNodeData?.labelData ?? [];
}
pickNodeClosestDatum(p) {
const { x: x0, y: y0 } = p;
let minDistanceSquared = Infinity;
let minDatum;
for (const datum of this.contextNodeData?.nodeData ?? []) {
const { x, y, size } = datum.point;
const dx2 = Math.max(Math.abs(x - x0) - size, 0);
const dy2 = Math.max(Math.abs(y - y0) - size, 0);
const distanceSquared = dx2 * dx2 + dy2 * dy2;
if (distanceSquared < minDistanceSquared) {
minDistanceSquared = distanceSquared;
minDatum = datum;
}
}
return minDatum == null ? void 0 : { datum: minDatum, distance: Math.sqrt(minDistanceSquared) };
}
legendItemSymbol(datumIndex) {
const { dataModel, processedData, properties } = this;
const { shape, fillOpacity, stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = properties;
let { fill } = properties;
if (datumIndex != null && this.isColorScaleValid()) {
const colorValues = dataModel.resolveColumnById(this, "colorValue", processedData);
const colorValue = colorValues[datumIndex];
fill = this.colorScale.convert(colorValue);
}
return {
marker: {
shape,
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
}
};
}
getLegendData(legendType) {
const { processedData, dataModel } = this;
if (processedData == null || dataModel == null)
return [];
const { id: seriesId, visible } = this;
const { title, legendItemName, idName, idKey, colorKey, colorRange, showInLegend } = this.properties;
if (legendType === "gradient" && colorKey != null && colorRange != null) {
const colorDomain = processedData.domain.values[dataModel.resolveProcessedDataIndexById(this, "colorValue")];
const legendDatum = {
legendType: "gradient",
enabled: visible,
seriesId,
series: this.getFormatterContext("color"),
colorRange,
colorDomain
};
return [legendDatum];
} else if (legendType === "category") {
const legendDatum = {
legendType: "category",
id: seriesId,
itemId: seriesId,
seriesId,
enabled: visible,
label: { text: legendItemName ?? title ?? idName ?? idKey ?? seriesId },
symbol: this.legendItemSymbol(),
legendItemName,
hideInLegend: !showInLegend
};
return [legendDatum];
} else {
return [];
}
}
getTooltipContent(datumIndex) {
const {
id: seriesId,
dataModel,
processedData,
properties,
ctx: { formatManager }
} = this;
const {
idKey,
idName,
latitudeKey,
latitudeName,
longitudeKey,
longitudeName,
colorKey,
colorName,
sizeKey,
sizeName,
labelKey,
labelName,
title,
legendItemName,
tooltip
} = properties;
if (!dataModel || !processedData)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const sizeValue = sizeKey == null ? void 0 : dataModel.resolveColumnById(this, `sizeValue`, processedData)[datumIndex];
const colorValue = colorKey == null ? void 0 : dataModel.resolveColumnById(this, `colorValue`, processedData)[datumIndex];
const data = [];
if (this.isLabelEnabled() && labelKey != null && labelKey !== idKey) {
const labelValue = dataModel.resolveColumnById(this, `labelValue`, processedData)[datumIndex];
const content = formatManager.format(this.callWithContext.bind(this), {
type: "category",
value: labelValue,
datum,
seriesId,
legendItemName,
key: labelKey,
source: "tooltip",
property: "label",
domain: [],
boundSeries: this.getFormatterContext("label")
});
data.push({ label: labelName, fallbackLabel: labelKey, value: content ?? labelValue });
}
if (sizeKey != null && sizeValue != null) {
const domain = dataModel.getDomain(this, `sizeValue`, "value", processedData).domain;
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: sizeValue,
datum,
seriesId,
legendItemName,
key: sizeKey,
source: "tooltip",
property: "size",
domain,
boundSeries: this.getFormatterContext("size"),
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: sizeName, fallbackLabel: sizeKey, value: content ?? String(sizeValue) });
}
if (colorKey != null && colorValue != null) {
const domain = dataModel.getDomain(this, `colorValue`, "value", processedData).domain;
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: colorValue,
datum,
seriesId,
legendItemName,
key: colorKey,
source: "tooltip",
property: "color",
domain,
boundSeries: this.getFormatterContext("color"),
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: colorName, fallbackLabel: colorKey, value: content ?? String(colorValue) });
}
let heading;
if (idKey != null) {
heading = dataModel.resolveColumnById(this, `idValue`, processedData)[datumIndex];
} else if (latitudeKey != null && longitudeKey != null) {
const latValue = dataModel.resolveColumnById(this, `latValue`, processedData)[datumIndex];
const lonValue = dataModel.resolveColumnById(this, `lonValue`, processedData)[datumIndex];
heading = `${Math.abs(latValue).toFixed(4)}\xB0 ${latValue >= 0 ? "N" : "S"}, ${Math.abs(lonValue).toFixed(4)}\xB0 ${lonValue >= 0 ? "W" : "E"}`;
}
const format = this.getMarkerItemStyle({ datumIndex, datum, colorValue, sizeValue }, false);
return this.formatTooltipWithContext(
tooltip,
{
heading,
title: title ?? legendItemName,
symbol: this.legendItemSymbol(datumIndex),
data
},
{
seriesId,
datum,
title,
idKey,
idName,
latitudeKey,
latitudeName,
longitudeKey,
longitudeName,
colorKey,
colorName,
sizeKey,
sizeName,
labelKey,
labelName,
...format
}
);
}
getFormattedMarkerStyle(markerDatum) {
const format = this.getMarkerItemStyle(markerDatum, false);
return { size: format.size, shape: format.shape };
}
computeFocusBounds(opts) {
return computeMarkerFocusBounds2(this, opts);
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.label.itemStyler != null;
}
};
MapMarkerSeries.className = "MapMarkerSeries";
MapMarkerSeries.type = "map-marker";
// packages/ag-charts-enterprise/src/series/map-marker/mapMarkerSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport170 } from "ag-charts-community";
import {
commonSeriesOptionsDefs as commonSeriesOptionsDefs12,
constant as constant13,
geoJson as geoJson3,
required as required13,
string as string14,
without as without7
} from "ag-charts-core";
var { mapMarkerSeriesThemeableOptionsDef } = _ModuleSupport170;
var mapMarkerSeriesOptionsDef = {
...without7(commonSeriesOptionsDefs12, ["highlightStyle", "highlight"]),
...mapMarkerSeriesThemeableOptionsDef,
type: required13(constant13("map-marker")),
idKey: string14,
latitudeKey: string14,
longitudeKey: string14,
sizeKey: string14,
colorKey: string14,
labelKey: string14,
idName: string14,
latitudeName: string14,
longitudeName: string14,
sizeName: string14,
colorName: string14,
labelName: string14,
topology: geoJson3,
topologyIdKey: string14,
legendItemName: string14,
title: string14
};
// packages/ag-charts-enterprise/src/series/map-marker/mapMarkerModule.ts
var MapMarkerSeriesModule = {
type: "series",
name: "map-marker",
chartType: "topology",
enterprise: true,
version: VERSION38,
dependencies: [TopologyChartModule],
options: mapMarkerSeriesOptionsDef,
themeTemplate: {
...MAP_THEME_DEFAULTS,
series: {
shape: "circle",
maxSize: 30,
fill: applyMapPalette({
$applySwitch: [
{ $path: "type" },
{ $mapPalette: "fill" },
["gradient", FILL_GRADIENT_RADIAL_REVERSED_DEFAULTS2],
["image", FILL_IMAGE_DEFAULTS9],
["pattern", FILL_PATTERN_DEFAULTS5]
]
}),
stroke: { $mapPalette: "stroke" },
colorRange: {
$if: [
{ $eq: [{ $mapPalette: "type" }, "inbuilt"] },
{ $mapPalette: "divergingColors" },
applyMapPalette(SAFE_RANGE2_OPERATION5)
]
},
fillOpacity: 0.5,
label: {
...LABEL_BOXING_DEFAULTS10,
enabled: false,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "textColor" }
},
highlight: applyMapPalette(MULTI_SERIES_HIGHLIGHT_STYLE5)
},
tooltip: {
range: "exact"
}
},
create: (ctx) => new MapMarkerSeries(ctx),
validate(options, optionsDefs, path) {
const result = validate(options, optionsDefs, path);
const { cleared, invalid } = result;
if (cleared?.idKey == null && (cleared?.latitudeKey == null || cleared?.longitudeKey == null)) {
const extendPath = (key) => path ? `${path}.${key}` : key;
const message = `Either \`${extendPath("idKey")}\` or both \`${extendPath("latitudeKey")}\` and \`${extendPath("longitudeKey")}\` are required.`;
invalid.push(new ValidationError("required", message, null, path));
}
return result;
}
};
// packages/ag-charts-enterprise/src/series/map-shape/mapShapeModule.ts
import { VERSION as VERSION39 } from "ag-charts-community";
import {
FILL_GRADIENT_LINEAR_DEFAULTS as FILL_GRADIENT_LINEAR_DEFAULTS5,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS10,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS6,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS11,
MULTI_SERIES_HIGHLIGHT_STYLE as MULTI_SERIES_HIGHLIGHT_STYLE6,
SAFE_RANGE2_OPERATION as SAFE_RANGE2_OPERATION6
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/map-shape/mapShapeSeries.ts
import { _ModuleSupport as _ModuleSupport172 } from "ag-charts-community";
import { Logger as Logger20, cachedTextMeasurer as cachedTextMeasurer10, isArray as isArray5, measureTextSegments as measureTextSegments4, mergeDefaults as mergeDefaults16, toPlainText as toPlainText7 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/map-util/polygonLabelUtil.ts
function preferredLabelCenter(polygons, { aspectRatio, precision }) {
const result = polygonPointSearch(polygons, precision, (p, cx, cy, stride) => {
const width = maxWidthOfRectConstrainedByCenterAndAspectRatioToPolygon(p, cx, cy, aspectRatio);
const maxWidth2 = width + 2 * stride * aspectRatio;
const distance2 = width * Math.SQRT2;
const maxDistance = maxWidth2 * Math.SQRT2;
return { distance: distance2, maxDistance };
});
if (result == null)
return;
const { x, y, distance } = result;
const maxWidth = distance / Math.SQRT2;
return { x, y, maxWidth };
}
function maxWidthOfRectConstrainedByCenterAndAspectRatioToLineSegment(a, b, cx, cy, aspectRatio) {
const [ax, ay] = a;
const [bx, by] = b;
const positiveM = 1 / aspectRatio;
const abx = bx - ax;
const aby = by - ay;
const [topPointX, topPointY] = ay <= by ? a : b;
const [leftPointX, leftPointY] = ax <= bx ? a : b;
const [bottomPointX, bottomPointY] = ay <= by ? b : a;
const [rightPointX, rightPointY] = ax <= bx ? b : a;
let maxWidth = Infinity;
if (abx === 0) {
for (let i = 0; i <= 1; i += 1) {
const m = i === 0 ? positiveM : -positiveM;
const y = m * (ax - cx) + cy;
if (y >= topPointY && y <= bottomPointY) {
const height = Math.abs(cy - y) * 2;
const width = height * aspectRatio;
maxWidth = Math.min(maxWidth, width);
}
}
} else {
const abm = aby / abx;
for (let i = 0; i <= 1; i += 1) {
const m = i === 0 ? positiveM : -positiveM;
const x = (abm * ax - ay - m * cx + cy) / (abm - m);
if (x >= leftPointX && x <= rightPointX) {
const width = Math.abs(cx - x) * 2;
maxWidth = Math.min(maxWidth, width);
}
}
}
const positiveMRecip = aspectRatio;
const centerToTopMRecip = Math.abs((topPointX - cx) / (topPointY - cy));
const centerToBottomMRecip = Math.abs((bottomPointX - cx) / (bottomPointY - cy));
if (bottomPointY < cy && centerToBottomMRecip < positiveMRecip) {
const height = Math.abs(cy - bottomPointY) * 2;
const width = height * aspectRatio;
maxWidth = Math.min(maxWidth, width);
} else if (topPointY > cy && centerToTopMRecip < positiveMRecip) {
const height = Math.abs(cy - topPointY) * 2;
const width = height * aspectRatio;
maxWidth = Math.min(maxWidth, width);
}
const centerToLeftM = Math.abs((leftPointY - cy) / (leftPointX - cx));
const centerToRightM = Math.abs((rightPointY - cy) / (rightPointX - cx));
if (rightPointX < cx && centerToRightM < positiveM) {
const width = Math.abs(cx - rightPointX) * 2;
maxWidth = Math.min(maxWidth, width);
} else if (leftPointX > cx && centerToLeftM < positiveM) {
const width = Math.abs(cx - leftPointX) * 2;
maxWidth = Math.min(maxWidth, width);
}
return maxWidth;
}
function maxWidthOfRectConstrainedByCenterAndAspectRatioToPolygon(polygons, cx, cy, aspectRatio) {
let inside = false;
let minWidth = Infinity;
for (const polygon of polygons) {
let p0 = polygon.at(-1);
let [x0, y0] = p0;
for (const p1 of polygon) {
const [x1, y1] = p1;
if (y1 > cy !== y0 > cy && cx < (x0 - x1) * (cy - y1) / (y0 - y1) + x1) {
inside = !inside;
}
const width = maxWidthOfRectConstrainedByCenterAndAspectRatioToLineSegment(p0, p1, cx, cy, aspectRatio);
minWidth = Math.min(minWidth, width);
p0 = p1;
x0 = x1;
y0 = y1;
}
}
return (inside ? 1 : -1) * minWidth;
}
function applyX(into, cx, x) {
if (x >= cx) {
into.maxX = Math.min(into.maxX, x - cx);
}
if (x <= cx) {
into.minX = Math.max(into.minX, x - cx);
}
}
function xExtentsOfRectConstrainedByCenterAndHeightToLineSegment(into, a, b, cx, cy, height) {
const ry0 = cy - height / 2;
const ry1 = cy + height / 2;
const [ax, ay] = a;
const [bx, by] = b;
const abx = bx - ax;
const aby = by - ay;
const [leftPointX, leftPointY] = ax <= bx ? a : b;
const [rightPointX, rightPointY] = ax <= bx ? b : a;
if (abx !== 0) {
const abm = aby / abx;
for (let i = 0; i <= 1; i += 1) {
const y = i === 0 ? ry0 : ry1;
const x = (y - ay) / abm + ax;
if (x >= leftPointX && x <= rightPointX) {
applyX(into, cx, x);
}
}
} else if (Math.max(ry0, Math.min(ay, by)) <= Math.min(ry1, Math.max(ay, by))) {
applyX(into, cx, ax);
}
if (rightPointX < cx && rightPointY >= ry0 && rightPointY <= ry1) {
applyX(into, cx, rightPointX);
} else if (leftPointX > cx && leftPointY >= ry0 && leftPointY <= ry1) {
applyX(into, cx, leftPointX);
}
return into;
}
function maxWidthInPolygonForRectOfHeight(polygons, cx, cy, height) {
const result = {
minX: -Infinity,
maxX: Infinity
};
for (const polygon of polygons) {
let p0 = polygon.at(-1);
for (const p1 of polygon) {
xExtentsOfRectConstrainedByCenterAndHeightToLineSegment(result, p0, p1, cx, cy, height);
p0 = p1;
}
}
const { minX, maxX } = result;
if (Number.isFinite(minX) && Number.isFinite(maxX)) {
return { x: cx + (minX + maxX) / 2, width: maxX - minX };
} else {
return { x: cx, width: 0 };
}
}
// packages/ag-charts-enterprise/src/series/map-shape/mapShapeSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport171 } from "ag-charts-community";
import { Property as Property78 } from "ag-charts-core";
var { SeriesProperties: SeriesProperties6, makeSeriesTooltip: makeSeriesTooltip15 } = _ModuleSupport171;
var MapShapeSeriesProperties = class extends SeriesProperties6 {
constructor() {
super(...arguments);
this.topology = void 0;
this.idKey = "";
this.idName = void 0;
this.topologyIdKey = "name";
this.labelKey = void 0;
this.labelName = void 0;
this.colorRange = void 0;
this.fill = "black";
this.fillOpacity = 1;
this.stroke = "black";
this.strokeOpacity = 1;
this.strokeWidth = 0;
this.lineDash = [0];
this.lineDashOffset = 0;
this.padding = 0;
this.label = new AutoSizedSecondaryLabel();
this.tooltip = makeSeriesTooltip15();
}
getStyle() {
const { fill, fillOpacity, stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = this;
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
opacity: 1
};
}
};
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "topology", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "title", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "legendItemName", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "idKey", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "idName", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "topologyIdKey", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "labelKey", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "labelName", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "colorKey", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "colorName", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "colorRange", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "fill", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "stroke", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "padding", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "label", 2);
__decorateClass([
Property78
], MapShapeSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/map-shape/mapShapeSeries.ts
var {
getMissCount: getMissCount4,
createDatumId: createDatumId14,
SeriesNodePickMode: SeriesNodePickMode11,
valueProperty: valueProperty13,
ColorScale: ColorScale4,
Group: Group15,
Selection: Selection11,
Text: Text6,
PointerEvents: PointerEvents7,
getLabelStyles: getLabelStyles4
} = _ModuleSupport172;
var fixedScale = _ModuleSupport172.MercatorScale.fixedScale();
var MapShapeSeries = class extends TopologySeries {
constructor(moduleCtx) {
super({
moduleCtx,
categoryKey: void 0,
propertyKeys: {
color: ["colorKey"],
label: ["labelKey"]
},
propertyNames: {
color: ["colorName"],
label: ["labelName"]
},
pickModes: [SeriesNodePickMode11.EXACT_SHAPE_MATCH, SeriesNodePickMode11.NEAREST_NODE]
});
this.properties = new MapShapeSeriesProperties();
this._chartTopology = void 0;
this.colorScale = new ColorScale4();
this.itemGroup = this.contentGroup.appendChild(new Group15({ name: "itemGroup" }));
this.itemLabelGroup = this.contentGroup.appendChild(new Group15({ name: "itemLabelGroup" }));
this.datumSelection = Selection11.select(
this.itemGroup,
() => this.nodeFactory()
);
this.labelSelection = Selection11.select(
this.itemLabelGroup,
Text6
);
this.highlightDatumSelection = Selection11.select(
this.highlightNodeGroup,
() => this.nodeFactory()
);
this.highlightLabelSelection = Selection11.select(this.highlightLabelGroup, Text6);
this.previousLabelLayouts = void 0;
this._previousDatumMidPoint = void 0;
this.itemLabelGroup.pointerEvents = PointerEvents7.None;
}
getNodeData() {
return this.contextNodeData?.nodeData;
}
get topology() {
return this.properties.topology ?? this._chartTopology;
}
get hasData() {
return super.hasData && this.topology != null;
}
renderToOffscreenCanvas() {
return true;
}
setChartTopology(topology) {
this._chartTopology = topology;
if (this.topology === topology) {
this.nodeDataRefresh = true;
}
}
setZIndex(zIndex) {
super.setZIndex(zIndex);
this.contentGroup.zIndex = [1 /* ShapeLine */, zIndex];
this.highlightGroup.zIndex = [4 /* ShapeLineHighlight */, zIndex];
return true;
}
isLabelEnabled() {
return this.properties.labelKey != null && this.properties.label.enabled;
}
nodeFactory() {
const geoGeometry = new GeoGeometry();
geoGeometry.renderMode = 1 /* Polygons */;
geoGeometry.lineJoin = "round";
return geoGeometry;
}
async processData(dataController) {
if (this.data == null)
return;
const { data, topology, colorScale } = this;
const { topologyIdKey, idKey, colorKey, labelKey, colorRange } = this.properties;
const featureById = /* @__PURE__ */ new Map();
for (const feature of topology?.features.values() ?? []) {
const property = feature.properties?.[topologyIdKey];
if (property == null || !containsType(feature.geometry, 1 /* Polygon */))
continue;
featureById.set(property, feature);
}
const colorScaleType = this.colorScale.type;
const mercatorScaleType = this.scale?.type;
const { dataModel, processedData } = await this.requestDataModel(dataController, data, {
props: [
valueProperty13(idKey, mercatorScaleType, { id: "idValue", includeProperty: false }),
valueProperty13(idKey, mercatorScaleType, {
id: "featureValue",
includeProperty: false,
processor: () => (datum) => featureById.get(datum)
}),
...labelKey ? [valueProperty13(labelKey, "category", { id: "labelValue" })] : [],
...colorKey ? [valueProperty13(colorKey, colorScaleType, { id: "colorValue" })] : []
]
});
const featureValues = dataModel.resolveColumnById(this, `featureValue`, processedData);
this.topologyBounds = featureValues.reduce((current, feature) => {
const geometry = feature?.geometry;
if (geometry == null)
return current;
return geometryBbox(geometry, current);
}, void 0);
if (colorRange != null && this.isColorScaleValid()) {
const colorKeyIdx = dataModel.resolveProcessedDataIndexById(this, "colorValue");
colorScale.domain = processedData.domain.values[colorKeyIdx];
colorScale.range = colorRange;
colorScale.update();
}
if (topology == null) {
Logger20.warnOnce(`no topology was provided for [MapShapeSeries]; nothing will be rendered.`);
}
}
isColorScaleValid() {
const { colorKey } = this.properties;
if (!colorKey) {
return false;
}
const { dataModel, processedData } = this;
if (!dataModel || !processedData) {
return false;
}
const colorIdx = dataModel.resolveProcessedDataIndexById(this, "colorValue");
const dataCount = processedData.input.count;
const missCount = getMissCount4(this, processedData.defs.values[colorIdx].missing);
const colorDataMissing = dataCount === 0 || dataCount === missCount;
return !colorDataMissing;
}
getLabelLayout(datum, labelValue, measurer3, geometry, previousLabelLayout) {
if (labelValue == null || geometry == null)
return;
const { idKey, idName, colorKey, colorName, labelKey, labelName, padding: padding2, label } = this.properties;
if (labelKey == null || !label.enabled)
return;
const labelText = this.getLabelText(
labelValue,
datum,
labelKey,
"label",
[],
label,
{
value: labelValue,
datum,
idKey,
idName,
colorKey,
colorName,
labelKey,
labelName
}
);
if (labelText == null)
return;
const baseSize = isArray5(labelText) ? measureTextSegments4(labelText, label) : measurer3.measureLines(String(labelText));
const aspectRatio = (baseSize.width + 2 * padding2) / (baseSize.height + 2 * padding2);
if (previousLabelLayout?.geometry === geometry && previousLabelLayout?.labelText === labelText && previousLabelLayout?.aspectRatio === aspectRatio) {
return previousLabelLayout;
}
const fixedGeometry = projectGeometry(geometry, fixedScale);
const fixedPolygon = largestPolygon(fixedGeometry);
if (fixedPolygon == null)
return;
const labelPlacement = preferredLabelCenter(fixedPolygon, {
aspectRatio,
precision: 1e-3
});
if (labelPlacement == null)
return;
const { x, y, maxWidth } = labelPlacement;
return { geometry, labelText, aspectRatio, x, y, maxWidth, fixedPolygon };
}
getLabelDatum(labelLayout, scaling, datumIndex, idValue) {
const { scale } = this;
if (scale == null)
return;
const { padding: padding2, label } = this.properties;
const { labelText, aspectRatio, x: untruncatedX, y, maxWidth, fixedPolygon } = labelLayout;
const maxSizeWithoutTruncation = {
width: Math.ceil(maxWidth * scaling),
height: Math.ceil(maxWidth * scaling / aspectRatio),
meta: untruncatedX
};
const labelFormatting = formatSingleLabel(
toPlainText7(labelText),
label,
{ padding: padding2 },
(height, allowTruncation) => {
if (!allowTruncation) {
return maxSizeWithoutTruncation;
}
const result = maxWidthInPolygonForRectOfHeight(fixedPolygon, untruncatedX, y, height / scaling);
return {
width: result.width * scaling,
height,
meta: result.x
};
}
);
if (labelFormatting == null)
return;
const [{ text: text2, fontSize, lineHeight, width }, formattingX] = labelFormatting;
const x = width < maxSizeWithoutTruncation.width ? untruncatedX : formattingX;
const position = this.scale.convert(fixedScale.invert([x, y]));
return {
x: position[0],
y: position[1],
text: text2,
fontSize,
lineHeight,
datumIndex,
idValue,
datumId: createDatumId14(idValue)
};
}
resolveColumn(key, columnId, processedData) {
if (key == null || this.dataModel == null)
return void 0;
return this.dataModel.resolveColumnById(this, columnId, processedData);
}
resolveShapeDataColumns(processedData) {
const { colorKey, labelKey } = this.properties;
return {
idValues: this.dataModel.resolveColumnById(this, "idValue", processedData),
featureValues: this.dataModel.resolveColumnById(this, "featureValue", processedData),
labelValues: this.resolveColumn(labelKey, "labelValue", processedData),
colorValues: this.resolveColumn(colorKey, "colorValue", processedData)
};
}
warnMissingGeometries(missingGeometries) {
if (missingGeometries.length === 0)
return;
const missingGeometriesCap = 10;
if (missingGeometries.length > missingGeometriesCap) {
const excessItems = missingGeometries.length - missingGeometriesCap;
missingGeometries.length = missingGeometriesCap;
missingGeometries.push(`(+${excessItems} more)`);
}
Logger20.warnOnce(`some data items do not have matches in the provided topology`, missingGeometries);
}
createNodeData() {
const { id: seriesId, dataModel, processedData, properties, scale, previousLabelLayouts } = this;
const { label, legendItemName, colorKey } = properties;
if (dataModel == null || processedData == null)
return;
if (!this.visible) {
return { itemId: seriesId, nodeData: [], labelData: [] };
}
const scaling = scale == null ? Number.NaN : (scale.range[1][0] - scale.range[0][0]) / scale.bounds.width;
const columns = this.resolveShapeDataColumns(processedData);
const measurer3 = cachedTextMeasurer10(label);
const labelLayouts = /* @__PURE__ */ new Map();
this.previousLabelLayouts = labelLayouts;
const nodeData = [];
const labelData = [];
const missingGeometries = [];
const rawData = processedData.dataSources.get(this.id)?.data ?? [];
for (const [datumIndex, datum] of rawData.entries()) {
const dataValues = {
idValue: columns.idValues[datumIndex],
colorValue: columns.colorValues?.[datumIndex],
labelValue: columns.labelValues?.[datumIndex]
};
const geometry = columns.featureValues[datumIndex]?.geometry ?? void 0;
if (geometry == null) {
missingGeometries.push(dataValues.idValue);
}
if (colorKey != null && dataValues.colorValue == null) {
continue;
}
const labelLayout = this.getLabelLayout(
datum,
dataValues.labelValue,
measurer3,
geometry,
previousLabelLayouts?.get(dataValues.idValue)
);
if (labelLayout != null) {
labelLayouts.set(dataValues.idValue, labelLayout);
}
const labelDatum = labelLayout != null && scale != null ? this.getLabelDatum(labelLayout, scaling, datumIndex, dataValues.idValue) : void 0;
if (labelDatum != null) {
labelData.push(labelDatum);
}
const projectedGeometry = geometry != null && scale != null ? projectGeometry(geometry, scale) : void 0;
nodeData.push({
series: this,
datum,
datumIndex,
...dataValues,
projectedGeometry,
legendItemName,
style: this.getItemStyle({ datum, datumIndex, colorValue: dataValues.colorValue }, false)
});
}
this.warnMissingGeometries(missingGeometries);
return {
itemId: seriesId,
nodeData,
labelData
};
}
updateSelections() {
if (this.nodeDataRefresh) {
this.contextNodeData = this.createNodeData();
this.nodeDataRefresh = false;
}
}
update() {
const { datumSelection, labelSelection, highlightDatumSelection } = this;
this.updateSelections();
this.contentGroup.visible = this.visible;
this.labelGroup.visible = this.visible;
const drawingMode = this.ctx.chartService.highlight?.drawingMode ?? "overlay";
const highlightedDatum = this.getHighlightedDatum();
const nodeData = this.contextNodeData?.nodeData ?? [];
const labelData = this.contextNodeData?.labelData ?? [];
this.datumSelection = this.updateDatumSelection({ nodeData, datumSelection });
this.updateDatumStyles({ datumSelection, isHighlight: false });
this.updateDatumNodes({ datumSelection, drawingMode: "overlay" });
this.labelSelection = this.updateLabelSelection({ labelData, labelSelection });
const highlightLabelData = this.getHighlightLabelData(labelData, highlightedDatum);
this.highlightLabelSelection = this.updateLabelSelection({
labelData: highlightLabelData,
labelSelection: this.highlightLabelSelection
});
this.updateLabelNodes({ labelSelection: this.labelSelection, isHighlight: false });
this.updateLabelNodes({ labelSelection: this.highlightLabelSelection, isHighlight: true });
this.highlightDatumSelection = this.updateDatumSelection({
nodeData: highlightedDatum == null ? [] : [highlightedDatum],
datumSelection: highlightDatumSelection
});
this.updateDatumStyles({ datumSelection: highlightDatumSelection, isHighlight: true });
this.updateDatumNodes({ datumSelection: highlightDatumSelection, drawingMode });
}
getHighlightLabelData(labelData, highlightedDatum) {
if (labelData.length === 0)
return [];
const highlightId = createDatumId14(highlightedDatum?.idValue);
return labelData.filter(
(labelDatum) => labelDatum.datumId === highlightId && labelDatum.datumIndex === highlightedDatum?.datumIndex
);
}
updateDatumSelection(opts) {
return opts.datumSelection.update(opts.nodeData, void 0, (datum) => createDatumId14(datum.idValue));
}
getItemStyle({ datumIndex, datum, colorValue }, isHighlight) {
const { properties, colorScale } = this;
const { colorRange, itemStyler } = properties;
const baseStyle = properties.getStyle();
if (colorValue != null) {
const fillOverride = this.isColorScaleValid() ? colorScale.convert(colorValue) : colorRange?.[0];
if (fillOverride != null) {
baseStyle.fill = fillOverride;
}
}
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
let style = mergeDefaults16(highlightStyle, baseStyle);
if (itemStyler != null && datumIndex != null) {
const overrides = this.cachedDatumCallback(
createDatumId14(datumIndex, isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(datum, datumIndex, isHighlight, style);
return this.ctx.optionsGraphService.resolvePartial(
["series", `${this.declarationOrder}`],
this.callWithContext(itemStyler, params)
);
}
);
if (overrides) {
style = mergeDefaults16(overrides, style);
}
}
return style;
}
makeItemStylerParams(datum, datumIndex, isHighlight, style) {
const { id: seriesId } = this;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightState = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum,
highlightState,
...style,
fill
};
}
updateDatumStyles({
datumSelection,
isHighlight
}) {
datumSelection.each((_, nodeDatum) => {
nodeDatum.style = this.getItemStyle(nodeDatum, isHighlight);
});
}
updateDatumNodes({
datumSelection,
drawingMode
}) {
const fillBBox = getTopologyShapeFillBBox(this.scale);
datumSelection.each((geoGeometry, nodeDatum) => {
const { projectedGeometry } = nodeDatum;
if (projectedGeometry == null) {
geoGeometry.visible = false;
geoGeometry.projectedGeometry = void 0;
return;
}
geoGeometry.visible = true;
geoGeometry.projectedGeometry = projectedGeometry;
geoGeometry.setStyleProperties(nodeDatum.style, fillBBox);
geoGeometry.drawingMode = drawingMode;
});
}
updateLabelSelection(opts) {
const labels = this.isLabelEnabled() ? opts.labelData : [];
return opts.labelSelection.update(labels);
}
updateLabelNodes({
isHighlight,
labelSelection
}) {
const { properties } = this;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
labelSelection.each((label, labelDatum) => {
const { x, y, text: text2, fontSize, lineHeight, datumIndex } = labelDatum;
const style = getLabelStyles4(
this,
void 0,
properties,
properties.label,
isHighlight,
activeHighlight
);
const { color: fill, fontStyle, fontWeight, fontFamily } = style;
label.visible = true;
label.x = x;
label.y = y;
label.text = text2;
label.fill = fill;
label.fontStyle = fontStyle;
label.fontWeight = fontWeight;
label.fontSize = fontSize;
label.lineHeight = lineHeight;
label.fontFamily = fontFamily;
label.textAlign = "center";
label.textBaseline = "middle";
label.fillOpacity = this.getHighlightStyle(isHighlight, datumIndex).opacity ?? 1;
label.setBoxing(style);
});
}
resetAnimation() {
}
pickNodeClosestDatum({ x, y }) {
let minDistanceSquared = Infinity;
let minDatum;
this.datumSelection.each((node, datum) => {
const distanceSquared = node.distanceSquared(x, y);
if (distanceSquared < minDistanceSquared) {
minDistanceSquared = distanceSquared;
minDatum = datum;
}
});
return minDatum == null ? void 0 : { datum: minDatum, distance: Math.sqrt(minDistanceSquared) };
}
datumMidPoint(datum) {
const { _previousDatumMidPoint } = this;
if (_previousDatumMidPoint?.datum === datum) {
return _previousDatumMidPoint.point;
}
const projectedGeometry = datum.projectedGeometry;
const polygon = projectedGeometry == null ? void 0 : largestPolygon(projectedGeometry);
const center = polygon == null ? void 0 : polygonMarkerCenter(polygon, 2);
const point = center == null ? void 0 : { x: center[0], y: center[1] };
this._previousDatumMidPoint = { datum, point };
return point;
}
legendItemSymbol(datumIndex) {
const { dataModel, processedData, properties } = this;
const { fillOpacity, stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = properties;
let { fill } = properties;
if (datumIndex != null && this.isColorScaleValid()) {
const colorValues = dataModel.resolveColumnById(this, "colorValue", processedData);
const colorValue = colorValues[datumIndex];
if (colorValue != null) {
fill = this.colorScale.convert(colorValue);
}
}
return {
marker: {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
}
};
}
getLegendData(legendType) {
const { processedData, dataModel } = this;
if (processedData == null || dataModel == null)
return [];
const { id: seriesId, visible } = this;
const { title, legendItemName, idKey, idName, colorKey, colorRange, showInLegend } = this.properties;
if (legendType === "gradient" && colorKey != null && colorRange != null) {
const colorDomain = processedData.domain.values[dataModel.resolveProcessedDataIndexById(this, "colorValue")];
const legendDatum = {
legendType: "gradient",
enabled: visible,
seriesId,
series: this.getFormatterContext("color"),
colorRange,
colorDomain
};
return [legendDatum];
} else if (legendType === "category") {
const legendDatum = {
legendType: "category",
id: seriesId,
itemId: seriesId,
seriesId,
enabled: visible,
label: { text: legendItemName ?? title ?? idName ?? idKey },
symbol: this.legendItemSymbol(),
legendItemName,
hideInLegend: !showInLegend
};
return [legendDatum];
} else {
return [];
}
}
getTooltipContent(datumIndex) {
const {
id: seriesId,
dataModel,
processedData,
properties,
ctx: { formatManager }
} = this;
const { idKey, idName, colorKey, colorName, labelKey, labelName, legendItemName, title, tooltip } = properties;
if (!dataModel || !processedData)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const idValue = dataModel.resolveColumnById(this, `idValue`, processedData)[datumIndex];
const colorValue = colorKey == null ? void 0 : dataModel.resolveColumnById(this, `colorValue`, processedData)[datumIndex];
if (colorKey != null && colorValue == null) {
return;
}
const data = [];
if (this.isLabelEnabled() && labelKey != null && labelKey !== idKey) {
const labelValue = dataModel.resolveColumnById(this, `labelValue`, processedData)[datumIndex];
const content = formatManager.format(this.callWithContext.bind(this), {
type: "category",
value: labelValue,
datum,
seriesId,
legendItemName,
key: labelKey,
source: "tooltip",
property: "label",
domain: [],
boundSeries: this.getFormatterContext("label")
});
data.push({ label: labelName, fallbackLabel: labelKey, value: content ?? labelValue });
}
if (colorValue != null) {
const domain = dataModel.getDomain(this, `colorValue`, "value", processedData).domain;
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: colorValue,
datum,
seriesId,
legendItemName,
key: colorKey,
source: "tooltip",
property: "color",
domain,
boundSeries: this.getFormatterContext("color"),
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: colorName, fallbackLabel: colorKey, value: content ?? String(colorValue) });
}
const format = this.getItemStyle({ datum, datumIndex, colorValue }, false);
return this.formatTooltipWithContext(
tooltip,
{
heading: idValue,
title: title ?? legendItemName,
symbol: this.legendItemSymbol(datumIndex),
data
},
{ seriesId, datum, title, idKey, idName, colorKey, colorName, labelKey, labelName, ...format }
);
}
computeFocusBounds(opts) {
return findFocusedGeoGeometry(this, opts);
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.label.itemStyler != null;
}
};
MapShapeSeries.className = "MapShapeSeries";
MapShapeSeries.type = "map-shape";
// packages/ag-charts-enterprise/src/series/map-shape/mapShapeSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport173 } from "ag-charts-community";
import {
commonSeriesOptionsDefs as commonSeriesOptionsDefs13,
constant as constant14,
geoJson as geoJson4,
required as required14,
string as string15,
without as without8
} from "ag-charts-core";
var { mapShapeSeriesThemeableOptionsDef } = _ModuleSupport173;
var mapShapeSeriesOptionsDef = {
...without8(commonSeriesOptionsDefs13, ["highlightStyle", "highlight"]),
...mapShapeSeriesThemeableOptionsDef,
type: required14(constant14("map-shape")),
idKey: required14(string15),
colorKey: string15,
labelKey: string15,
idName: string15,
colorName: string15,
labelName: string15,
topology: geoJson4,
topologyIdKey: string15,
legendItemName: string15,
title: string15
};
// packages/ag-charts-enterprise/src/series/map-shape/mapShapeModule.ts
var MapShapeSeriesModule = {
type: "series",
name: "map-shape",
chartType: "topology",
enterprise: true,
version: VERSION39,
dependencies: [TopologyChartModule],
options: mapShapeSeriesOptionsDef,
themeTemplate: {
...MAP_THEME_DEFAULTS,
series: {
fill: applyMapPalette({
$applySwitch: [
{ $path: "type" },
{ $mapPalette: "fill" },
["gradient", FILL_GRADIENT_LINEAR_DEFAULTS5],
["image", FILL_IMAGE_DEFAULTS10],
["pattern", FILL_PATTERN_DEFAULTS6]
]
}),
stroke: { $ref: "chartBackgroundColor" },
colorRange: {
$if: [
{ $eq: [{ $mapPalette: "type" }, "inbuilt"] },
{ $mapPalette: "divergingColors" },
applyMapPalette(SAFE_RANGE2_OPERATION6)
]
},
fillOpacity: 1,
strokeWidth: 1,
lineDash: [0],
lineDashOffset: 0,
padding: 2,
label: {
...LABEL_BOXING_DEFAULTS11,
enabled: true,
color: { $ref: "chartBackgroundColor" },
fontFamily: { $ref: "fontFamily" },
fontSize: { $ref: "fontSize" },
fontWeight: "bold",
overflowStrategy: "hide"
},
highlight: applyMapPalette(MULTI_SERIES_HIGHLIGHT_STYLE6)
},
tooltip: {
range: "exact"
}
},
create: (ctx) => new MapShapeSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/map-shape-background/mapShapeBackgroundModule.ts
import { VERSION as VERSION40 } from "ag-charts-community";
import {
FILL_GRADIENT_LINEAR_HIERARCHY_DEFAULTS,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS11,
FILL_PATTERN_HIERARCHY_DEFAULTS
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/map-shape-background/mapShapeBackgroundSeries.ts
import { _ModuleSupport as _ModuleSupport175 } from "ag-charts-community";
import { Logger as Logger21 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/map-shape-background/mapShapeBackgroundSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport174 } from "ag-charts-community";
import { Property as Property79 } from "ag-charts-core";
var { SeriesProperties: SeriesProperties7, makeSeriesTooltip: makeSeriesTooltip16 } = _ModuleSupport174;
var MapShapeBackgroundSeriesProperties = class extends SeriesProperties7 {
constructor() {
super(...arguments);
this.topology = void 0;
this.fill = "black";
this.fillOpacity = 1;
this.stroke = "black";
this.strokeOpacity = 1;
this.strokeWidth = 0;
this.lineDash = [0];
this.lineDashOffset = 0;
this.tooltip = makeSeriesTooltip16();
}
};
__decorateClass([
Property79
], MapShapeBackgroundSeriesProperties.prototype, "topology", 2);
__decorateClass([
Property79
], MapShapeBackgroundSeriesProperties.prototype, "fill", 2);
__decorateClass([
Property79
], MapShapeBackgroundSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property79
], MapShapeBackgroundSeriesProperties.prototype, "stroke", 2);
__decorateClass([
Property79
], MapShapeBackgroundSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property79
], MapShapeBackgroundSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property79
], MapShapeBackgroundSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
Property79
], MapShapeBackgroundSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property79
], MapShapeBackgroundSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/map-shape-background/mapShapeBackgroundSeries.ts
var { createDatumId: createDatumId15, Selection: Selection12, Group: Group16, PointerEvents: PointerEvents8 } = _ModuleSupport175;
var MapShapeBackgroundSeries = class extends TopologySeries {
constructor(moduleCtx) {
super({
moduleCtx,
categoryKey: void 0,
pickModes: []
});
this.properties = new MapShapeBackgroundSeriesProperties();
this._chartTopology = void 0;
this.itemGroup = this.contentGroup.appendChild(new Group16({ name: "itemGroup" }));
this.datumSelection = Selection12.select(
this.itemGroup,
() => this.nodeFactory()
);
this.itemGroup.pointerEvents = PointerEvents8.None;
}
get topology() {
return this.properties.topology ?? this._chartTopology;
}
get focusable() {
return false;
}
setOptionsData() {
}
setChartData() {
}
getNodeData() {
return;
}
get hasData() {
return false;
}
renderToOffscreenCanvas() {
return true;
}
setChartTopology(topology) {
this._chartTopology = topology;
if (this.topology === topology) {
this.nodeDataRefresh = true;
}
}
setZIndex(zIndex) {
super.setZIndex(zIndex);
this.contentGroup.zIndex = [0 /* ShapeLineBackground */, zIndex, 0];
this.highlightGroup.zIndex = [0 /* ShapeLineBackground */, zIndex, 1];
return true;
}
nodeFactory() {
const geoGeometry = new GeoGeometry();
geoGeometry.renderMode = 1 /* Polygons */;
geoGeometry.lineJoin = "round";
geoGeometry.pointerEvents = PointerEvents8.None;
return geoGeometry;
}
processData() {
const { topology } = this;
this.topologyBounds = topology?.features.reduce((current, feature) => {
const geometry = feature.geometry;
if (geometry == null)
return current;
return geometryBbox(geometry, current);
}, void 0);
if (topology == null) {
Logger21.warnOnce(`no topology was provided for [MapShapeBackgroundSeries]; nothing will be rendered.`);
}
}
createNodeData() {
const { id: seriesId, topology, scale, properties } = this;
if (topology == null)
return;
const { fill, fillOpacity, stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = properties;
const nodeData = [];
const labelData = [];
for (const [index, feature] of topology.features.entries()) {
const { geometry } = feature;
const projectedGeometry = geometry != null && scale != null ? projectGeometry(geometry, scale) : void 0;
if (projectedGeometry == null)
continue;
nodeData.push({
series: this,
datum: feature,
datumIndex: 0,
index,
projectedGeometry,
style: { fill, fillOpacity, stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset }
});
}
return {
itemId: seriesId,
nodeData,
labelData
};
}
updateSelections() {
if (this.nodeDataRefresh) {
this.contextNodeData = this.createNodeData();
this.nodeDataRefresh = false;
}
}
update() {
const { datumSelection } = this;
this.updateSelections();
this.contentGroup.visible = this.visible;
this.labelGroup.visible = this.visible;
const { nodeData = [] } = this.contextNodeData ?? {};
this.datumSelection = this.updateDatumSelection({ nodeData, datumSelection });
this.updateDatumNodes({ datumSelection });
}
updateDatumSelection(opts) {
return opts.datumSelection.update(opts.nodeData, void 0, (datum) => createDatumId15(datum.index));
}
updateDatumNodes(opts) {
const { datumSelection } = opts;
datumSelection.each((geoGeometry, datum) => {
const { projectedGeometry } = datum;
if (projectedGeometry == null) {
geoGeometry.visible = false;
geoGeometry.projectedGeometry = void 0;
return;
}
geoGeometry.visible = true;
geoGeometry.projectedGeometry = projectedGeometry;
geoGeometry.setProperties(datum.style);
});
}
resetAnimation() {
}
getLegendData() {
return [];
}
getTooltipContent(_seriesDatum) {
return;
}
pickFocus() {
return void 0;
}
computeFocusBounds(_opts) {
return void 0;
}
hasItemStylers() {
return false;
}
};
MapShapeBackgroundSeries.className = "MapShapeBackgroundSeries";
MapShapeBackgroundSeries.type = "map-shape-background";
// packages/ag-charts-enterprise/src/series/map-shape-background/mapShapeBackgroundSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport176 } from "ag-charts-community";
import { commonSeriesOptionsDefs as commonSeriesOptionsDefs14, constant as constant15, geoJson as geoJson5, required as required15 } from "ag-charts-core";
var { mapShapeBackgroundSeriesThemeableOptionsDef } = _ModuleSupport176;
var mapShapeBackgroundSeriesOptionsDef = {
...mapShapeBackgroundSeriesThemeableOptionsDef,
...commonSeriesOptionsDefs14,
type: required15(constant15("map-shape-background")),
topology: geoJson5
};
// packages/ag-charts-enterprise/src/series/map-shape-background/mapShapeBackgroundModule.ts
var MapShapeBackgroundSeriesModule = {
type: "series",
name: "map-shape-background",
chartType: "topology",
enterprise: true,
version: VERSION40,
dependencies: [TopologyChartModule],
options: mapShapeBackgroundSeriesOptionsDef,
themeTemplate: {
...MAP_THEME_DEFAULTS,
series: {
fill: applyMapPalette({
$applySwitch: [
{ $path: "type" },
{ $path: ["/1", { $mapPalette: "fill" }, { $mapPalette: "hierarchyColors" }] },
["gradient", FILL_GRADIENT_LINEAR_HIERARCHY_DEFAULTS],
["image", FILL_IMAGE_DEFAULTS11],
["pattern", FILL_PATTERN_HIERARCHY_DEFAULTS]
]
}),
stroke: { $ref: "chartBackgroundColor" },
strokeWidth: 1
}
},
create: (ctx) => new MapShapeBackgroundSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/nightingale/nightingaleModule.ts
import { PolarChartModule, VERSION as VERSION41 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection46, POLAR_AXIS_TYPE as POLAR_AXIS_TYPE2 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/nightingale/nightingaleSeries.ts
import { _ModuleSupport as _ModuleSupport182 } from "ag-charts-community";
import { PolarZIndexMap } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnSeriesBase.ts
import { _ModuleSupport as _ModuleSupport178 } from "ag-charts-community";
import {
ChartAxisDirection as ChartAxisDirection45,
isDefined as isDefined3,
isGradientFill as isGradientFill2,
normalizeAngle360 as normalizeAngle3605
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/util/radialUtil.ts
import { _ModuleSupport as _ModuleSupport177 } from "ag-charts-community";
import { mergeDefaults as mergeDefaults17 } from "ag-charts-core";
var { createDatumId: createDatumId16, toHighlightString: toHighlightString4 } = _ModuleSupport177;
function makeStylerParams(series, highlightStateEnum) {
const { id: seriesId } = series;
const {
angleKey,
cornerRadius,
fill,
fillOpacity,
lineDash,
lineDashOffset,
radiusKey,
stackGroup,
stroke: stroke3,
strokeOpacity,
strokeWidth
} = series.properties;
const highlightState = toHighlightString4(highlightStateEnum ?? _ModuleSupport177.HighlightState.None);
return {
angleKey,
cornerRadius,
fill,
fillOpacity,
highlightState,
lineDash,
lineDashOffset,
radiusKey,
seriesId,
stackGroup,
stroke: stroke3,
strokeOpacity,
strokeWidth
};
}
function getStyle(series, ignoreStylerCallback, highlightState) {
const { styler } = series.properties;
let stylerResult = {};
if (!ignoreStylerCallback && styler) {
const stylerParams = makeStylerParams(series, highlightState);
stylerResult = series.ctx.optionsGraphService.resolvePartial(
["series", `${series.declarationOrder}`],
series.cachedCallWithContext(styler, stylerParams) ?? {},
{ pick: false }
) ?? {};
}
return {
cornerRadius: stylerResult.cornerRadius ?? series.properties.cornerRadius,
fill: stylerResult.fill ?? series.properties.fill,
fillOpacity: stylerResult.fillOpacity ?? series.properties.fillOpacity,
lineDash: stylerResult.lineDash ?? series.properties.lineDash,
lineDashOffset: stylerResult.lineDashOffset ?? series.properties.lineDashOffset,
stroke: stylerResult.stroke ?? series.properties.stroke,
strokeOpacity: stylerResult.strokeOpacity ?? series.properties.strokeOpacity,
strokeWidth: stylerResult.strokeWidth ?? series.properties.strokeWidth,
opacity: 1
};
}
function makeItemStylerParams(series, nodeDatum, isHighlight, style) {
const { id: seriesId, properties } = series;
const { angleKey, radiusKey } = properties;
const activeHighlight = series.ctx.highlightManager?.getActiveHighlight();
const highlightStateString = series.getHighlightStateString(activeHighlight, isHighlight, nodeDatum.datumIndex);
const fill = series.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum: nodeDatum.datum,
highlightState: highlightStateString,
angleKey,
radiusKey,
...style,
fill
};
}
function getItemStyle(series, nodeDatum, isHighlight, highlightState) {
const { properties } = series;
const { itemStyler } = properties;
const highlightStyle = series.getHighlightStyle(isHighlight, nodeDatum?.datumIndex, highlightState);
const baseStyle = mergeDefaults17(highlightStyle, getStyle(series, nodeDatum === void 0, highlightState));
let style = baseStyle;
if (itemStyler != null && nodeDatum != null) {
const overrides = series.cachedDatumCallback(
createDatumId16(series.getDatumId(nodeDatum), isHighlight ? "highlight" : "node"),
() => {
const params = makeItemStylerParams(series, nodeDatum, isHighlight, style);
return series.callWithContext(itemStyler, params);
}
);
if (overrides) {
style = mergeDefaults17(overrides, style);
}
}
return style;
}
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnSeriesBase.ts
var {
DEFAULT_POLAR_DIRECTION_KEYS,
DEFAULT_POLAR_DIRECTION_NAMES,
PolarAxis,
diff: diff6,
fixNumericExtent: fixNumericExtent8,
groupAccumulativeValueProperty: groupAccumulativeValueProperty2,
keyProperty: keyProperty9,
normaliseGroupTo,
resetLabelFn: resetLabelFn5,
seriesLabelFadeInAnimation: seriesLabelFadeInAnimation5,
seriesLabelFadeOutAnimation,
valueProperty: valueProperty14,
animationValidation: animationValidation7,
createDatumId: createDatumId17,
SeriesNodePickMode: SeriesNodePickMode12,
CategoryScale: CategoryScale3,
motion: motion6,
updateLabelNode: updateLabelNode6,
getItemStyles: getItemStyles3
} = _ModuleSupport178;
var RadialColumnSeriesNodeEvent = class extends _ModuleSupport178.SeriesNodeEvent {
constructor(type, nativeEvent, datum, series) {
super(type, nativeEvent, datum, series);
this.angleKey = series.properties.angleKey;
this.radiusKey = series.properties.radiusKey;
}
};
var RadialColumnSeriesBase = class extends _ModuleSupport178.PolarSeries {
constructor(moduleCtx, {
animationResetFns
}) {
super({
moduleCtx,
categoryKey: "angleValue",
propertyKeys: DEFAULT_POLAR_DIRECTION_KEYS,
propertyNames: DEFAULT_POLAR_DIRECTION_NAMES,
canHaveAxes: true,
pickModes: [SeriesNodePickMode12.NEAREST_NODE, SeriesNodePickMode12.EXACT_SHAPE_MATCH],
animationResetFns: {
...animationResetFns,
label: resetLabelFn5
}
});
this.NodeEvent = RadialColumnSeriesNodeEvent;
this.groupScale = new CategoryScale3();
this.circleCache = { r: 0, cx: 0, cy: 0 };
}
getSeriesDomain(direction) {
const { dataModel, processedData } = this;
if (!processedData || !dataModel)
return { domain: [] };
if (direction === ChartAxisDirection45.Angle) {
return dataModel.getDomain(this, "angleValue", "key", processedData);
} else {
const yExtent = dataModel.getDomain(this, "radiusValue-end", "value", processedData).domain;
const fixedYExtent = Number.isFinite(yExtent[1] - yExtent[0]) ? [Math.min(yExtent[0], 0), Math.max(yExtent[1], 0)] : [];
return { domain: fixNumericExtent8(fixedYExtent) };
}
}
async processData(dataController) {
const { angleKey, radiusKey, normalizedTo } = this.properties;
const animationEnabled = !this.ctx.animationManager.isSkipped();
const stackGroupId = this.getStackId();
const stackGroupTrailingId = `${stackGroupId}-trailing`;
const extraProps = [];
if (isDefined3(normalizedTo)) {
extraProps.push(normaliseGroupTo([stackGroupId, stackGroupTrailingId], Math.abs(normalizedTo)));
}
if (this.needsDataModelDiff() && this.processedData) {
extraProps.push(diff6(this.id, this.processedData));
}
if (animationEnabled) {
extraProps.push(animationValidation7());
}
const visibleProps = this.visible ? {} : { forceValue: 0 };
const radiusScaleType = this.axes[ChartAxisDirection45.Radius]?.scale.type;
const angleScaleType = this.axes[ChartAxisDirection45.Angle]?.scale.type;
const allowNullKey = this.properties.allowNullKeys ?? false;
await this.requestDataModel(dataController, this.data, {
props: [
keyProperty9(angleKey, angleScaleType, { id: "angleValue", allowNullKey }),
valueProperty14(radiusKey, radiusScaleType, {
id: "radiusValue-raw",
invalidValue: null,
...visibleProps
}),
...groupAccumulativeValueProperty2(
radiusKey,
"normal",
{
id: `radiusValue-end`,
rangeId: `radiusValue-range`,
invalidValue: null,
groupId: stackGroupId,
separateNegative: true,
...visibleProps
},
radiusScaleType
),
...groupAccumulativeValueProperty2(
radiusKey,
"trailing",
{
id: `radiusValue-start`,
invalidValue: null,
groupId: stackGroupTrailingId,
separateNegative: true,
...visibleProps
},
radiusScaleType
),
...extraProps
],
groupByKeys: true,
groupByData: false
});
this.animationState.transition("updateData");
}
didCircleChange() {
const r = this.radius;
const cx = this.centerX;
const cy = this.centerY;
const cache = this.circleCache;
if (r !== cache.r || cx !== cache.cx || cy !== cache.cy) {
this.circleCache = { r, cx, cy };
return true;
}
return false;
}
isRadiusAxisReversed() {
return this.axes[ChartAxisDirection45.Radius]?.isReversed();
}
maybeRefreshNodeData() {
const circleChanged = this.didCircleChange();
if (!circleChanged && !this.nodeDataRefresh)
return;
this.contextNodeData = this.createNodeData();
this.nodeData = this.contextNodeData?.nodeData ?? [];
this.nodeDataRefresh = false;
}
getAxisInnerRadius() {
const radiusAxis = this.axes[ChartAxisDirection45.Radius];
return radiusAxis instanceof PolarAxis ? this.radius * radiusAxis.innerRadiusRatio : 0;
}
createNodeData() {
const { processedData, dataModel, groupScale } = this;
if (!dataModel || processedData?.type !== "grouped")
return;
const angleAxis = this.axes[ChartAxisDirection45.Angle];
const radiusAxis = this.axes[ChartAxisDirection45.Radius];
const angleScale = angleAxis?.scale;
const radiusScale = radiusAxis?.scale;
if (!angleScale || !radiusScale) {
return;
}
const angleValues = dataModel.resolveKeysById(this, `angleValue`, processedData);
const radiusStartValues = dataModel.resolveColumnById(this, `radiusValue-start`, processedData);
const radiusEndValues = dataModel.resolveColumnById(this, `radiusValue-end`, processedData);
const radiusRawValues = dataModel.resolveColumnById(this, `radiusValue-raw`, processedData);
let groupPaddingInner = 0;
let groupPaddingOuter = 0;
if (angleAxis instanceof AngleCategoryAxis) {
groupPaddingInner = angleAxis.groupPaddingInner;
groupPaddingOuter = angleAxis.paddingInner;
}
const groupAngleStep = angleScale.bandwidth ?? 0;
const paddedGroupAngleStep = groupAngleStep * (1 - groupPaddingOuter);
const { index: groupIndex, visibleGroupCount } = this.ctx.seriesStateManager.getVisiblePeerGroupIndex(this);
groupScale.domain = Array.from({ length: visibleGroupCount }).map((_, i) => String(i));
groupScale.range = [-paddedGroupAngleStep / 2, paddedGroupAngleStep / 2];
groupScale.paddingInner = visibleGroupCount > 1 ? groupPaddingInner : 0;
const radiusAxisReversed = this.isRadiusAxisReversed();
const axisInnerRadius = this.getAxisInnerRadius();
const axisOuterRadius = this.radius;
const axisTotalRadius = axisOuterRadius + axisInnerRadius;
const { angleKey, radiusKey, angleName, radiusName, legendItemName, label } = this.properties;
const radiusDomain = this.getSeriesDomain(ChartAxisDirection45.Radius).domain;
const getLabelNodeDatum = (datum, radiusDatum, x, y) => {
const labelText = this.getLabelText(
radiusDatum,
datum,
radiusKey,
"radius",
radiusDomain,
label,
{ value: radiusDatum, datum, angleKey, radiusKey, angleName, radiusName, legendItemName }
);
if (labelText) {
return { x, y, text: labelText, textAlign: "center", textBaseline: "middle" };
}
};
const nodeData = [];
const styles = getItemStyles3(
(nodeDatum, isHighlight, highlightState) => getItemStyle(this, nodeDatum, isHighlight, highlightState)
);
const context = {
itemId: radiusKey,
nodeData,
labelData: nodeData,
styles
};
if (!this.visible)
return context;
const { dataSources } = processedData;
const rawData = dataSources.get(this.id)?.data ?? [];
for (const { datumIndex } of dataModel.forEachGroupDatum(this, processedData)) {
const datum = rawData[datumIndex];
const angleDatum = angleValues[datumIndex];
if (angleDatum === void 0 && !this.properties.allowNullKeys)
return;
const radiusDatum = radiusRawValues[datumIndex];
const isPositive = radiusDatum >= 0 && !Object.is(radiusDatum, -0);
const innerRadiusDatum = radiusStartValues[datumIndex];
const outerRadiusDatum = radiusEndValues[datumIndex];
const negative = isPositive === radiusAxisReversed;
if (innerRadiusDatum === void 0 || outerRadiusDatum === void 0)
return;
let startAngle;
let endAngle;
let angle;
if (rawData.length === 1) {
startAngle = -0.5 * Math.PI;
endAngle = 1.5 * Math.PI;
angle = startAngle;
} else {
const groupAngle = angleScale.convert(angleDatum);
startAngle = normalizeAngle3605(groupAngle + groupScale.convert(String(groupIndex)));
endAngle = normalizeAngle3605(startAngle + groupScale.bandwidth);
angle = startAngle + groupScale.bandwidth / 2;
}
const innerRadius = axisTotalRadius - radiusScale.convert(innerRadiusDatum);
const outerRadius = axisTotalRadius - radiusScale.convert(outerRadiusDatum);
const midRadius = (innerRadius + outerRadius) / 2;
const x = Math.cos(angle) * midRadius;
const y = Math.sin(angle) * midRadius;
const labelNodeDatum = this.properties.label.enabled ? getLabelNodeDatum(datum, radiusDatum, x, y) : void 0;
const columnWidth = this.getColumnWidth(startAngle, endAngle);
nodeData.push({
series: this,
datum,
datumIndex,
point: { x, y, size: 0 },
midPoint: { x, y },
label: labelNodeDatum,
angleValue: angleDatum,
radiusValue: radiusDatum,
negative,
innerRadius,
outerRadius,
stackInnerRadius: innerRadius,
stackOuterRadius: outerRadius,
startAngle,
endAngle,
midAngle: angle,
axisInnerRadius,
axisOuterRadius,
columnWidth,
index: datumIndex
});
}
return {
itemId: radiusKey,
nodeData,
labelData: nodeData,
styles
};
}
getColumnWidth(_startAngle, _endAngle) {
return Number.NaN;
}
update({ seriesRect }) {
const resize = this.checkResize(seriesRect);
this.maybeRefreshNodeData();
this.contentGroup.translationX = this.centerX;
this.contentGroup.translationY = this.centerY;
this.highlightGroup.translationX = this.centerX;
this.highlightGroup.translationY = this.centerY;
if (this.labelGroup) {
this.labelGroup.translationX = this.centerX;
this.labelGroup.translationY = this.centerY;
}
this.updateSectorSelection(this.itemSelection, false);
this.updateSectorSelection(this.highlightSelection, true);
this.updateLabels();
if (resize) {
this.animationState.transition("resize");
}
this.animationState.transition("update");
}
updateSectorSelection(selection, isHighlight) {
const { contextNodeData } = this;
if (!contextNodeData) {
return;
}
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
let selectionData = [];
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
if (isHighlight) {
if (activeHighlight?.datum && activeHighlight.series === this) {
selectionData.push(activeHighlight);
}
} else {
selectionData = this.nodeData;
}
const radiusAxisReversed = this.isRadiusAxisReversed();
const axisInnerRadius = radiusAxisReversed ? this.radius : this.getAxisInnerRadius();
const axisOuterRadius = radiusAxisReversed ? this.getAxisInnerRadius() : this.radius;
const fillBBox = this.getShapeFillBBox();
const hasItemStylers = this.hasItemStylers();
selection.update(selectionData, void 0, (datum) => this.getDatumId(datum)).each((node, nodeDatum) => {
const { midPoint } = nodeDatum;
if (hasItemStylers) {
const highlightState = this.getHighlightState(activeHighlight, isHighlight, nodeDatum.datumIndex);
nodeDatum.style = getItemStyle(this, nodeDatum, isHighlight, highlightState);
}
const style = nodeDatum.style ?? contextNodeData.styles[this.getHighlightState(highlightedDatum, isHighlight, nodeDatum.datumIndex)];
const fill = style.fill;
const itemBounds = isGradientFill2(fill) && fill.bounds === "item";
const fillParams = itemBounds ? { centerX: midPoint?.x ?? 0, centerY: midPoint?.y ?? 0 } : { centerX: 0, centerY: 0, innerRadius: axisInnerRadius, outerRadius: axisOuterRadius };
this.updateItemPath(node, nodeDatum, isHighlight);
node.setStyleProperties(style, fillBBox, fillParams);
node.cornerRadius = style.cornerRadius ?? 0;
node.lineJoin = "round";
});
}
updateLabels() {
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightDatum = activeHighlight?.series === this && activeHighlight?.datum ? activeHighlight : void 0;
const highlightData = highlightDatum ? [highlightDatum] : [];
this.labelSelection.update(this.nodeData).each((node, datum) => {
updateLabelNode6(this, node, this.properties, this.properties.label, datum.label, false, activeHighlight);
node.fillOpacity = this.getHighlightStyle(false, datum.datumIndex).opacity ?? 1;
});
this.highlightLabelSelection.update(highlightData, void 0, (datum) => this.getDatumId(datum)).each((node, datum) => {
updateLabelNode6(this, node, this.properties, this.properties.label, datum.label, true, activeHighlight);
node.fillOpacity = this.getHighlightStyle(true, datum.datumIndex).opacity ?? 1;
});
}
animateEmptyUpdateReady() {
const { labelSelection } = this;
const fns = this.getColumnTransitionFunctions();
motion6.fromToMotion(this.id, "datums", this.ctx.animationManager, [this.itemSelection], fns);
seriesLabelFadeInAnimation5(
this,
"labels",
this.ctx.animationManager,
labelSelection,
this.highlightLabelSelection
);
}
animateClearingUpdateEmpty() {
const { itemSelection } = this;
const { animationManager } = this.ctx;
const fns = this.getColumnTransitionFunctions();
motion6.fromToMotion(this.id, "datums", animationManager, [itemSelection], fns);
seriesLabelFadeOutAnimation(
this,
"labels",
animationManager,
this.labelSelection,
this.highlightLabelSelection
);
}
getTooltipContent(datumIndex) {
const { id: seriesId, dataModel, processedData, axes, properties } = this;
const { angleKey, angleName, radiusKey, radiusName, legendItemName, tooltip } = properties;
const angleAxis = axes[ChartAxisDirection45.Angle];
const radiusAxis = axes[ChartAxisDirection45.Radius];
const nodeDatum = this.nodeData?.[datumIndex];
if (!dataModel || !processedData || !angleAxis || !radiusAxis || !nodeDatum)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const angleValue = dataModel.resolveKeysById(this, `angleValue`, processedData)[datumIndex];
const radiusValue = dataModel.resolveColumnById(this, `radiusValue-raw`, processedData)[datumIndex];
if (angleValue === void 0 && !this.properties.allowNullKeys)
return;
const format = getItemStyle(this, nodeDatum, false);
return this.formatTooltipWithContext(
tooltip,
{
heading: this.getAxisValueText(angleAxis, "tooltip", angleValue, datum, angleKey, void 0),
symbol: this.legendItemSymbol(),
data: [
{
label: radiusName,
fallbackLabel: radiusKey,
value: this.getAxisValueText(radiusAxis, "tooltip", radiusValue, datum, radiusKey, void 0),
missing: _ModuleSupport178.isTooltipValueMissing(radiusValue)
}
]
},
{
seriesId,
datum,
title: angleName,
angleKey,
angleName,
radiusKey,
radiusName,
legendItemName,
...format
}
);
}
pickNodeClosestDatum(point) {
return this.pickNodeNearestDistantObject(point, this.itemSelection.nodes());
}
legendItemSymbol() {
const { fill, stroke: stroke3, fillOpacity, strokeOpacity, strokeWidth, lineDash, lineDashOffset } = getStyle(
this,
false,
_ModuleSupport178.HighlightState.None
);
const markerStyle = {
fill: fill ?? "rgba(0, 0, 0, 0)",
stroke: stroke3 ?? "rgba(0, 0, 0, 0)",
fillOpacity,
strokeOpacity,
strokeWidth,
lineDash,
lineDashOffset
};
if (isGradientFill2(markerStyle.fill)) {
markerStyle.fill = { ...markerStyle.fill, gradient: "linear", rotation: 0, reverse: false };
}
return {
marker: markerStyle
};
}
getLegendData(legendType) {
if (legendType !== "category") {
return [];
}
const { id: seriesId, visible } = this;
const { radiusKey, radiusName, legendItemName, showInLegend } = this.properties;
return [
{
legendType: "category",
id: seriesId,
itemId: radiusKey,
seriesId,
enabled: visible,
label: {
text: legendItemName ?? radiusName ?? radiusKey
},
symbol: this.legendItemSymbol(),
legendItemName,
hideInLegend: !showInLegend
}
];
}
getDatumId(datum) {
return createDatumId17(datum.angleValue);
}
computeLabelsBBox() {
return null;
}
};
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnSeriesBaseProperties.ts
import { _ModuleSupport as _ModuleSupport179 } from "ag-charts-community";
import { Property as Property80 } from "ag-charts-core";
var { SeriesProperties: SeriesProperties8, makeSeriesTooltip: makeSeriesTooltip17, Label: Label12 } = _ModuleSupport179;
var RadialColumnSeriesBaseProperties = class extends SeriesProperties8 {
constructor() {
super(...arguments);
this.angleKeyAxis = "angle";
this.radiusKeyAxis = "radius";
this.fill = "black";
this.fillOpacity = 1;
this.stroke = "black";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.cornerRadius = 0;
this.rotation = 0;
this.label = new Label12();
this.tooltip = makeSeriesTooltip17();
}
getStyle() {
const { fill, fillOpacity, stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset, cornerRadius } = this;
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
cornerRadius,
opacity: 1
};
}
};
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "angleKey", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "angleName", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "radiusKey", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "radiusName", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "angleKeyAxis", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "radiusKeyAxis", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "legendItemName", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "fill", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "stroke", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "lineDash", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "cornerRadius", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "styler", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "itemStyler", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "rotation", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "stackGroup", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "normalizedTo", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "label", 2);
__decorateClass([
Property80
], RadialColumnSeriesBaseProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/nightingale/nightingaleUtil.ts
import { _ModuleSupport as _ModuleSupport181 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnUtil.ts
import { _ModuleSupport as _ModuleSupport180 } from "ag-charts-community";
var { motion: motion7 } = _ModuleSupport180;
function createAngleMotionCalculator() {
const angles = {
startAngle: /* @__PURE__ */ new Map(),
endAngle: /* @__PURE__ */ new Map()
};
const angleKeys = ["startAngle", "endAngle"];
const calculate = (node, datum, status) => {
for (const key of angleKeys) {
const map = angles[key];
let from2 = (status === "removed" || status === "updated" ? node : datum)[key];
let to2 = (status === "removed" ? node : datum)[key];
if (Number.isNaN(to2)) {
to2 = node.previousDatum?.[key] ?? Number.NaN;
}
const diff8 = from2 - to2;
if (Math.abs(diff8) > Math.PI) {
from2 -= Math.sign(diff8) * 2 * Math.PI;
}
map.set(datum, { from: from2, to: to2 });
}
};
const getAngles = (datum, fromToKey) => {
return {
startAngle: angles.startAngle.get(datum)[fromToKey],
endAngle: angles.endAngle.get(datum)[fromToKey]
};
};
const from = (datum) => getAngles(datum, "from");
const to = (datum) => getAngles(datum, "to");
return { calculate, from, to };
}
function fixRadialColumnAnimationStatus(node, datum, status) {
if (status === "updated") {
if (node.previousDatum == null || Number.isNaN(node.previousDatum.startAngle) || Number.isNaN(node.previousDatum.endAngle)) {
return "added";
}
if (Number.isNaN(datum.startAngle) || Number.isNaN(datum.endAngle)) {
return "removed";
}
}
if (status === "added" && node.previousDatum != null) {
return "updated";
}
return status;
}
function prepareRadialColumnAnimationFunctions(axisZeroRadius) {
const angles = createAngleMotionCalculator();
const fromFn = (node, datum, status) => {
status = fixRadialColumnAnimationStatus(node, datum, status);
angles.calculate(node, datum, status);
const { startAngle, endAngle } = angles.from(datum);
let innerRadius;
let outerRadius;
let columnWidth;
let axisInnerRadius;
let axisOuterRadius;
if (status === "removed" || status === "updated") {
innerRadius = node.innerRadius;
outerRadius = node.outerRadius;
columnWidth = node.columnWidth;
axisInnerRadius = node.axisInnerRadius;
axisOuterRadius = node.axisOuterRadius;
} else {
innerRadius = axisZeroRadius;
outerRadius = axisZeroRadius;
columnWidth = datum.columnWidth;
axisInnerRadius = datum.axisInnerRadius;
axisOuterRadius = datum.axisOuterRadius;
}
const phase = motion7.NODE_UPDATE_STATE_TO_PHASE_MAPPING[status];
return {
innerRadius,
outerRadius,
columnWidth,
axisInnerRadius,
axisOuterRadius,
startAngle,
endAngle,
phase
};
};
const toFn = (node, datum, status) => {
const { startAngle, endAngle } = angles.to(datum);
let innerRadius;
let outerRadius;
let columnWidth;
let axisInnerRadius;
let axisOuterRadius;
if (status === "removed") {
innerRadius = node.innerRadius;
outerRadius = node.innerRadius;
columnWidth = node.columnWidth;
axisInnerRadius = node.axisInnerRadius;
axisOuterRadius = node.axisOuterRadius;
} else {
innerRadius = Number.isNaN(datum.innerRadius) ? axisZeroRadius : datum.innerRadius;
outerRadius = Number.isNaN(datum.outerRadius) ? axisZeroRadius : datum.outerRadius;
columnWidth = Number.isNaN(datum.columnWidth) ? node.columnWidth : datum.columnWidth;
axisInnerRadius = datum.axisInnerRadius;
axisOuterRadius = datum.axisOuterRadius;
}
return { innerRadius, outerRadius, columnWidth, axisInnerRadius, axisOuterRadius, startAngle, endAngle };
};
return { toFn, fromFn };
}
function resetRadialColumnSelectionFn(_node, {
innerRadius,
outerRadius,
columnWidth,
axisInnerRadius,
axisOuterRadius,
startAngle,
endAngle
}) {
return { innerRadius, outerRadius, columnWidth, axisInnerRadius, axisOuterRadius, startAngle, endAngle };
}
// packages/ag-charts-enterprise/src/series/nightingale/nightingaleUtil.ts
var { SectorBox, motion: motion8 } = _ModuleSupport181;
function getRadii(datum) {
const { negative, innerRadius, outerRadius, stackInnerRadius, stackOuterRadius } = datum;
return {
innerRadius: negative ? stackOuterRadius : stackInnerRadius,
outerRadius: negative ? stackInnerRadius : stackOuterRadius,
clipInnerRadius: negative ? outerRadius : innerRadius,
clipOuterRadius: negative ? innerRadius : outerRadius
};
}
function prepareNightingaleAnimationFunctions(axisZeroRadius) {
const angles = createAngleMotionCalculator();
const fromFn = (sect, datum, status) => {
status = fixRadialColumnAnimationStatus(sect, datum, status);
angles.calculate(sect, datum, status);
const { startAngle, endAngle } = angles.from(datum);
let innerRadius;
let outerRadius;
let clipSector;
if (status === "removed" || status === "updated") {
innerRadius = sect.innerRadius;
outerRadius = sect.outerRadius;
clipSector = sect.clipSector;
} else {
innerRadius = axisZeroRadius;
outerRadius = axisZeroRadius;
}
clipSector ?? (clipSector = new SectorBox(startAngle, endAngle, innerRadius, outerRadius));
const phase = motion8.NODE_UPDATE_STATE_TO_PHASE_MAPPING[status];
return { innerRadius, outerRadius, startAngle, endAngle, clipSector, phase };
};
const toFn = (_sect, datum, status) => {
const { startAngle, endAngle } = angles.to(datum);
let innerRadius;
let outerRadius;
let clipSector;
if (status === "removed") {
innerRadius = axisZeroRadius;
outerRadius = axisZeroRadius;
clipSector = new SectorBox(startAngle, endAngle, innerRadius, outerRadius);
} else {
let clipInnerRadius, clipOuterRadius;
({ innerRadius, outerRadius, clipInnerRadius, clipOuterRadius } = getRadii(datum));
if (Number.isNaN(innerRadius))
innerRadius = axisZeroRadius;
if (Number.isNaN(outerRadius))
outerRadius = axisZeroRadius;
if (Number.isNaN(clipInnerRadius))
clipInnerRadius = axisZeroRadius;
if (Number.isNaN(clipOuterRadius))
clipOuterRadius = axisZeroRadius;
clipSector = new SectorBox(startAngle, endAngle, clipInnerRadius, clipOuterRadius);
}
return { innerRadius, outerRadius, startAngle, endAngle, clipSector };
};
return { toFn, fromFn };
}
function resetNightingaleSelectionFn(_sect, datum) {
const { startAngle, endAngle } = datum;
const { innerRadius, outerRadius, clipInnerRadius, clipOuterRadius } = getRadii(datum);
const clipSector = new SectorBox(startAngle, endAngle, clipInnerRadius, clipOuterRadius);
return { innerRadius, outerRadius, startAngle, endAngle, clipSector };
}
// packages/ag-charts-enterprise/src/series/nightingale/nightingaleSeries.ts
var { Sector: Sector4, SectorBox: SectorBox2 } = _ModuleSupport182;
var NightingaleSeries = class extends RadialColumnSeriesBase {
// TODO: Enable once the options contract has been revisited
// @TempValidate
// sectorSpacing = 1;
constructor(moduleCtx) {
super(moduleCtx, { animationResetFns: { item: resetNightingaleSelectionFn } });
this.properties = new RadialColumnSeriesBaseProperties();
}
setZIndex(zIndex) {
super.setZIndex(zIndex);
this.contentGroup.zIndex = [0, PolarZIndexMap.FOREGROUND, zIndex];
this.highlightGroup.zIndex = [0, PolarZIndexMap.HIGHLIGHT, zIndex];
this.labelGroup.zIndex = [0, PolarZIndexMap.LABEL, zIndex];
return true;
}
getStackId() {
const groupIndex = this.seriesGrouping?.groupIndex ?? this.id;
return `nightingale-stack-${groupIndex}-yValues`;
}
nodeFactory() {
return new Sector4();
}
updateItemPath(node, datum, highlight) {
const { negative } = datum;
node.centerX = 0;
node.centerY = 0;
node.startOuterCornerRadius = negative ? 0 : this.properties.cornerRadius;
node.endOuterCornerRadius = negative ? 0 : this.properties.cornerRadius;
node.startInnerCornerRadius = negative ? this.properties.cornerRadius : 0;
node.endInnerCornerRadius = negative ? this.properties.cornerRadius : 0;
if (highlight) {
const { startAngle, endAngle } = datum;
const { innerRadius, outerRadius, clipInnerRadius, clipOuterRadius } = getRadii(datum);
node.innerRadius = innerRadius;
node.outerRadius = outerRadius;
node.startAngle = startAngle;
node.endAngle = endAngle;
node.clipSector = new SectorBox2(startAngle, endAngle, clipInnerRadius, clipOuterRadius);
}
}
getColumnTransitionFunctions() {
const axisZeroRadius = this.isRadiusAxisReversed() ? this.radius : this.getAxisInnerRadius();
return prepareNightingaleAnimationFunctions(axisZeroRadius);
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.styler != null || this.properties.label.itemStyler != null;
}
};
NightingaleSeries.className = "NightingaleSeries";
NightingaleSeries.type = "nightingale";
// packages/ag-charts-enterprise/src/series/nightingale/nightingaleSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport183 } from "ag-charts-community";
import {
boolean as boolean17,
commonSeriesOptionsDefs as commonSeriesOptionsDefs15,
constant as constant16,
number as number8,
required as required16,
string as string16,
undocumented as undocumented12
} from "ag-charts-core";
var { nightingaleSeriesThemeableOptionsDef } = _ModuleSupport183;
var nightingaleSeriesOptionsDef = {
...commonSeriesOptionsDefs15,
...nightingaleSeriesThemeableOptionsDef,
type: required16(constant16("nightingale")),
angleKey: required16(string16),
radiusKey: required16(string16),
angleName: string16,
radiusName: string16,
legendItemName: string16,
grouped: boolean17,
stacked: boolean17,
stackGroup: string16,
normalizedTo: number8
};
nightingaleSeriesOptionsDef.angleKeyAxis = undocumented12(string16);
nightingaleSeriesOptionsDef.radiusKeyAxis = undocumented12(string16);
// packages/ag-charts-enterprise/src/series/nightingale/nightingaleThemes.ts
import {
FILL_GRADIENT_RADIAL_SERIES_DEFAULTS,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS12,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS7,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS12,
MULTI_SERIES_HIGHLIGHT_STYLE as MULTI_SERIES_HIGHLIGHT_STYLE7,
POLAR_AXIS_SHAPE,
POLAR_AXIS_TYPE
} from "ag-charts-core";
var NIGHTINGALE_SERIES_THEME = {
series: {
fill: {
$applySwitch: [
{ $path: "type" },
{ $palette: "fill" },
["gradient", FILL_GRADIENT_RADIAL_SERIES_DEFAULTS],
["image", FILL_IMAGE_DEFAULTS12],
["pattern", FILL_PATTERN_DEFAULTS7]
]
},
stroke: {
$if: [{ $eq: [{ $palette: "type" }, "inbuilt"] }, { $ref: "chartBackgroundColor" }, { $palette: "stroke" }]
},
strokeWidth: 1,
label: {
...LABEL_BOXING_DEFAULTS12,
enabled: false,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "textColor" }
},
highlight: { ...MULTI_SERIES_HIGHLIGHT_STYLE7, bringToFront: false }
},
axes: {
[POLAR_AXIS_TYPE.ANGLE_CATEGORY]: {
shape: { $findFirstSiblingNotOperation: POLAR_AXIS_SHAPE.CIRCLE },
groupPaddingInner: 0,
paddingInner: 0,
label: {
spacing: 10
}
},
[POLAR_AXIS_TYPE.RADIUS_NUMBER]: {
shape: { $findFirstSiblingNotOperation: POLAR_AXIS_SHAPE.CIRCLE }
}
}
};
// packages/ag-charts-enterprise/src/series/nightingale/nightingaleModule.ts
var NightingaleSeriesModule = {
type: "series",
name: "nightingale",
chartType: "polar",
enterprise: true,
stackable: true,
groupable: true,
stackedByDefault: true,
version: VERSION41,
dependencies: [PolarChartModule],
options: nightingaleSeriesOptionsDef,
defaultAxes: { angle: { type: POLAR_AXIS_TYPE2.ANGLE_CATEGORY }, radius: { type: POLAR_AXIS_TYPE2.RADIUS_NUMBER } },
axisKeys: { [ChartAxisDirection46.X]: "xKeyAxis", [ChartAxisDirection46.Y]: "yKeyAxis" },
themeTemplate: NIGHTINGALE_SERIES_THEME,
create: (ctx) => new NightingaleSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/pyramid/pyramidModule.ts
import { VERSION as VERSION42 } from "ag-charts-community";
// packages/ag-charts-enterprise/src/series/pyramid/pyramidSeries.ts
import {
_ModuleSupport as _ModuleSupport185
} from "ag-charts-community";
import {
StateMachine as StateMachine14,
cachedTextMeasurer as cachedTextMeasurer11,
isArray as isArray6,
measureTextSegments as measureTextSegments5,
mergeDefaults as mergeDefaults18,
toPlainText as toPlainText8,
toTextString as toTextString4
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/pyramid/pyramidProperties.ts
import { _ModuleSupport as _ModuleSupport184 } from "ag-charts-community";
import { Property as Property81 } from "ag-charts-core";
var { SeriesProperties: SeriesProperties9, makeSeriesTooltip: makeSeriesTooltip18, Label: Label13, DropShadow: DropShadow5 } = _ModuleSupport184;
var PyramidSeriesLabel = class extends Label13 {
};
var PyramidSeriesStageLabel = class extends Label13 {
constructor() {
super(...arguments);
this.spacing = 0;
}
};
__decorateClass([
Property81
], PyramidSeriesStageLabel.prototype, "spacing", 2);
__decorateClass([
Property81
], PyramidSeriesStageLabel.prototype, "placement", 2);
var PyramidProperties = class extends SeriesProperties9 {
constructor() {
super(...arguments);
this.fills = [];
this.fillOpacity = 1;
this.strokes = [];
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.direction = "vertical";
this.reverse = void 0;
this.spacing = 0;
this.aspectRatio = void 0;
this.shadow = new DropShadow5().set({ enabled: false });
this.label = new PyramidSeriesLabel();
this.stageLabel = new PyramidSeriesStageLabel();
this.tooltip = makeSeriesTooltip18();
}
getStyle(index = 0) {
const { fills, strokes, fillOpacity, strokeWidth, strokeOpacity, lineDash, lineDashOffset } = this;
return {
fill: fills[index % fills.length],
fillOpacity,
stroke: strokes[index % strokes.length],
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
opacity: 1
};
}
};
__decorateClass([
Property81
], PyramidProperties.prototype, "stageKey", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "valueKey", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "fills", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "strokes", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "lineDash", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "direction", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "reverse", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "spacing", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "aspectRatio", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "itemStyler", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "shadow", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "label", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "stageLabel", 2);
__decorateClass([
Property81
], PyramidProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/pyramid/pyramidUtil.ts
function applyPyramidDatum(connector, { x, y, top, right, bottom, left }) {
connector.x0 = x - top / 2;
connector.x1 = x + top / 2;
connector.x2 = x + bottom / 2;
connector.x3 = x - bottom / 2;
connector.y0 = y - left / 2;
connector.y1 = y - right / 2;
connector.y2 = y + right / 2;
connector.y3 = y + left / 2;
}
function preparePyramidAnimationFunctions(direction) {
const fromFn = (_connector, datum) => {
const { x, y } = datum;
let { top, right, bottom, left } = datum;
if (direction === "vertical") {
top = 0;
bottom = 0;
} else {
left = 0;
right = 0;
}
return { x, y, top, right, bottom, left };
};
const toFn = (_connector, datum) => {
const { x, y, top, right, bottom, left } = datum;
return { x, y, top, right, bottom, left };
};
const applyFn = applyPyramidDatum;
return { fromFn, toFn, applyFn };
}
// packages/ag-charts-enterprise/src/series/pyramid/pyramidSeries.ts
var {
valueProperty: valueProperty15,
SeriesNodePickMode: SeriesNodePickMode13,
createDatumId: createDatumId18,
BBox: BBox23,
Group: Group17,
Selection: Selection13,
Text: Text7,
PointerEvents: PointerEvents9,
fromToMotion: fromToMotion4,
seriesLabelFadeInAnimation: seriesLabelFadeInAnimation6,
getLabelStyles: getLabelStyles5
} = _ModuleSupport185;
var PyramidSeries = class extends _ModuleSupport185.DataModelSeries {
constructor(moduleCtx) {
super({
moduleCtx,
categoryKey: void 0,
pickModes: [SeriesNodePickMode13.EXACT_SHAPE_MATCH, SeriesNodePickMode13.NEAREST_NODE]
});
this.properties = new PyramidProperties();
this.itemGroup = this.contentGroup.appendChild(new Group17({ name: "itemGroup" }));
this.itemLabelGroup = this.contentGroup.appendChild(new Group17({ name: "itemLabelGroup" }));
this.stageLabelGroup = this.contentGroup.appendChild(new Group17({ name: "stageLabelGroup" }));
this.datumSelection = Selection13.select(
this.itemGroup,
() => this.nodeFactory()
);
this.labelSelection = Selection13.select(
this.itemLabelGroup,
Text7
);
this.stageLabelSelection = Selection13.select(this.stageLabelGroup, Text7);
this.highlightLabelSelection = Selection13.select(this.highlightLabelGroup, Text7);
this.highlightDatumSelection = Selection13.select(
this.highlightNodeGroup,
() => this.nodeFactory()
);
this.animationState = new StateMachine14(
"empty",
{
empty: {
update: {
target: "ready",
action: () => this.animateEmptyUpdateReady()
},
reset: "empty",
skip: "ready"
},
ready: {
clear: "empty",
reset: "empty",
skip: "ready"
}
},
() => this.checkProcessedDataAnimatable()
);
this.itemLabelGroup.pointerEvents = PointerEvents9.None;
this.stageLabelGroup.pointerEvents = PointerEvents9.None;
this.cleanup.register(this.ctx.eventsHub.on("legend:item-click", (event) => this.onLegendItemClick(event)));
}
nodeFactory() {
return new FunnelConnector();
}
getNodeData() {
return this.contextNodeData?.nodeData;
}
resetAnimation(phase) {
if (phase === "initial") {
this.animationState.transition("reset");
} else if (phase === "ready") {
this.animationState.transition("skip");
}
}
async processData(dataController) {
if (this.data == null)
return;
const {
id: seriesId,
visible,
ctx: { legendManager }
} = this;
const { stageKey, valueKey } = this.properties;
const xScaleType = "category";
const yScaleType = "number";
const validation = (_value, _datum, index) => visible && legendManager.getItemEnabled({ seriesId, itemId: index });
const visibleProps = this.visible ? {} : { forceValue: 0 };
const allowNullKey = this.properties.allowNullKeys ?? false;
await this.requestDataModel(dataController, this.data, {
props: [
valueProperty15(stageKey, xScaleType, { id: "xValue", allowNullKey }),
valueProperty15(valueKey, yScaleType, { id: `yValue`, ...visibleProps, validation, invalidValue: 0 })
]
});
}
createNodeData() {
const {
id: seriesId,
dataModel,
processedData,
properties,
visible,
ctx: { legendManager }
} = this;
const {
stageKey,
valueKey,
direction,
reverse = direction === "horizontal",
spacing,
aspectRatio,
label,
stageLabel
} = properties;
if (dataModel == null || processedData == null)
return;
const horizontal = direction === "horizontal";
const xValues = dataModel.resolveColumnById(this, `xValue`, processedData);
const yValues = dataModel.resolveColumnById(this, `yValue`, processedData);
const xDomain = dataModel.getDomain(this, "xValue", "value", processedData).domain;
const yDomain = dataModel.getDomain(this, "yValue", "value", processedData).domain;
const textMeasurer = cachedTextMeasurer11(stageLabel);
let textAlign;
let textBaseline;
if (horizontal) {
textAlign = "center";
textBaseline = stageLabel.placement === "before" ? "bottom" : "top";
} else {
textAlign = stageLabel.placement === "after" ? "left" : "right";
textBaseline = "middle";
}
const stageLabelData = stageLabel.enabled ? [] : void 0;
let maxLabelWidth = 0;
let maxLabelHeight = 0;
let yTotal = 0;
const rawData = processedData.dataSources.get(this.id)?.data ?? [];
for (const [datumIndex, datum] of rawData.entries()) {
const xValue = xValues[datumIndex];
if (xValue === void 0 && !this.properties.allowNullKeys)
continue;
const yValue = yValues[datumIndex];
const enabled = visible && legendManager.getItemEnabled({ seriesId, itemId: datumIndex });
yTotal += yValue;
if (stageLabelData == null)
continue;
const text2 = this.getLabelText(
xValue,
datum,
stageKey,
"x",
xDomain,
this.properties.stageLabel,
{ datum, value: yValue, stageKey, valueKey },
this.properties.allowNullKeys ?? false
);
const { width, height } = isArray6(text2) ? measureTextSegments5(text2, label) : textMeasurer.measureLines(toTextString4(text2));
maxLabelWidth = Math.max(maxLabelWidth, width);
maxLabelHeight = Math.max(maxLabelHeight, height);
stageLabelData.push({
x: Number.NaN,
y: Number.NaN,
text: text2,
textAlign,
textBaseline,
visible: enabled
});
}
const seriesRectWidth = this._nodeDataDependencies?.seriesRectWidth ?? 0;
const seriesRectHeight = this._nodeDataDependencies?.seriesRectHeight ?? 0;
const totalSpacing = spacing * (processedData.input.count - 1);
let bounds;
if (horizontal) {
const verticalInset = maxLabelHeight + stageLabel.spacing;
bounds = new BBox23(
0,
stageLabel.placement === "before" ? verticalInset : 0,
seriesRectWidth,
seriesRectHeight - verticalInset
);
} else {
const horizontalInset = maxLabelWidth + stageLabel.spacing;
bounds = new BBox23(
stageLabel.placement === "after" ? 0 : horizontalInset,
0,
seriesRectWidth - horizontalInset,
seriesRectHeight
);
}
if (aspectRatio != null && aspectRatio !== 0) {
const directionalAspectRatio = direction === "horizontal" ? 1 / aspectRatio : aspectRatio;
const constrainedWidth = Math.min(bounds.width, bounds.height * directionalAspectRatio);
const constrainedHeight = constrainedWidth / directionalAspectRatio;
bounds = new BBox23(
bounds.x + (bounds.width - constrainedWidth) / 2,
bounds.y + (bounds.height - constrainedHeight) / 2,
constrainedWidth,
constrainedHeight
);
}
let labelX;
let labelY;
if (horizontal) {
labelY = stageLabel.placement === "before" ? bounds.y - stageLabel.spacing : bounds.y + bounds.height + stageLabel.spacing;
} else {
labelX = stageLabel.placement === "after" ? bounds.x + bounds.width + stageLabel.spacing : bounds.x - stageLabel.spacing;
}
const availableWidth = bounds.width - (horizontal ? totalSpacing : 0);
const availableHeight = bounds.height - (horizontal ? 0 : totalSpacing);
if (availableWidth < 0 || availableHeight < 0)
return;
const nodeData = [];
const labelData = [];
let yStart = 0;
let stageLabelIndex = 0;
for (const [datumIndex, datum] of rawData.entries()) {
const xValue = xValues[datumIndex];
if (xValue === void 0 && !this.properties.allowNullKeys)
continue;
const yValue = yValues[datumIndex];
const enabled = visible && legendManager.getItemEnabled({ seriesId, itemId: datumIndex });
const yEnd = yStart + yValue;
const yMidRatio = (yStart + yEnd) / (2 * yTotal);
const yRangeRatio = (yEnd - yStart) / yTotal;
const xOffset = horizontal ? availableWidth * yMidRatio + spacing * datumIndex : availableWidth * 0.5;
const yOffset = horizontal ? availableHeight * 0.5 : availableHeight * yMidRatio + spacing * datumIndex;
const x = bounds.x + xOffset;
const y = bounds.y + yOffset;
if (stageLabelData != null) {
const stageLabelDatum = stageLabelData[stageLabelIndex++];
stageLabelDatum.x = labelX ?? x;
stageLabelDatum.y = labelY ?? y;
}
let top;
let right;
let bottom;
let left;
if (horizontal) {
const barWidth = availableWidth * yRangeRatio;
top = barWidth;
bottom = barWidth;
const y0 = (xOffset + barWidth / 2) * (availableHeight / bounds.width);
const y1 = (xOffset - barWidth / 2) * (availableHeight / bounds.width);
right = reverse ? bounds.height - y0 : y0;
left = reverse ? bounds.height - y1 : y1;
} else {
const barHeight = availableHeight * yRangeRatio;
right = barHeight;
left = barHeight;
const x0 = (yOffset - barHeight / 2) * (availableWidth / bounds.height);
const x1 = (yOffset + barHeight / 2) * (availableWidth / bounds.height);
top = reverse ? bounds.width - x0 : x0;
bottom = reverse ? bounds.width - x1 : x1;
}
const text2 = this.getLabelText(
yValue,
datum,
valueKey,
"y",
yDomain,
label,
{
datum,
value: yValue,
stageKey,
valueKey
}
);
const labelDatum = {
x,
y,
text: text2,
textAlign: "center",
textBaseline: "middle",
visible: enabled
};
labelData.push(labelDatum);
nodeData.push({
series: this,
datum,
datumIndex,
index: datumIndex,
xValue,
yValue,
x,
y,
top,
right,
bottom,
left,
label: labelDatum,
enabled,
midPoint: {
x,
y
},
style: this.getItemStyle({ datumIndex, datum }, false)
});
yStart = yEnd;
}
return {
itemId: seriesId,
nodeData,
labelData,
stageLabelData,
bounds
};
}
updateSelections() {
if (this.nodeDataRefresh) {
this.contextNodeData = this.createNodeData();
this.nodeDataRefresh = false;
}
}
update({ seriesRect }) {
this.checkResize(seriesRect);
const {
datumSelection,
labelSelection,
stageLabelSelection,
highlightDatumSelection,
highlightLabelSelection
} = this;
this.updateSelections();
this.contentGroup.visible = this.visible;
this.contentGroup.opacity = this.getOpacity();
let highlightedDatum = this.ctx.highlightManager?.getActiveHighlight();
if (highlightedDatum != null && (highlightedDatum.series !== this || highlightedDatum.datum == null)) {
highlightedDatum = void 0;
}
const nodeData = this.contextNodeData?.nodeData ?? [];
const labelData = this.contextNodeData?.labelData ?? [];
const stageLabelData = this.contextNodeData?.stageLabelData ?? [];
this.datumSelection = this.updateDatumSelection({ nodeData, datumSelection });
this.updateDatumStyles({ datumSelection, isHighlight: false });
this.updateDatumNodes({ datumSelection, isHighlight: false });
this.labelSelection = this.updateLabelSelection({ labelData, labelSelection });
this.updateLabelNodes({ labelSelection, labelProperties: this.properties.label });
this.stageLabelSelection = this.updateStageLabelSelection({ stageLabelData, stageLabelSelection });
this.updateLabelNodes({
labelSelection: stageLabelSelection,
labelProperties: this.properties.stageLabel,
checkActiveHighlight: true
});
const highlightLabelData = this.getHighlightLabelData(labelData, highlightedDatum) ?? [];
this.highlightLabelSelection = highlightLabelSelection.update(highlightLabelData);
this.updateLabelNodes({
labelSelection: this.highlightLabelSelection,
labelProperties: this.properties.label,
isHighlight: true
});
this.highlightDatumSelection = this.updateDatumSelection({
nodeData: highlightedDatum == null ? [] : [highlightedDatum],
datumSelection: highlightDatumSelection
});
this.updateDatumStyles({ datumSelection: highlightDatumSelection, isHighlight: true });
this.updateDatumNodes({ datumSelection: highlightDatumSelection, isHighlight: true });
this.animationState.transition("update");
}
updateDatumSelection(opts) {
return opts.datumSelection.update(opts.nodeData);
}
getItemStyle({ datumIndex, datum }, isHighlight) {
const { properties } = this;
const { itemStyler } = properties;
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
const baseStyle = mergeDefaults18(highlightStyle, properties.getStyle(datumIndex));
let style = baseStyle;
if (itemStyler != null && datumIndex != null) {
const overrides = this.cachedDatumCallback(
createDatumId18(datumIndex, isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(datum, datumIndex, isHighlight, style);
return this.callWithContext(itemStyler, params);
}
);
if (overrides) {
style = mergeDefaults18(overrides, style);
}
}
return style;
}
makeItemStylerParams(datum, datumIndex, isHighlight, style) {
const { id: seriesId, properties } = this;
const { stageKey, valueKey } = properties;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightState = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum,
stageKey,
valueKey,
highlightState,
...style,
fill
};
}
updateDatumStyles({
datumSelection,
isHighlight
}) {
datumSelection.each((_, nodeDatum) => {
nodeDatum.style = this.getItemStyle(nodeDatum, isHighlight);
});
}
updateDatumNodes({
datumSelection
}) {
const { properties } = this;
const { shadow } = properties;
const bounds = this.contextNodeData?.bounds;
const fillBBox = bounds ? { series: bounds, axis: bounds } : void 0;
datumSelection.each((connector, nodeDatum) => {
connector.setStyleProperties(nodeDatum.style, fillBBox);
applyPyramidDatum(connector, nodeDatum);
connector.fillShadow = shadow;
});
}
updateLabelSelection(opts) {
return opts.labelSelection.update(this.properties.label.enabled ? opts.labelData : []);
}
updateStageLabelSelection(opts) {
return opts.stageLabelSelection.update(opts.stageLabelData);
}
updateLabelNodes(opts) {
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const { labelSelection, labelProperties, isHighlight = false, checkActiveHighlight = false } = opts;
labelSelection.each((label, nodeDatum, datumIndex) => {
const { visible, x, y, text: text2, textAlign, textBaseline } = nodeDatum;
const datumIsHighlighted = isHighlight || checkActiveHighlight && activeHighlight?.datumIndex === datumIndex;
const highlightStyle = this.getHighlightStyle(datumIsHighlighted, datumIndex);
const style = getLabelStyles5(
this,
void 0,
this.properties,
labelProperties,
datumIsHighlighted,
activeHighlight
);
const { color: fill, fontSize, fontStyle, fontWeight, fontFamily } = style;
label.visible = visible;
label.x = x;
label.y = y;
label.text = text2;
label.fill = fill;
label.opacity = (highlightStyle.opacity ?? 1) * (style.fillOpacity ?? 1);
label.fillOpacity = (highlightStyle.opacity ?? 1) * (style.fillOpacity ?? 1);
label.fontStyle = fontStyle;
label.fontWeight = fontWeight;
label.fontSize = fontSize;
label.fontFamily = fontFamily;
label.textAlign = textAlign;
label.textBaseline = textBaseline;
label.setBoxing(style);
});
}
getHighlightLabelData(_labelData, highlightedItem) {
if (highlightedItem?.label) {
return [{ ...highlightedItem.label }];
}
return void 0;
}
computeFocusBounds(opts) {
const datum = this.getNodeData()?.[opts.datumIndex];
if (datum === void 0)
return;
for (const node of this.datumSelection) {
if (node.datum === datum) {
return node.node;
}
}
}
getTooltipContent(datumIndex) {
const { id: seriesId, dataModel, processedData, properties } = this;
const { stageKey, valueKey, tooltip } = properties;
if (!dataModel || !processedData)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const xValue = dataModel.resolveColumnById(this, "xValue", processedData)[datumIndex];
const yValue = dataModel.resolveColumnById(this, `yValue`, processedData)[datumIndex];
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (xValue === void 0 && !allowNullKeys)
return;
const label = this.getLabelText(
xValue,
datum,
stageKey,
"x",
dataModel.getDomain(this, "xValue", "value", processedData).domain,
this.properties.stageLabel,
{ datum, value: xValue, stageKey, valueKey }
);
const format = this.getItemStyle({ datumIndex, datum }, false);
return this.formatTooltipWithContext(
tooltip,
{
symbol: this.legendItemSymbol(datumIndex),
data: [{ label: toPlainText8(label), value: toPlainText8(yValue) }]
},
{
seriesId,
datum,
title: void 0,
stageKey,
valueKey,
...format
}
);
}
getSeriesDomain() {
return { domain: [Number.NaN, Number.NaN] };
}
getSeriesRange() {
return [Number.NaN, Number.NaN];
}
pickNodeClosestDatum({ x, y }) {
let minDistanceSquared = Infinity;
let minDatum;
this.datumSelection.each((node, datum) => {
const distanceSquared = node.distanceSquared(x, y);
if (distanceSquared < minDistanceSquared) {
minDistanceSquared = distanceSquared;
minDatum = datum;
}
});
return minDatum == null ? void 0 : { datum: minDatum, distance: Math.sqrt(minDistanceSquared) };
}
legendItemSymbol(datumIndex) {
const { fills, strokes, strokeWidth, fillOpacity, strokeOpacity, lineDash, lineDashOffset } = this.properties;
const fill = fills[datumIndex] ?? "black";
const stroke3 = strokes[datumIndex] ?? "black";
return {
marker: {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
}
};
}
getLegendData(legendType) {
const {
processedData,
dataModel,
id: seriesId,
ctx: { legendManager },
visible
} = this;
if (!dataModel || !processedData || legendType !== "category") {
return [];
}
const { showInLegend } = this.properties;
const stageValues = dataModel.resolveColumnById(this, `xValue`, processedData);
return (processedData.dataSources.get(this.id)?.data ?? []).map((datum, datumIndex) => {
const stageValue = stageValues[datumIndex];
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (stageValue == null && !allowNullKeys)
return;
return {
legendType: "category",
id: seriesId,
datum,
itemId: datumIndex,
seriesId,
enabled: visible && legendManager.getItemEnabled({ seriesId, itemId: datumIndex }),
label: { text: String(stageValue) },
symbol: this.legendItemSymbol(datumIndex),
hideInLegend: !showInLegend
};
}).filter((datum) => datum != null);
}
animateReset() {
this.ctx.animationManager.skipCurrentBatch();
this.ctx.animationManager.stopByAnimationGroupId(this.id);
}
animateEmptyUpdateReady() {
const { datumSelection, labelSelection, properties } = this;
const fns = preparePyramidAnimationFunctions(properties.direction);
fromToMotion4(this.id, "nodes", this.ctx.animationManager, [datumSelection], fns);
seriesLabelFadeInAnimation6(this, "labels", this.ctx.animationManager, labelSelection);
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.label.itemStyler != null;
}
};
PyramidSeries.className = "PyramidSeries";
PyramidSeries.type = "pyramid";
// packages/ag-charts-enterprise/src/series/pyramid/pyramidSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport186 } from "ag-charts-community";
import { commonSeriesOptionsDefs as commonSeriesOptionsDefs16, constant as constant17, required as required17, string as string17 } from "ag-charts-core";
var { pyramidSeriesThemeableOptionsDef } = _ModuleSupport186;
var pyramidSeriesOptionsDef = {
...pyramidSeriesThemeableOptionsDef,
...commonSeriesOptionsDefs16,
type: required17(constant17("pyramid")),
stageKey: required17(string17),
valueKey: required17(string17)
};
// packages/ag-charts-enterprise/src/series/pyramid/pyramidThemes.ts
import {
DEFAULT_SHADOW_COLOUR as DEFAULT_SHADOW_COLOUR2,
FILL_GRADIENT_LINEAR_DEFAULTS as FILL_GRADIENT_LINEAR_DEFAULTS6,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS13,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS8,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS13
} from "ag-charts-core";
var PYRAMID_SERIES_THEME = {
series: {
direction: "vertical",
strokeWidth: { $isUserOption: ["./strokes/0", 2, 0] },
spacing: 2,
fills: {
$applyCycle: [
{ $size: { $path: ["./data", { $path: "/data" }] } },
{ $palette: "fills" },
{
$applySwitch: [
{ $path: ["/type", void 0, { $value: "$1" }] },
{ $value: "$1" },
["gradient", FILL_GRADIENT_LINEAR_DEFAULTS6],
["pattern", FILL_PATTERN_DEFAULTS8],
["image", FILL_IMAGE_DEFAULTS13]
]
}
]
},
strokes: {
$applyCycle: [{ $size: { $path: ["./data", { $path: "/data" }] } }, { $palette: "strokes" }]
},
label: {
...LABEL_BOXING_DEFAULTS13,
enabled: true,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "chartBackgroundColor" }
},
stageLabel: {
...LABEL_BOXING_DEFAULTS13,
enabled: true,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "textColor" },
spacing: 12
},
shadow: {
enabled: false,
color: DEFAULT_SHADOW_COLOUR2,
xOffset: 3,
yOffset: 3,
blur: 5
},
highlight: {
unhighlightedItem: {
opacity: 0.4
}
}
}
};
// packages/ag-charts-enterprise/src/series/pyramid/pyramidModule.ts
var PyramidSeriesModule = {
type: "series",
name: "pyramid",
chartType: "standalone",
enterprise: true,
solo: true,
version: VERSION42,
dependencies: [StandaloneChartModule],
options: pyramidSeriesOptionsDef,
themeTemplate: PYRAMID_SERIES_THEME,
create: (ctx) => new PyramidSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/radar-area/radarAreaModule.ts
import { PolarChartModule as PolarChartModule2, VERSION as VERSION43 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection49, POLAR_AXIS_TYPE as POLAR_AXIS_TYPE4 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radar/radarThemes.ts
import {
FILL_GRADIENT_LINEAR_DEFAULTS as FILL_GRADIENT_LINEAR_DEFAULTS7,
FILL_GRADIENT_RADIAL_REVERSED_DEFAULTS as FILL_GRADIENT_RADIAL_REVERSED_DEFAULTS3,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS14,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS9,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS14,
MARKER_SERIES_HIGHLIGHT_STYLE as MARKER_SERIES_HIGHLIGHT_STYLE2,
POLAR_AXIS_TYPE as POLAR_AXIS_TYPE3,
SAFE_STROKE_FILL_OPERATION as SAFE_STROKE_FILL_OPERATION3,
mergeDefaults as mergeDefaults19
} from "ag-charts-core";
var BASE_RADAR_SERIES_THEME = {
series: {
stroke: { $palette: "stroke" },
label: {
...LABEL_BOXING_DEFAULTS14,
enabled: false,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "textColor" }
},
marker: {
enabled: true,
fill: {
$applySwitch: [
{ $path: "type" },
{ $palette: "fill" },
["gradient", FILL_GRADIENT_RADIAL_REVERSED_DEFAULTS3],
["image", FILL_IMAGE_DEFAULTS14],
["pattern", FILL_PATTERN_DEFAULTS9]
]
},
stroke: { $palette: "stroke" },
fillOpacity: 1,
shape: "circle",
size: 6,
strokeOpacity: 1,
strokeWidth: { $isUserOption: ["./stroke", 1, 0] }
},
highlight: MARKER_SERIES_HIGHLIGHT_STYLE2,
tooltip: {
range: { $path: ["/tooltip/range", "nearest"] }
}
},
axes: {
[POLAR_AXIS_TYPE3.ANGLE_CATEGORY]: {
label: {
spacing: 10
}
}
}
};
var RADAR_LINE_SERIES_THEME = mergeDefaults19(
{
series: {
stroke: SAFE_STROKE_FILL_OPERATION3,
strokeWidth: 2
}
},
BASE_RADAR_SERIES_THEME
);
var RADAR_AREA_SERIES_THEME = mergeDefaults19(
{
series: {
fill: {
$applySwitch: [
{ $path: "type" },
{ $palette: "fill" },
["gradient", FILL_GRADIENT_LINEAR_DEFAULTS7],
["image", FILL_IMAGE_DEFAULTS14],
["pattern", FILL_PATTERN_DEFAULTS9]
]
},
fillOpacity: 0.8,
strokeWidth: 2,
marker: {
enabled: false
}
}
},
BASE_RADAR_SERIES_THEME
);
// packages/ag-charts-enterprise/src/series/radar-area/radarAreaSeries.ts
import {
_ModuleSupport as _ModuleSupport189
} from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection48 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radar/radarSeries.ts
import {
_ModuleSupport as _ModuleSupport188
} from "ag-charts-community";
import {
ChartAxisDirection as ChartAxisDirection47,
extent as extent3,
isFiniteNumber as isFiniteNumber3,
isNumberEqual as isNumberEqual9,
mergeDefaults as mergeDefaults20
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radar/radarSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport187 } from "ag-charts-community";
import { Property as Property82 } from "ag-charts-core";
var { Label: Label14, SeriesMarker: SeriesMarker2, SeriesProperties: SeriesProperties10, makeSeriesTooltip: makeSeriesTooltip19 } = _ModuleSupport187;
var RadarSeriesProperties = class extends SeriesProperties10 {
constructor() {
super(...arguments);
this.angleKeyAxis = "angle";
this.radiusKeyAxis = "radius";
this.stroke = "black";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.rotation = 0;
this.marker = new SeriesMarker2();
this.label = new Label14();
this.tooltip = makeSeriesTooltip19();
this.connectMissingData = false;
}
};
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "angleKey", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "radiusKey", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "angleName", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "radiusName", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "angleKeyAxis", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "radiusKeyAxis", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "legendItemName", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "stroke", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "rotation", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "styler", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "marker", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "label", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "tooltip", 2);
__decorateClass([
Property82
], RadarSeriesProperties.prototype, "connectMissingData", 2);
// packages/ag-charts-enterprise/src/series/radar/radarSeries.ts
var {
DEFAULT_POLAR_DIRECTION_KEYS: DEFAULT_POLAR_DIRECTION_KEYS2,
DEFAULT_POLAR_DIRECTION_NAMES: DEFAULT_POLAR_DIRECTION_NAMES2,
PolarAxis: PolarAxis2,
SeriesNodePickMode: SeriesNodePickMode14,
keyProperty: keyProperty10,
valueProperty: valueProperty16,
fixNumericExtent: fixNumericExtent9,
seriesLabelFadeInAnimation: seriesLabelFadeInAnimation7,
markerFadeInAnimation: markerFadeInAnimation2,
resetMarkerFn: resetMarkerFn2,
resetLabelFn: resetLabelFn6,
animationValidation: animationValidation8,
computeMarkerFocusBounds: computeMarkerFocusBounds3,
BBox: BBox24,
Group: Group18,
Path: Path12,
Selection: Selection14,
Text: Text8,
Marker: Marker5,
updateLabelNode: updateLabelNode7,
getMarkerStyles: getMarkerStyles2
} = _ModuleSupport188;
var RadarSeriesNodeEvent = class extends _ModuleSupport188.SeriesNodeEvent {
constructor(type, nativeEvent, datum, series) {
super(type, nativeEvent, datum, series);
this.angleKey = series.properties.angleKey;
this.radiusKey = series.properties.radiusKey;
}
};
var RadarSeries = class extends _ModuleSupport188.PolarSeries {
constructor(moduleCtx) {
super({
moduleCtx,
categoryKey: "angleValue",
propertyKeys: DEFAULT_POLAR_DIRECTION_KEYS2,
propertyNames: DEFAULT_POLAR_DIRECTION_NAMES2,
pickModes: [SeriesNodePickMode14.NEAREST_NODE, SeriesNodePickMode14.EXACT_SHAPE_MATCH],
canHaveAxes: true,
animationResetFns: {
item: resetMarkerFn2,
label: resetLabelFn6
},
clipFocusBox: false
});
this.NodeEvent = RadarSeriesNodeEvent;
this.lineGroup = this.contentGroup.appendChild(new Group18({ name: "radar-line" }));
this.lineSelection = Selection14.select(
this.lineGroup,
Path12
);
this.resetInvalidToZero = false;
this.circleCache = { r: 0, cx: 0, cy: 0 };
this.lineGroup.zIndex = 0;
this.itemGroup.zIndex = 1;
}
renderToOffscreenCanvas() {
const hasMarkers = (this.nodeData?.length ?? 0) > 0;
return hasMarkers && this.getDrawingMode(false) === "cutout" || super.renderToOffscreenCanvas();
}
nodeFactory() {
return new Marker5();
}
getSeriesDomain(direction) {
const { dataModel, processedData } = this;
if (!processedData || !dataModel)
return { domain: [] };
if (direction === ChartAxisDirection47.Angle) {
const domain = dataModel.getDomain(this, `angleValue`, "key", processedData).domain;
const sortMetadata = dataModel.getKeySortMetadata(this, "angleValue", processedData);
return { domain, sortMetadata };
} else {
const domain = dataModel.getDomain(this, `radiusValue`, "value", processedData).domain;
const ext = extent3(domain.length === 0 ? domain : [0].concat(domain));
return { domain: fixNumericExtent9(ext) };
}
}
async processData(dataController) {
const { angleKey, radiusKey } = this.properties;
const extraProps = [];
if (!this.ctx.animationManager.isSkipped()) {
extraProps.push(animationValidation8());
}
const radiusScaleType = this.axes[ChartAxisDirection47.Radius]?.scale.type;
const angleScaleType = this.axes[ChartAxisDirection47.Angle]?.scale.type;
const allowNullKey = this.properties.allowNullKeys ?? false;
await this.requestDataModel(dataController, this.data, {
props: [
keyProperty10(angleKey, angleScaleType, { id: "angleValue", allowNullKey }),
valueProperty16(radiusKey, radiusScaleType, { id: "radiusValue", invalidValue: void 0 }),
...extraProps
]
});
this.animationState.transition("updateData");
}
didCircleChange() {
const r = this.radius;
const cx = this.centerX;
const cy = this.centerY;
const cache = this.circleCache;
if (!(r === cache.r && cx === cache.cx && cy === cache.cy)) {
this.circleCache = { r, cx, cy };
return true;
}
return false;
}
getAxisInnerRadius() {
const radiusAxis = this.axes[ChartAxisDirection47.Radius];
return radiusAxis instanceof PolarAxis2 ? this.radius * radiusAxis.innerRadiusRatio : 0;
}
maybeRefreshNodeData() {
const didCircleChange = this.didCircleChange();
if (!didCircleChange && !this.nodeDataRefresh)
return;
this.contextNodeData = this.createNodeData();
this.nodeData = this.contextNodeData?.nodeData ?? [];
this.nodeDataRefresh = false;
}
createNodeData() {
const { processedData, dataModel } = this;
if (!processedData || !dataModel)
return;
const { angleKey, radiusKey, angleName, radiusName, legendItemName, marker, label } = this.properties;
const angleScale = this.axes[ChartAxisDirection47.Angle]?.scale;
const radiusScale = this.axes[ChartAxisDirection47.Radius]?.scale;
if (!angleScale || !radiusScale) {
return;
}
const angleValues = dataModel.resolveKeysById(this, `angleValue`, processedData);
const radiusValues = dataModel.resolveColumnById(this, `radiusValue`, processedData);
const axisInnerRadius = this.getAxisInnerRadius();
const radiusDomain = this.getSeriesDomain(ChartAxisDirection47.Radius).domain;
const rawData = processedData.dataSources.get(this.id)?.data ?? [];
const allowNullKeys = this.properties.allowNullKeys ?? false;
const nodeData = [];
for (let datumIndex = 0; datumIndex < rawData.length; datumIndex++) {
const datum = rawData[datumIndex];
const angleDatum = angleValues[datumIndex];
if (angleDatum === void 0 && !allowNullKeys) {
continue;
}
const radiusDatum = radiusValues[datumIndex];
const angle = angleScale.convert(angleDatum);
const radius = this.radius + axisInnerRadius - radiusScale.convert(radiusDatum);
const cos = Math.cos(angle);
const sin = Math.sin(angle);
const x = cos * radius;
const y = sin * radius;
let labelNodeDatum;
if (label.enabled) {
const labelText = this.getLabelText(
radiusDatum,
datum,
radiusKey,
"radius",
radiusDomain,
label,
{ value: radiusDatum, datum, angleKey, radiusKey, angleName, radiusName, legendItemName }
);
if (labelText) {
let textAlign = "right";
if (isNumberEqual9(cos, 0)) {
textAlign = "center";
} else if (cos > 0) {
textAlign = "left";
}
let textBaseline = "bottom";
if (isNumberEqual9(sin, 0)) {
textBaseline = "middle";
} else if (sin > 0) {
textBaseline = "top";
}
labelNodeDatum = {
x: x + cos * marker.size,
y: y + sin * marker.size,
text: labelText,
textAlign,
textBaseline
};
}
}
nodeData.push({
series: this,
datum,
datumIndex,
index: datumIndex,
point: { x, y, size: marker.size },
midPoint: { x, y },
label: labelNodeDatum,
angleValue: angleDatum,
radiusValue: radiusDatum,
missing: !isFiniteNumber3(angle) || !isFiniteNumber3(radius)
});
}
return {
itemId: radiusKey,
nodeData,
labelData: nodeData,
styles: getMarkerStyles2(this, this.properties, marker)
};
}
update({ seriesRect }) {
const resize = this.checkResize(seriesRect);
const animationEnabled = !this.ctx.animationManager.isSkipped();
const { series } = this.ctx.highlightManager?.getActiveHighlight() ?? {};
this.highlightGroup.visible = (animationEnabled || this.visible) && series === this;
this.maybeRefreshNodeData();
this.contentGroup.translationX = this.centerX;
this.contentGroup.translationY = this.centerY;
this.highlightGroup.translationX = this.centerX;
this.highlightGroup.translationY = this.centerY;
if (this.labelGroup) {
this.labelGroup.translationX = this.centerX;
this.labelGroup.translationY = this.centerY;
}
this.updatePathSelections();
this.updateMarkerSelection();
this.updateHighlightSelection();
this.updatePathNodes();
if (this.hasItemStylers()) {
this.updateDatumStyles(this.itemSelection, false);
this.updateDatumStyles(this.highlightSelection, true);
}
const drawingMode = this.ctx.chartService.highlight?.drawingMode ?? "overlay";
this.updateMarkers(this.itemSelection, false, "overlay");
this.updateMarkers(this.highlightSelection, true, drawingMode);
this.updateLabels();
if (resize) {
this.animationState.transition("resize");
}
this.animationState.transition("update");
}
updatePathSelections() {
const pathData = this.visible ? [true] : [];
this.lineSelection.update(pathData);
}
updateMarkerSelection() {
const { marker, styler } = this.properties;
if (marker.isDirty()) {
this.itemSelection.clear();
this.itemSelection.cleanup();
this.itemSelection = Selection14.select(this.itemGroup, () => this.nodeFactory(), false);
}
const markersEnabled = styler == null ? marker.enabled : this.getStyle().marker.enabled;
const data = this.visible && marker.shape && markersEnabled ? this.nodeData : [];
this.itemSelection.update(data);
}
updateHighlightSelection() {
const { marker, styler } = this.properties;
if (marker.isDirty()) {
this.highlightSelection.clear();
this.highlightSelection.cleanup();
this.highlightSelection = Selection14.select(this.highlightGroup, () => this.nodeFactory(), false);
}
const markersEnabled = styler == null ? marker.enabled : this.getStyle().marker.enabled;
const highlighted = this.ctx.highlightManager?.getActiveHighlight();
const data = this.visible && marker.shape && markersEnabled && highlighted?.datum ? [{ ...highlighted }] : [];
this.highlightSelection.update(data);
}
getMarkerFill(highlightedStyle) {
return highlightedStyle?.fill ?? this.getStyle().marker.fill;
}
getDatumStylerProperties(datum) {
const { id: seriesId, properties } = this;
const { angleKey, radiusKey } = properties;
return {
seriesId,
datum,
angleKey,
radiusKey
};
}
updateDatumStyles(selection, isHighlight) {
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
selection.each((_, datum) => {
const highlightState = this.getHighlightState(highlightedDatum, isHighlight, datum.datumIndex);
const stylerStyle = this.getStyle(highlightState);
const { stroke: stroke3, strokeWidth, strokeOpacity } = stylerStyle;
datum.style = this.getMarkerStyle(
this.properties.marker,
datum,
this.getDatumStylerProperties(datum.datum),
{ isHighlight, highlightState },
stylerStyle.marker,
{
stroke: stroke3,
strokeWidth,
strokeOpacity
}
);
});
}
updateMarkers(selection, isHighlight, drawingMode) {
const fillBBox = this.getShapeFillBBox();
const { contextNodeData } = this;
if (!contextNodeData) {
return;
}
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
drawingMode = this.getDrawingMode(isHighlight, drawingMode);
selection.each((node, datum) => {
const style = datum.style ?? contextNodeData.styles[this.getHighlightState(highlightedDatum, isHighlight, datum.datumIndex)];
this.applyMarkerStyle(style, node, datum.point, fillBBox);
node.drawingMode = drawingMode;
});
}
updateLabels() {
const { properties } = this;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightData = activeHighlight?.series === this && activeHighlight?.datum ? [{ ...activeHighlight }] : [];
this.labelSelection.update(this.nodeData).each((node, datum) => {
if (datum.label) {
const isHighlight = false;
node.fillOpacity = this.getHighlightStyle(isHighlight, datum.datumIndex).opacity ?? 1;
updateLabelNode7(this, node, properties, properties.label, datum.label, isHighlight, activeHighlight);
}
});
this.highlightLabelSelection.update(highlightData).each((node, datum) => {
if (datum.label) {
const isHighlight = true;
node.fillOpacity = this.getHighlightStyle(isHighlight, datum.datumIndex).opacity ?? 1;
updateLabelNode7(this, node, properties, properties.label, datum.label, isHighlight, activeHighlight);
}
});
}
getTooltipContent(datumIndex) {
const { id: seriesId, dataModel, processedData, axes, properties } = this;
const { angleKey, angleName, radiusKey, radiusName, legendItemName, tooltip, marker } = properties;
const angleAxis = axes[ChartAxisDirection47.Angle];
const radiusAxis = axes[ChartAxisDirection47.Radius];
if (!dataModel || !processedData || !angleAxis || !radiusAxis)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const angleValue = dataModel.resolveKeysById(this, `angleValue`, processedData)[datumIndex];
const radiusValue = dataModel.resolveColumnById(this, `radiusValue`, processedData)[datumIndex];
const allowNullKeys = this.properties.allowNullKeys ?? false;
if (angleValue === void 0 && !allowNullKeys)
return;
const activeStyle = this.getMarkerStyle(marker, { datum, datumIndex }, this.getDatumStylerProperties(datum), {
isHighlight: false
});
return this.formatTooltipWithContext(
tooltip,
{
heading: this.getAxisValueText(
angleAxis,
"tooltip",
angleValue,
datum,
angleKey,
void 0,
allowNullKeys
),
symbol: this.legendItemSymbol(),
data: [
{
label: radiusName,
fallbackLabel: radiusKey,
value: this.getAxisValueText(radiusAxis, "tooltip", radiusValue, datum, radiusKey, void 0),
missing: _ModuleSupport188.isTooltipValueMissing(radiusValue)
}
]
},
{
seriesId,
datum,
title: angleName,
angleKey,
radiusKey,
angleName,
radiusName,
legendItemName,
...activeStyle
}
);
}
legendItemSymbol() {
const { stroke: stroke3, strokeWidth, strokeOpacity, lineDash, marker } = this.getStyle();
const markerStyle = {
shape: marker.shape,
enabled: marker.enabled || strokeWidth <= 0,
fill: this.getMarkerFill() ?? marker.stroke ?? stroke3 ?? "rgba(0, 0, 0, 0)",
stroke: marker.stroke ?? stroke3 ?? "rgba(0, 0, 0, 0)",
fillOpacity: marker.fillOpacity,
strokeOpacity: marker.strokeOpacity,
strokeWidth: marker.strokeWidth,
lineDash: marker.lineDash,
lineDashOffset: marker.lineDashOffset
};
return {
marker: markerStyle,
line: {
enabled: true,
stroke: stroke3,
strokeOpacity,
strokeWidth,
lineDash
}
};
}
getLegendData(legendType) {
if (legendType !== "category") {
return [];
}
const {
id: seriesId,
ctx: { legendManager },
visible
} = this;
const { radiusKey, radiusName, legendItemName, showInLegend } = this.properties;
return [
{
legendType: "category",
id: seriesId,
itemId: radiusKey,
seriesId,
enabled: visible && legendManager.getItemEnabled({ seriesId, itemId: radiusKey }),
label: {
text: legendItemName ?? radiusName ?? radiusKey
},
symbol: this.legendItemSymbol(),
legendItemName,
hideInLegend: !showInLegend
}
];
}
pickNodeClosestDatum(hitPoint) {
const { nodeData, centerX: cx, centerY: cy } = this;
const { x, y } = hitPoint;
const radius = this.radius;
const distanceFromCenter = Math.hypot(x - cx, y - cy);
if (distanceFromCenter > radius + this.maxChartMarkerSize) {
return;
}
let minDistance = Infinity;
let closestDatum;
for (const datum of nodeData) {
const { point: { x: datumX = Number.NaN, y: datumY = Number.NaN } = {} } = datum;
if (Number.isNaN(datumX) || Number.isNaN(datumY)) {
continue;
}
const distance = Math.hypot(hitPoint.x - datumX - cx, hitPoint.y - datumY - cy);
if (distance < minDistance) {
minDistance = distance;
closestDatum = datum;
}
}
if (closestDatum) {
const distance = Math.max(minDistance - (closestDatum.point?.size ?? 0) / 2, 0);
return { datum: closestDatum, distance };
}
}
computeLabelsBBox() {
const { label } = this.properties;
this.maybeRefreshNodeData();
const textBoxes = [];
const tempText = new Text8();
for (const nodeDatum of this.nodeData) {
if (!label.enabled || !nodeDatum.label) {
continue;
}
tempText.text = nodeDatum.label.text;
tempText.x = nodeDatum.label.x;
tempText.y = nodeDatum.label.y;
tempText.setFont(label);
tempText.setAlign(nodeDatum.label);
const box = tempText.getBBox();
textBoxes.push(box);
}
if (textBoxes.length === 0) {
return null;
}
return BBox24.merge(textBoxes);
}
getLineNode() {
return this.lineSelection?.at(0);
}
beforePathAnimation() {
this.updatePathNodes();
}
getPathNodesStyle() {
const highlightDatum = this.ctx.highlightManager?.getActiveHighlight();
const highlightState = this.getHighlightState(highlightDatum);
const highlightStyle = this.getHighlightStyle(void 0, void 0, highlightState);
const stylerStyle = this.getStyle(highlightState);
return mergeDefaults20(highlightStyle, stylerStyle);
}
getLinePoints() {
const { nodeData, resetInvalidToZero } = this;
const { connectMissingData } = this.properties;
if (nodeData.length === 0) {
return [];
}
const radiusAxis = this.axes[ChartAxisDirection47.Radius];
const angleAxis = this.axes[ChartAxisDirection47.Angle];
const reversedAngleAxis = angleAxis?.isReversed();
const reversedRadiusAxis = radiusAxis?.isReversed();
const data = reversedRadiusAxis && !reversedAngleAxis ? [...nodeData].reverse() : nodeData;
const points = [];
let prevPointInvalid = false;
let firstValid;
for (const [index, datum] of data.entries()) {
let { x, y } = datum.point;
const isPointInvalid = Number.isNaN(x) || Number.isNaN(y);
if (!isPointInvalid) {
firstValid ?? (firstValid = datum);
}
if (isPointInvalid && !connectMissingData) {
x = 0;
y = 0;
}
const moveTo2 = index === 0 || !resetInvalidToZero && !connectMissingData && (isPointInvalid || prevPointInvalid);
points.push({ x, y, moveTo: moveTo2 });
prevPointInvalid = isPointInvalid;
}
if (firstValid !== void 0) {
points.push({ x: firstValid.point.x, y: firstValid.point.y, moveTo: false });
}
return points;
}
animateSinglePath(pathNode, points, ratio8) {
const { path } = pathNode;
path.clear(true);
const axisInnerRadius = this.getAxisInnerRadius();
const radiusAxis = this.axes[ChartAxisDirection47.Radius];
const reversedRadiusAxis = radiusAxis?.isReversed();
const radiusZero = reversedRadiusAxis ? this.radius + axisInnerRadius - radiusAxis?.scale.convert(0) : axisInnerRadius;
for (const point of points) {
const { x: x1, y: y1, arc, radius = 0, startAngle = 0, endAngle = 0, moveTo: moveTo2 } = point;
const angle = Math.atan2(y1, x1);
const x0 = radiusZero * Math.cos(angle);
const y0 = radiusZero * Math.sin(angle);
const t = ratio8;
const x = x0 * (1 - t) + x1 * t;
const y = y0 * (1 - t) + y1 * t;
if (arc) {
path.arc(x1, y1, radius, startAngle, endAngle);
} else if (moveTo2) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
}
pathNode.checkPathDirty();
}
animatePaths(ratio8) {
const linePoints = this.getLinePoints();
const lineNode = this.getLineNode();
if (!lineNode)
return;
this.animateSinglePath(lineNode, linePoints, ratio8);
}
animateEmptyUpdateReady() {
const { itemSelection, labelSelection } = this;
const { animationManager } = this.ctx;
this.beforePathAnimation();
animationManager.animate({
id: `${this.id}_'path`,
groupId: this.id,
from: 0,
to: 1,
phase: "initial",
collapsable: false,
onUpdate: (ratio8) => this.animatePaths(ratio8),
onStop: () => this.animatePaths(1)
});
markerFadeInAnimation2(this, animationManager, "added", this.getAnimationDrawingModes(), itemSelection);
seriesLabelFadeInAnimation7(this, "labels", animationManager, labelSelection, this.highlightLabelSelection);
}
animateWaitingUpdateReady(data) {
super.animateWaitingUpdateReady(data);
this.resetPaths();
}
animateReadyResize(data) {
super.animateReadyResize(data);
this.resetPaths();
}
resetPaths() {
const lineNode = this.getLineNode();
if (lineNode) {
const { path: linePath } = lineNode;
const linePoints = this.getLinePoints();
const stylerStyle = this.getStyle();
lineNode.fill = void 0;
lineNode.stroke = stylerStyle.stroke;
lineNode.strokeWidth = stylerStyle.strokeWidth;
lineNode.strokeOpacity = stylerStyle.strokeOpacity;
lineNode.lineDash = stylerStyle.lineDash;
lineNode.lineDashOffset = stylerStyle.lineDashOffset;
linePath.clear(true);
for (const { x, y, moveTo: moveTo2 } of linePoints) {
if (moveTo2) {
linePath.moveTo(x, y);
} else {
linePath.lineTo(x, y);
}
}
lineNode.checkPathDirty();
return stylerStyle;
}
}
getStylerResult(stylerResult, highlightState) {
const { styler } = this.properties;
if (styler) {
const stylerParams = this.makeStylerParams(highlightState);
const cbResult = this.cachedCallWithContext(styler, stylerParams) ?? {};
const resolved = this.ctx.optionsGraphService.resolvePartial(
["series", `${this.declarationOrder}`],
cbResult,
{ pick: false }
);
if (resolved) {
stylerResult = resolved;
}
}
return stylerResult;
}
getFormattedMarkerStyle(datum) {
const { angleKey, radiusKey } = this.properties;
return this.getMarkerStyle(this.properties.marker, datum, { angleKey, radiusKey }, { isHighlight: true });
}
computeFocusBounds(opts) {
return computeMarkerFocusBounds3(this, opts);
}
hasItemStylers() {
return this.properties.styler != null || this.properties.marker.itemStyler != null || this.properties.label.itemStyler != null;
}
};
RadarSeries.className = "RadarSeries";
// packages/ag-charts-enterprise/src/series/radar-area/radarAreaSeriesProperties.ts
import "ag-charts-community";
import { Property as Property83 } from "ag-charts-core";
var RadarAreaSeriesProperties = class extends RadarSeriesProperties {
constructor() {
super(...arguments);
this.fill = "black";
this.fillOpacity = 1;
}
};
__decorateClass([
Property83
], RadarAreaSeriesProperties.prototype, "fill", 2);
__decorateClass([
Property83
], RadarAreaSeriesProperties.prototype, "fillOpacity", 2);
// packages/ag-charts-enterprise/src/series/radar-area/radarAreaSeries.ts
var { Group: Group19, HighlightState: HighlightState5, Path: Path13, PointerEvents: PointerEvents10, Selection: Selection15, toHighlightString: toHighlightString5 } = _ModuleSupport189;
var RadarAreaSeries = class extends RadarSeries {
constructor(moduleCtx) {
super(moduleCtx);
this.properties = new RadarAreaSeriesProperties();
this.areaGroup = this.contentGroup.appendChild(new Group19({ name: "radar-area" }));
this.areaSelection = Selection15.select(
this.areaGroup,
Path13
);
this.resetInvalidToZero = true;
this.areaGroup.zIndex = -1;
}
updatePathSelections() {
const pathData = this.visible ? [true] : [];
this.areaSelection.update(pathData);
super.updatePathSelections();
}
getAreaNode() {
return this.areaSelection.at(0);
}
getMarkerFill(highlightedStyle) {
if (highlightedStyle?.fill != null)
return highlightedStyle.fill;
const stylerStyle = this.getStyle();
return stylerStyle.marker.fill ?? stylerStyle.fill;
}
updatePathNodes() {
const styles = this.getPathNodesStyle();
const { fill, fillOpacity, strokeWidth, stroke: stroke3, strokeOpacity, lineDash, lineDashOffset, opacity } = styles;
const lineNode = this.getLineNode();
if (lineNode) {
lineNode.setProperties({
fill: void 0,
lineJoin: "round",
lineCap: "round",
pointerEvents: PointerEvents10.None,
opacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
});
}
const areaNode = this.getAreaNode();
if (areaNode) {
areaNode.setStyleProperties({ fill, fillOpacity, stroke: void 0 }, this.getShapeFillBBox());
areaNode.setProperties({
lineJoin: "round",
pointerEvents: PointerEvents10.None,
opacity
});
}
}
animatePaths(ratio8) {
super.animatePaths(ratio8);
const areaNode = this.getAreaNode();
if (areaNode) {
this.animateSinglePath(areaNode, this.getAreaPoints(), ratio8);
}
}
getAreaPoints() {
const points = this.getLinePoints();
const getPolarAxis = (direction) => {
const axis = this.axes[direction];
return axis instanceof _ModuleSupport189.PolarAxis ? axis : void 0;
};
const radiusAxis = getPolarAxis(ChartAxisDirection48.Radius);
const angleAxis = getPolarAxis(ChartAxisDirection48.Angle);
const reversedRadiusAxis = radiusAxis?.isReversed();
if (!reversedRadiusAxis) {
return points;
}
const zeroLinePoints = angleAxis?.getAxisLinePoints()?.points ?? [];
return points.concat(...zeroLinePoints);
}
resetPaths() {
const superStyle = super.resetPaths();
const areaNode = this.getAreaNode();
if (areaNode) {
const { path: areaPath } = areaNode;
const areaPoints = this.getAreaPoints();
const stylerStyle = superStyle ?? this.getStyle();
const fillBBox = this.getShapeFillBBox();
areaNode.setStyleProperties(
{
fill: stylerStyle.fill,
stroke: void 0,
fillOpacity: stylerStyle.fillOpacity,
lineDash: stylerStyle.lineDash,
lineDashOffset: stylerStyle.lineDashOffset
},
fillBBox
);
areaNode.lineJoin = areaNode.lineCap = "round";
areaPath.clear(true);
for (const { x, y, moveTo: moveTo2, arc, radius = 0, startAngle = 0, endAngle = 0 } of areaPoints) {
if (arc) {
areaPath.arc(x, y, radius, startAngle, endAngle);
} else if (moveTo2) {
areaPath.moveTo(x, y);
} else {
areaPath.lineTo(x, y);
}
}
areaPath.closePath();
areaNode.checkPathDirty();
return stylerStyle;
}
}
makeStylerParams(highlightStateEnum) {
const { properties } = this;
const highlightState = toHighlightString5(highlightStateEnum ?? HighlightState5.None);
return {
marker: {
fill: properties.marker.fill,
fillOpacity: properties.marker.fillOpacity,
size: properties.marker.size,
shape: properties.marker.shape,
stroke: properties.marker.stroke,
strokeOpacity: properties.marker.strokeOpacity,
strokeWidth: properties.marker.strokeWidth,
lineDash: properties.marker.lineDash,
lineDashOffset: properties.marker.lineDashOffset
},
highlightState,
fill: properties.fill,
fillOpacity: properties.fillOpacity,
lineDash: properties.lineDash,
lineDashOffset: properties.lineDashOffset,
seriesId: this.id,
stroke: properties.stroke,
strokeOpacity: properties.strokeOpacity,
strokeWidth: properties.strokeWidth,
angleKey: properties.angleKey,
radiusKey: properties.radiusKey
};
}
getStyle(highlightState) {
const { marker, fill, fillOpacity, lineDash, lineDashOffset, stroke: stroke3, strokeOpacity, strokeWidth } = this.properties;
const { size, shape, fill: markerFill = "transparent", fillOpacity: markerFillOpacity } = marker;
const stylerResult = this.getStylerResult({}, highlightState);
stylerResult.marker ?? (stylerResult.marker = {});
return {
fill: stylerResult.fill ?? fill,
fillOpacity: stylerResult.fillOpacity ?? fillOpacity,
lineDash: stylerResult.lineDash ?? lineDash,
lineDashOffset: stylerResult.lineDashOffset ?? lineDashOffset,
stroke: stylerResult.stroke ?? stroke3,
strokeOpacity: stylerResult.strokeOpacity ?? strokeOpacity,
strokeWidth: stylerResult.strokeWidth ?? strokeWidth,
marker: {
enabled: stylerResult.marker.enabled ?? marker.enabled,
fill: stylerResult.marker.fill ?? markerFill,
fillOpacity: stylerResult.marker.fillOpacity ?? markerFillOpacity,
shape: stylerResult.marker.shape ?? shape,
size: stylerResult.marker.size ?? size,
lineDash: stylerResult.marker.lineDash ?? marker.lineDash ?? lineDash,
lineDashOffset: stylerResult.marker.lineDashOffset ?? marker.lineDashOffset ?? lineDashOffset,
stroke: stylerResult.marker.stroke ?? marker.stroke ?? stroke3,
strokeOpacity: stylerResult.marker.strokeOpacity ?? marker.strokeOpacity ?? strokeOpacity,
strokeWidth: stylerResult.marker.strokeWidth ?? marker.strokeWidth ?? strokeWidth
}
};
}
};
RadarAreaSeries.className = "RadarAreaSeries";
RadarAreaSeries.type = "radar-area";
// packages/ag-charts-enterprise/src/series/radar-area/radarAreaSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport190 } from "ag-charts-community";
import { commonSeriesOptionsDefs as commonSeriesOptionsDefs17, constant as constant18, required as required18, string as string18, undocumented as undocumented13 } from "ag-charts-core";
var { radarAreaSeriesThemeableOptionsDef } = _ModuleSupport190;
var radarAreaSeriesOptionsDef = {
...commonSeriesOptionsDefs17,
...radarAreaSeriesThemeableOptionsDef,
type: required18(constant18("radar-area")),
angleKey: required18(string18),
radiusKey: required18(string18),
angleName: string18,
radiusName: string18,
legendItemName: string18
};
radarAreaSeriesOptionsDef.angleKeyAxis = undocumented13(string18);
radarAreaSeriesOptionsDef.radiusKeyAxis = undocumented13(string18);
// packages/ag-charts-enterprise/src/series/radar-area/radarAreaModule.ts
var RadarAreaSeriesModule = {
type: "series",
name: "radar-area",
chartType: "polar",
enterprise: true,
version: VERSION43,
dependencies: [PolarChartModule2],
options: radarAreaSeriesOptionsDef,
defaultAxes: { angle: { type: POLAR_AXIS_TYPE4.ANGLE_CATEGORY }, radius: { type: POLAR_AXIS_TYPE4.RADIUS_NUMBER } },
axisKeys: { [ChartAxisDirection49.Angle]: "angleKeyAxis", [ChartAxisDirection49.Radius]: "radiusKeyAxis" },
themeTemplate: RADAR_AREA_SERIES_THEME,
create: (ctx) => new RadarAreaSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/radar-line/radarLineModule.ts
import { PolarChartModule as PolarChartModule3, VERSION as VERSION44 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection50, POLAR_AXIS_TYPE as POLAR_AXIS_TYPE5 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radar-line/radarLineSeries.ts
import {
_ModuleSupport as _ModuleSupport191
} from "ag-charts-community";
var { HighlightState: HighlightState6, PointerEvents: PointerEvents11, toHighlightString: toHighlightString6 } = _ModuleSupport191;
var RadarLineSeries = class extends RadarSeries {
constructor() {
super(...arguments);
this.properties = new RadarSeriesProperties();
}
updatePathSelections() {
this.lineSelection.update(this.visible ? [true] : []);
}
updatePathNodes() {
const lineNode = this.getLineNode();
if (!lineNode)
return;
const style = this.getPathNodesStyle();
const { strokeWidth, stroke: stroke3, strokeOpacity, lineDash, lineDashOffset, opacity } = style;
lineNode.setProperties({
fill: void 0,
lineJoin: "round",
lineCap: "round",
pointerEvents: PointerEvents11.None,
opacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
});
}
makeStylerParams(highlightStateEnum) {
const { properties } = this;
const highlightState = toHighlightString6(highlightStateEnum ?? HighlightState6.None);
return {
marker: {
fill: properties.marker.fill,
fillOpacity: properties.marker.fillOpacity,
size: properties.marker.size,
shape: properties.marker.shape,
stroke: properties.marker.stroke,
strokeOpacity: properties.marker.strokeOpacity,
strokeWidth: properties.marker.strokeWidth,
lineDash: properties.marker.lineDash,
lineDashOffset: properties.marker.lineDashOffset
},
highlightState,
lineDash: properties.lineDash,
lineDashOffset: properties.lineDashOffset,
seriesId: this.id,
stroke: properties.stroke,
strokeOpacity: properties.strokeOpacity,
strokeWidth: properties.strokeWidth,
angleKey: properties.angleKey,
radiusKey: properties.radiusKey
};
}
getStyle(highlightState) {
const { marker, lineDash, lineDashOffset, stroke: stroke3, strokeOpacity, strokeWidth } = this.properties;
const { size, shape, fill = "transparent", fillOpacity } = marker;
const stylerResult = this.getStylerResult({}, highlightState);
stylerResult.marker ?? (stylerResult.marker = {});
return {
lineDash: stylerResult.lineDash ?? lineDash,
lineDashOffset: stylerResult.lineDashOffset ?? lineDashOffset,
stroke: stylerResult.stroke ?? stroke3,
strokeOpacity: stylerResult.strokeOpacity ?? strokeOpacity,
strokeWidth: stylerResult.strokeWidth ?? strokeWidth,
marker: {
enabled: stylerResult.marker.enabled ?? marker.enabled,
fill: stylerResult.marker.fill ?? fill,
fillOpacity: stylerResult.marker.fillOpacity ?? fillOpacity,
shape: stylerResult.marker.shape ?? shape,
size: stylerResult.marker.size ?? size,
lineDash: stylerResult.marker.lineDash ?? marker.lineDash ?? lineDash,
lineDashOffset: stylerResult.marker.lineDashOffset ?? marker.lineDashOffset ?? lineDashOffset,
stroke: stylerResult.marker.stroke ?? marker.stroke ?? stroke3,
strokeOpacity: stylerResult.marker.strokeOpacity ?? marker.strokeOpacity ?? strokeOpacity,
strokeWidth: stylerResult.marker.strokeWidth ?? marker.strokeWidth ?? strokeWidth
}
};
}
};
RadarLineSeries.className = "RadarLineSeries";
RadarLineSeries.type = "radar-line";
// packages/ag-charts-enterprise/src/series/radar-line/radarLineSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport192 } from "ag-charts-community";
import { commonSeriesOptionsDefs as commonSeriesOptionsDefs18, constant as constant19, required as required19, string as string19, undocumented as undocumented14 } from "ag-charts-core";
var { radarLineSeriesThemeableOptionsDef } = _ModuleSupport192;
var radarLineSeriesOptionsDef = {
...commonSeriesOptionsDefs18,
...radarLineSeriesThemeableOptionsDef,
type: required19(constant19("radar-line")),
angleKey: required19(string19),
radiusKey: required19(string19),
angleName: string19,
radiusName: string19,
legendItemName: string19
};
radarLineSeriesOptionsDef.angleKeyAxis = undocumented14(string19);
radarLineSeriesOptionsDef.radiusKeyAxis = undocumented14(string19);
// packages/ag-charts-enterprise/src/series/radar-line/radarLineModule.ts
var RadarLineSeriesModule = {
type: "series",
name: "radar-line",
chartType: "polar",
enterprise: true,
version: VERSION44,
dependencies: [PolarChartModule3],
options: radarLineSeriesOptionsDef,
defaultAxes: { angle: { type: POLAR_AXIS_TYPE5.ANGLE_CATEGORY }, radius: { type: POLAR_AXIS_TYPE5.RADIUS_NUMBER } },
axisKeys: { [ChartAxisDirection50.Angle]: "angleKeyAxis", [ChartAxisDirection50.Radius]: "radiusKeyAxis" },
themeTemplate: RADAR_LINE_SERIES_THEME,
create: (ctx) => new RadarLineSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/radial-bar/radialBarModule.ts
import { PolarChartModule as PolarChartModule4, VERSION as VERSION45 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection52, POLAR_AXIS_TYPE as POLAR_AXIS_TYPE7 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radial-bar/radialBarSeries.ts
import {
_ModuleSupport as _ModuleSupport195
} from "ag-charts-community";
import {
ChartAxisDirection as ChartAxisDirection51,
angleBetween as angleBetween3,
isDefined as isDefined4,
isGradientFill as isGradientFill3
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radial-bar/radialBarSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport193 } from "ag-charts-community";
import { Property as Property84 } from "ag-charts-core";
var { SeriesProperties: SeriesProperties11, makeSeriesTooltip: makeSeriesTooltip20, Label: Label15 } = _ModuleSupport193;
var RadialBarSeriesProperties = class extends SeriesProperties11 {
constructor() {
super(...arguments);
this.angleKeyAxis = "angle";
this.radiusKeyAxis = "radius";
this.fill = "black";
this.fillOpacity = 1;
this.stroke = "black";
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.cornerRadius = 0;
this.rotation = 0;
this.label = new Label15();
this.tooltip = makeSeriesTooltip20();
}
getStyle() {
const { fill, fillOpacity, stroke: stroke3, strokeWidth, strokeOpacity, lineDash, lineDashOffset, cornerRadius } = this;
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
cornerRadius,
opacity: 1
};
}
};
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "angleKey", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "radiusKey", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "angleName", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "radiusName", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "angleKeyAxis", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "radiusKeyAxis", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "legendItemName", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "fill", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "stroke", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "lineDash", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "cornerRadius", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "styler", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "rotation", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "stackGroup", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "normalizedTo", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "label", 2);
__decorateClass([
Property84
], RadialBarSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/radial-bar/radialBarUtil.ts
import { _ModuleSupport as _ModuleSupport194 } from "ag-charts-community";
var { SectorBox: SectorBox3, motion: motion9 } = _ModuleSupport194;
function fixRadialBarAnimationStatus(node, datum, status) {
if (status === "updated") {
if (node.previousDatum == null || Number.isNaN(node.previousDatum.innerRadius) || Number.isNaN(node.previousDatum.outerRadius)) {
return "added";
}
if (Number.isNaN(datum.innerRadius) || Number.isNaN(datum.outerRadius)) {
return "removed";
}
}
if (status === "added" && node.previousDatum != null) {
return "updated";
}
return status;
}
function prepareRadialBarSeriesAnimationFunctions(axisZeroAngle) {
const fromFn = (sect, datum, status) => {
status = fixRadialBarAnimationStatus(sect, datum, status);
let startAngle;
let endAngle;
let innerRadius;
let outerRadius;
let clipSector;
if (status === "removed" || status === "updated") {
startAngle = sect.startAngle;
endAngle = sect.endAngle;
innerRadius = sect.innerRadius;
outerRadius = sect.outerRadius;
clipSector = sect.clipSector;
} else {
startAngle = axisZeroAngle;
endAngle = axisZeroAngle;
innerRadius = datum.innerRadius;
outerRadius = datum.outerRadius;
}
clipSector ?? (clipSector = new SectorBox3(startAngle, endAngle, innerRadius, outerRadius));
const phase = motion9.NODE_UPDATE_STATE_TO_PHASE_MAPPING[status];
return { startAngle, endAngle, innerRadius, outerRadius, clipSector, phase };
};
const toFn = (sect, datum, status) => {
let startAngle;
let endAngle;
let innerRadius;
let outerRadius;
let clipSector;
if (status === "removed") {
startAngle = axisZeroAngle;
endAngle = axisZeroAngle;
innerRadius = datum.innerRadius;
outerRadius = datum.outerRadius;
clipSector = new SectorBox3(startAngle, endAngle, innerRadius, outerRadius);
} else {
startAngle = datum.startAngle;
endAngle = datum.endAngle;
innerRadius = Number.isNaN(datum.innerRadius) ? sect.innerRadius : datum.innerRadius;
outerRadius = Number.isNaN(datum.outerRadius) ? sect.outerRadius : datum.outerRadius;
clipSector = datum.clipSector;
}
return { startAngle, endAngle, innerRadius, outerRadius, clipSector };
};
return { toFn, fromFn };
}
function resetRadialBarSelectionsFn(_node, datum) {
return {
centerX: 0,
centerY: 0,
innerRadius: datum.innerRadius,
outerRadius: datum.outerRadius,
startAngle: datum.startAngle,
endAngle: datum.endAngle,
clipSector: datum.clipSector
};
}
// packages/ag-charts-enterprise/src/series/radial-bar/radialBarSeries.ts
var {
DEFAULT_POLAR_DIRECTION_KEYS: DEFAULT_POLAR_DIRECTION_KEYS3,
DEFAULT_POLAR_DIRECTION_NAMES: DEFAULT_POLAR_DIRECTION_NAMES3,
PolarAxis: PolarAxis3,
diff: diff7,
groupAccumulativeValueProperty: groupAccumulativeValueProperty3,
keyProperty: keyProperty11,
normaliseGroupTo: normaliseGroupTo2,
valueProperty: valueProperty17,
fixNumericExtent: fixNumericExtent10,
resetLabelFn: resetLabelFn7,
seriesLabelFadeInAnimation: seriesLabelFadeInAnimation8,
seriesLabelFadeOutAnimation: seriesLabelFadeOutAnimation2,
animationValidation: animationValidation9,
createDatumId: createDatumId19,
CategoryScale: CategoryScale4,
Sector: Sector5,
SectorBox: SectorBox4,
motion: motion10,
updateLabelNode: updateLabelNode8,
getItemStyles: getItemStyles4
} = _ModuleSupport195;
var RadialBarSeriesNodeEvent = class extends _ModuleSupport195.SeriesNodeEvent {
constructor(type, nativeEvent, datum, series) {
super(type, nativeEvent, datum, series);
this.angleKey = series.properties.angleKey;
this.radiusKey = series.properties.radiusKey;
}
};
var RadialBarSeries = class extends _ModuleSupport195.PolarSeries {
constructor(moduleCtx) {
super({
moduleCtx,
categoryKey: "radiusValue",
propertyKeys: DEFAULT_POLAR_DIRECTION_KEYS3,
propertyNames: DEFAULT_POLAR_DIRECTION_NAMES3,
canHaveAxes: true,
animationResetFns: {
item: resetRadialBarSelectionsFn,
label: resetLabelFn7
}
});
this.properties = new RadialBarSeriesProperties();
this.NodeEvent = RadialBarSeriesNodeEvent;
this.groupScale = new CategoryScale4();
this.circleCache = { r: 0, cx: 0, cy: 0 };
}
nodeFactory() {
return new Sector5();
}
getSeriesDomain(direction) {
const { dataModel, processedData } = this;
if (!processedData || !dataModel)
return { domain: [] };
if (direction === ChartAxisDirection51.Angle) {
const xExtent = dataModel.getDomain(this, "angleValue-end", "value", processedData).domain;
const fixedXExtent = [Math.min(xExtent[0], 0), Math.max(xExtent[1], 0)];
return { domain: fixNumericExtent10(fixedXExtent) };
} else {
return dataModel.getDomain(this, "radiusValue", "key", processedData);
}
}
async processData(dataController) {
const { angleKey, radiusKey, normalizedTo } = this.properties;
const animationEnabled = !this.ctx.animationManager.isSkipped();
const stackGroupId = this.getStackId();
const stackGroupTrailingId = `${stackGroupId}-trailing`;
const extraProps = [];
if (isDefined4(normalizedTo)) {
extraProps.push(normaliseGroupTo2([stackGroupId, stackGroupTrailingId], Math.abs(normalizedTo)));
}
if (this.needsDataModelDiff() && this.processedData) {
extraProps.push(diff7(this.id, this.processedData));
}
if (animationEnabled) {
extraProps.push(animationValidation9());
}
const visibleProps = this.visible ? {} : { forceValue: 0 };
const radiusScaleType = this.axes[ChartAxisDirection51.Radius]?.scale.type;
const angleScaleType = this.axes[ChartAxisDirection51.Angle]?.scale.type;
const allowNullKey = this.properties.allowNullKeys ?? false;
await this.requestDataModel(dataController, this.data, {
props: [
keyProperty11(radiusKey, radiusScaleType, { id: "radiusValue", allowNullKey }),
valueProperty17(angleKey, angleScaleType, {
id: "angleValue-raw",
invalidValue: null,
...visibleProps
}),
...groupAccumulativeValueProperty3(
angleKey,
"normal",
{
id: `angleValue-end`,
rangeId: `angleValue-range`,
invalidValue: null,
groupId: stackGroupId,
separateNegative: true,
...visibleProps
},
angleScaleType
),
...groupAccumulativeValueProperty3(
angleKey,
"trailing",
{
id: `angleValue-start`,
invalidValue: null,
groupId: stackGroupTrailingId,
separateNegative: true,
...visibleProps
},
angleScaleType
),
...extraProps
],
groupByKeys: true,
groupByData: false
});
this.animationState.transition("updateData");
}
didCircleChange() {
const r = this.radius;
const cx = this.centerX;
const cy = this.centerY;
const cache = this.circleCache;
if (!(r === cache.r && cx === cache.cx && cy === cache.cy)) {
this.circleCache = { r, cx, cy };
return true;
}
return false;
}
maybeRefreshNodeData() {
const circleChanged = this.didCircleChange();
if (!circleChanged && !this.nodeDataRefresh)
return;
this.contextNodeData = this.createNodeData();
this.nodeData = this.contextNodeData?.nodeData ?? [];
this.nodeDataRefresh = false;
}
getAxisInnerRadius() {
const radiusAxis = this.axes[ChartAxisDirection51.Radius];
return radiusAxis instanceof PolarAxis3 ? this.radius * radiusAxis.innerRadiusRatio : 0;
}
createNodeData() {
const { processedData, dataModel } = this;
if (!dataModel || processedData?.type !== "grouped")
return;
const angleAxis = this.axes[ChartAxisDirection51.Angle];
const radiusAxis = this.axes[ChartAxisDirection51.Radius];
const angleScale = angleAxis?.scale;
const radiusScale = radiusAxis?.scale;
if (!angleScale || !radiusScale) {
return;
}
const radiusValues = dataModel.resolveKeysById(this, "radiusValue", processedData);
const angleStartValues = dataModel.resolveColumnById(this, `angleValue-start`, processedData);
const angleEndValues = dataModel.resolveColumnById(this, `angleValue-end`, processedData);
const angleRawValues = dataModel.resolveColumnById(this, `angleValue-raw`, processedData);
const angleRangeIndex = dataModel.resolveProcessedDataIndexById(this, `angleValue-range`);
let groupPaddingInner = 0;
if (radiusAxis instanceof RadiusCategoryAxis) {
groupPaddingInner = radiusAxis.groupPaddingInner;
}
const { groupScale } = this;
const { index: groupIndex, visibleGroupCount } = this.ctx.seriesStateManager.getVisiblePeerGroupIndex(this);
groupScale.domain = Array.from({ length: visibleGroupCount }).map((_, i) => String(i));
groupScale.range = [0, Math.abs(radiusScale.bandwidth ?? 0)];
groupScale.paddingInner = visibleGroupCount > 1 ? groupPaddingInner : 0;
const barWidth = groupScale.bandwidth >= 1 ? groupScale.bandwidth : groupScale.rawBandwidth;
const angleAxisReversed = angleAxis.isReversed();
const radiusAxisReversed = radiusAxis.isReversed();
const axisInnerRadius = radiusAxisReversed ? this.radius : this.getAxisInnerRadius();
const axisOuterRadius = radiusAxisReversed ? this.getAxisInnerRadius() : this.radius;
const axisTotalRadius = axisOuterRadius + axisInnerRadius;
const angleDomain = this.getSeriesDomain(ChartAxisDirection51.Angle).domain;
const { angleKey, radiusKey, angleName, radiusName, legendItemName, label } = this.properties;
const getLabelNodeDatum = (datum, angleDatum, x, y) => {
const labelText = this.getLabelText(
angleDatum,
datum,
angleKey,
"angle",
angleDomain,
label,
{ value: angleDatum, datum, angleKey, radiusKey, angleName, radiusName, legendItemName }
);
if (labelText) {
return { x, y, text: labelText, textAlign: "center", textBaseline: "middle" };
}
};
const nodeData = [];
const styles = getItemStyles4(
(nodeDatum, isHighlight, highlightState) => getItemStyle(this, nodeDatum, isHighlight, highlightState)
);
const context = {
itemId: radiusKey,
nodeData,
labelData: nodeData,
styles
};
if (!this.visible)
return context;
const { dataSources } = processedData;
const rawData = dataSources.get(this.id)?.data ?? [];
for (const { datumIndex, group } of dataModel.forEachGroupDatum(this, processedData)) {
const datum = rawData[datumIndex];
const radiusDatum = radiusValues[datumIndex];
if (radiusDatum === void 0 && !this.properties.allowNullKeys)
return;
const angleDatum = angleRawValues[datumIndex];
const angleStartDatum = angleStartValues[datumIndex];
const angleEndDatum = angleEndValues[datumIndex];
const isPositive = angleDatum >= 0 && !Object.is(angleDatum, -0);
const angleRange = group.aggregation[angleRangeIndex][isPositive ? 1 : 0];
const reversed = isPositive === angleAxisReversed;
let startAngle = angleScale.convert(angleStartDatum, { clamp: true });
let endAngle = angleScale.convert(angleEndDatum, { clamp: true });
let rangeStartAngle = angleScale.convert(0, { clamp: true });
let rangeEndAngle = angleScale.convert(angleRange, { clamp: true });
if (reversed) {
[rangeStartAngle, rangeEndAngle] = [rangeEndAngle, rangeStartAngle];
[startAngle, endAngle] = [endAngle, startAngle];
}
const dataRadius = axisTotalRadius - radiusScale.convert(radiusDatum);
const innerRadius = dataRadius + groupScale.convert(String(groupIndex));
const outerRadius = innerRadius + barWidth;
const midRadius = (innerRadius + outerRadius) / 2;
const midAngle = startAngle + angleBetween3(startAngle, endAngle) / 2;
const x = Math.cos(midAngle) * midRadius;
const y = Math.sin(midAngle) * midRadius;
const labelNodeDatum = this.properties.label.enabled ? getLabelNodeDatum(datum, angleDatum, x, y) : void 0;
const clipSector = new SectorBox4(startAngle, endAngle, innerRadius, outerRadius);
nodeData.push({
series: this,
datum,
datumIndex,
point: { x, y, size: 0 },
midPoint: { x, y },
label: labelNodeDatum,
angleValue: angleDatum,
radiusValue: radiusDatum,
innerRadius,
outerRadius,
startAngle: rangeStartAngle,
endAngle: rangeEndAngle,
clipSector,
reversed,
index: datumIndex
});
}
return context;
}
update({ seriesRect }) {
const resize = this.checkResize(seriesRect);
this.maybeRefreshNodeData();
this.contentGroup.translationX = this.centerX;
this.contentGroup.translationY = this.centerY;
this.highlightGroup.translationX = this.centerX;
this.highlightGroup.translationY = this.centerY;
if (this.labelGroup) {
this.labelGroup.translationX = this.centerX;
this.labelGroup.translationY = this.centerY;
}
this.updateSectorSelection(this.itemSelection, false);
this.updateSectorSelection(this.highlightSelection, true);
this.updateLabels();
if (resize) {
this.animationState.transition("resize");
}
this.animationState.transition("update");
}
updateSectorSelection(selection, isHighlight) {
let selectionData = [];
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
if (isHighlight) {
if (activeHighlight?.datum && activeHighlight.series === this) {
selectionData.push(activeHighlight);
}
} else {
selectionData = this.nodeData;
}
const { contextNodeData } = this;
if (!contextNodeData) {
return;
}
const highlightedDatum = this.ctx.highlightManager.getActiveHighlight();
const fillBBox = this.getShapeFillBBox();
const hasItemStylers = this.hasItemStylers();
selection.update(selectionData, void 0, (datum) => this.getDatumId(datum)).each((node, nodeDatum) => {
const datum = readDatum(nodeDatum);
if (datum == null)
return;
if (hasItemStylers) {
const highlightState = this.getHighlightState(activeHighlight, isHighlight, nodeDatum.datumIndex);
nodeDatum.style = getItemStyle(this, nodeDatum, isHighlight, highlightState);
}
const style = nodeDatum.style ?? contextNodeData.styles[this.getHighlightState(highlightedDatum, isHighlight, nodeDatum.datumIndex)];
const cornerRadius = style.cornerRadius;
const fill = style.fill;
const fillParams = isGradientFill3(fill) && fill.bounds !== "item" ? { centerX: 0, centerY: 0 } : void 0;
node.setStyleProperties(style, fillBBox, fillParams);
node.lineJoin = "round";
node.inset = node.stroke == null ? 0 : node.strokeWidth / 2;
node.startInnerCornerRadius = datum.reversed ? cornerRadius : 0;
node.startOuterCornerRadius = datum.reversed ? cornerRadius : 0;
node.endInnerCornerRadius = datum.reversed ? 0 : cornerRadius;
node.endOuterCornerRadius = datum.reversed ? 0 : cornerRadius;
if (isHighlight) {
node.startAngle = nodeDatum.startAngle;
node.endAngle = nodeDatum.endAngle;
node.clipSector = nodeDatum.clipSector;
node.innerRadius = nodeDatum.innerRadius;
node.outerRadius = nodeDatum.outerRadius;
}
});
}
updateLabels() {
const { properties } = this;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightDatum = activeHighlight?.series === this && activeHighlight?.datum ? activeHighlight : void 0;
const highlightData = highlightDatum ? [highlightDatum] : [];
this.labelSelection.update(this.nodeData).each((node, datum) => {
const isHighlight = false;
updateLabelNode8(this, node, properties, properties.label, datum.label, isHighlight, activeHighlight);
node.fillOpacity = this.getHighlightStyle(isHighlight, datum.datumIndex).opacity ?? 1;
});
this.highlightLabelSelection.update(highlightData, void 0, (datum) => this.getDatumId(datum)).each((node, datum) => {
const isHighlight = true;
updateLabelNode8(this, node, properties, properties.label, datum.label, isHighlight, activeHighlight);
node.fillOpacity = this.getHighlightStyle(isHighlight, datum.datumIndex).opacity ?? 1;
});
}
getBarTransitionFunctions() {
const angleScale = this.axes[ChartAxisDirection51.Angle]?.scale;
let axisZeroAngle = 0;
if (!angleScale) {
return prepareRadialBarSeriesAnimationFunctions(axisZeroAngle);
}
const d0 = Math.min(angleScale.domain[0], angleScale.domain[1]);
const d1 = Math.max(angleScale.domain[0], angleScale.domain[1]);
if (d0 <= 0 && d1 >= 0) {
axisZeroAngle = angleScale.convert(0);
}
return prepareRadialBarSeriesAnimationFunctions(axisZeroAngle);
}
animateEmptyUpdateReady() {
const { labelSelection } = this;
const fns = this.getBarTransitionFunctions();
motion10.fromToMotion(this.id, "datums", this.ctx.animationManager, [this.itemSelection], fns);
seriesLabelFadeInAnimation8(
this,
"labels",
this.ctx.animationManager,
labelSelection,
this.highlightLabelSelection
);
}
animateClearingUpdateEmpty() {
const { itemSelection } = this;
const { animationManager } = this.ctx;
const fns = this.getBarTransitionFunctions();
motion10.fromToMotion(this.id, "datums", animationManager, [itemSelection], fns);
seriesLabelFadeOutAnimation2(
this,
"labels",
animationManager,
this.labelSelection,
this.highlightLabelSelection
);
}
getTooltipContent(datumIndex) {
const { id: seriesId, dataModel, processedData, axes, properties } = this;
const { angleKey, angleName, radiusKey, radiusName, legendItemName, tooltip } = properties;
const angleAxis = axes[ChartAxisDirection51.Angle];
const radiusAxis = axes[ChartAxisDirection51.Radius];
const nodeDatum = this.nodeData?.[datumIndex];
if (!dataModel || !processedData || !angleAxis || !radiusAxis || !nodeDatum)
return;
const datum = processedData.dataSources.get(this.id)?.data[datumIndex];
const radiusValue = dataModel.resolveKeysById(this, `radiusValue`, processedData)[datumIndex];
const angleValue = dataModel.resolveColumnById(this, `angleValue-raw`, processedData)[datumIndex];
if (radiusValue === void 0 && !this.properties.allowNullKeys)
return;
const format = getItemStyle(this, nodeDatum, false);
return this.formatTooltipWithContext(
tooltip,
{
heading: this.getAxisValueText(radiusAxis, "tooltip", radiusValue, datum, radiusKey, void 0),
symbol: this.legendItemSymbol(),
data: [
{
label: angleName,
fallbackLabel: angleKey,
value: this.getAxisValueText(angleAxis, "tooltip", angleValue, datum, angleKey, void 0),
missing: _ModuleSupport195.isTooltipValueMissing(angleValue)
}
]
},
{
seriesId,
datum,
title: angleName,
angleKey,
angleName,
radiusKey,
radiusName,
legendItemName,
...format
}
);
}
pickNodeClosestDatum(point) {
return this.pickNodeNearestDistantObject(point, this.itemSelection.nodes());
}
legendItemSymbol() {
const { fill, stroke: stroke3, fillOpacity, strokeOpacity, strokeWidth, lineDash, lineDashOffset } = getStyle(
this,
false,
_ModuleSupport195.HighlightState.None
);
const markerStyle = {
fill: fill ?? "rgba(0, 0, 0, 0)",
stroke: stroke3 ?? "rgba(0, 0, 0, 0)",
fillOpacity,
strokeOpacity,
strokeWidth,
lineDash,
lineDashOffset
};
if (isGradientFill3(markerStyle.fill)) {
markerStyle.fill = { ...markerStyle.fill, gradient: "linear", rotation: 0, reverse: false };
}
return {
marker: markerStyle
};
}
getLegendData(legendType) {
if (legendType !== "category") {
return [];
}
const { id: seriesId, visible } = this;
const { angleKey, angleName, legendItemName, showInLegend } = this.properties;
return [
{
legendType: "category",
id: seriesId,
itemId: angleKey,
seriesId,
enabled: visible,
label: {
text: legendItemName ?? angleName ?? angleKey
},
symbol: this.legendItemSymbol(),
legendItemName,
hideInLegend: !showInLegend
}
];
}
getDatumId(datum) {
return createDatumId19(datum.radiusValue);
}
computeLabelsBBox() {
return null;
}
getStackId() {
const groupIndex = this.seriesGrouping?.groupIndex ?? this.id;
return `radialBar-stack-${groupIndex}-xValues`;
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.styler != null || this.properties.label.itemStyler != null;
}
};
RadialBarSeries.className = "RadialBarSeries";
RadialBarSeries.type = "radial-bar";
// packages/ag-charts-enterprise/src/series/radial-bar/radialBarSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport196 } from "ag-charts-community";
import {
boolean as boolean18,
commonSeriesOptionsDefs as commonSeriesOptionsDefs19,
constant as constant20,
number as number9,
required as required20,
string as string20,
undocumented as undocumented15
} from "ag-charts-core";
var { radialBarSeriesThemeableOptionsDef } = _ModuleSupport196;
var radialBarSeriesOptionsDef = {
...commonSeriesOptionsDefs19,
...radialBarSeriesThemeableOptionsDef,
type: required20(constant20("radial-bar")),
angleKey: required20(string20),
radiusKey: required20(string20),
angleName: string20,
radiusName: string20,
legendItemName: string20,
grouped: boolean18,
stacked: boolean18,
stackGroup: string20,
normalizedTo: number9
};
radialBarSeriesOptionsDef.angleKeyAxis = undocumented15(string20);
radialBarSeriesOptionsDef.radiusKeyAxis = undocumented15(string20);
// packages/ag-charts-enterprise/src/series/radial-bar/radialBarThemes.ts
import {
FILL_GRADIENT_CONIC_SERIES_DEFAULTS,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS15,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS10,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS15,
MULTI_SERIES_HIGHLIGHT_STYLE as MULTI_SERIES_HIGHLIGHT_STYLE8,
POLAR_AXIS_TYPE as POLAR_AXIS_TYPE6
} from "ag-charts-core";
var RADIAL_BAR_SERIES_THEME = {
series: {
fill: {
$applySwitch: [
{ $path: "type" },
{ $palette: "fill" },
["gradient", FILL_GRADIENT_CONIC_SERIES_DEFAULTS],
["image", FILL_IMAGE_DEFAULTS15],
["pattern", FILL_PATTERN_DEFAULTS10]
]
},
stroke: { $palette: "stroke" },
strokeWidth: { $isUserOption: ["./stroke", 1, 0] },
label: {
...LABEL_BOXING_DEFAULTS15,
enabled: false,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "chartBackgroundColor" }
},
highlight: MULTI_SERIES_HIGHLIGHT_STYLE8
},
axes: {
[POLAR_AXIS_TYPE6.RADIUS_CATEGORY]: {
innerRadiusRatio: 0.2,
groupPaddingInner: 0.2,
paddingInner: 0.2,
paddingOuter: 0.1
}
}
};
// packages/ag-charts-enterprise/src/series/radial-bar/radialBarModule.ts
var RadialBarSeriesModule = {
type: "series",
name: "radial-bar",
chartType: "polar",
enterprise: true,
stackable: true,
groupable: true,
version: VERSION45,
dependencies: [PolarChartModule4],
options: radialBarSeriesOptionsDef,
defaultAxes: { angle: { type: POLAR_AXIS_TYPE7.ANGLE_NUMBER }, radius: { type: POLAR_AXIS_TYPE7.RADIUS_CATEGORY } },
axisKeys: { [ChartAxisDirection52.Angle]: "angleKeyAxis", [ChartAxisDirection52.Radius]: "radiusKeyAxis" },
themeTemplate: RADIAL_BAR_SERIES_THEME,
create: (ctx) => new RadialBarSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnModule.ts
import { PolarChartModule as PolarChartModule5, VERSION as VERSION46 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection54, POLAR_AXIS_TYPE as POLAR_AXIS_TYPE9 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnSeries.ts
import { _ModuleSupport as _ModuleSupport197 } from "ag-charts-community";
import { ChartAxisDirection as ChartAxisDirection53 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnSeriesProperties.ts
import { Property as Property85 } from "ag-charts-core";
var RadialColumnSeriesProperties = class extends RadialColumnSeriesBaseProperties {
};
__decorateClass([
Property85
], RadialColumnSeriesProperties.prototype, "columnWidthRatio", 2);
__decorateClass([
Property85
], RadialColumnSeriesProperties.prototype, "maxColumnWidthRatio", 2);
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnSeries.ts
var { PolarAxis: PolarAxis4, RadialColumnShape, getRadialColumnWidth } = _ModuleSupport197;
var RadialColumnSeries = class extends RadialColumnSeriesBase {
constructor(moduleCtx) {
super(moduleCtx, {
animationResetFns: {
item: resetRadialColumnSelectionFn
}
});
this.properties = new RadialColumnSeriesProperties();
}
getStackId() {
const groupIndex = this.seriesGrouping?.groupIndex ?? this.id;
return `radarColumn-stack-${groupIndex}-yValues`;
}
nodeFactory() {
return new RadialColumnShape();
}
getColumnTransitionFunctions() {
const axisZeroRadius = this.isRadiusAxisReversed() ? this.radius : this.getAxisInnerRadius();
return prepareRadialColumnAnimationFunctions(axisZeroRadius);
}
isRadiusAxisCircle() {
const radiusAxis = this.axes[ChartAxisDirection53.Radius];
return radiusAxis instanceof PolarAxis4 ? radiusAxis.shape === "circle" : false;
}
updateItemPath(node, datum, highlight) {
node.isBeveled = this.isRadiusAxisCircle();
if (highlight) {
node.innerRadius = datum.innerRadius;
node.outerRadius = datum.outerRadius;
node.startAngle = datum.startAngle;
node.endAngle = datum.endAngle;
node.columnWidth = datum.columnWidth;
node.axisInnerRadius = datum.axisInnerRadius;
node.axisOuterRadius = datum.axisOuterRadius;
}
}
getColumnWidth(startAngle, endAngle) {
const { columnWidthRatio = 0.5, maxColumnWidthRatio = 0.5 } = this.properties;
return getRadialColumnWidth(startAngle, endAngle, this.radius, columnWidthRatio, maxColumnWidthRatio);
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.styler != null || this.properties.label.itemStyler != null;
}
};
RadialColumnSeries.className = "RadialColumnSeries";
RadialColumnSeries.type = "radial-column";
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport198 } from "ag-charts-community";
import {
boolean as boolean19,
commonSeriesOptionsDefs as commonSeriesOptionsDefs20,
constant as constant21,
number as number10,
required as required21,
string as string21,
undocumented as undocumented16
} from "ag-charts-core";
var { radialColumnSeriesThemeableOptionsDef } = _ModuleSupport198;
var radialColumnSeriesOptionsDef = {
...commonSeriesOptionsDefs20,
...radialColumnSeriesThemeableOptionsDef,
type: required21(constant21("radial-column")),
angleKey: required21(string21),
radiusKey: required21(string21),
angleName: string21,
radiusName: string21,
legendItemName: string21,
grouped: boolean19,
stacked: boolean19,
stackGroup: string21,
normalizedTo: number10
};
radialColumnSeriesOptionsDef.angleKeyAxis = undocumented16(string21);
radialColumnSeriesOptionsDef.radiusKeyAxis = undocumented16(string21);
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnThemes.ts
import {
FILL_GRADIENT_RADIAL_SERIES_DEFAULTS as FILL_GRADIENT_RADIAL_SERIES_DEFAULTS2,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS16,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS11,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS16,
MULTI_SERIES_HIGHLIGHT_STYLE as MULTI_SERIES_HIGHLIGHT_STYLE9,
POLAR_AXIS_SHAPE as POLAR_AXIS_SHAPE2,
POLAR_AXIS_TYPE as POLAR_AXIS_TYPE8
} from "ag-charts-core";
var RADIAL_COLUMN_SERIES_THEME = {
series: {
fill: {
$applySwitch: [
{ $path: "type" },
{ $palette: "fill" },
["gradient", FILL_GRADIENT_RADIAL_SERIES_DEFAULTS2],
["image", FILL_IMAGE_DEFAULTS16],
["pattern", FILL_PATTERN_DEFAULTS11]
]
},
stroke: { $palette: "stroke" },
columnWidthRatio: 0.5,
maxColumnWidthRatio: 0.5,
strokeWidth: { $isUserOption: ["./stroke", 1, 0] },
label: {
...LABEL_BOXING_DEFAULTS16,
enabled: false,
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "textColor" }
},
highlight: MULTI_SERIES_HIGHLIGHT_STYLE9
},
axes: {
[POLAR_AXIS_TYPE8.ANGLE_CATEGORY]: {
shape: { $findFirstSiblingNotOperation: POLAR_AXIS_SHAPE2.CIRCLE },
groupPaddingInner: 0,
paddingInner: 0,
label: {
spacing: 10
}
},
[POLAR_AXIS_TYPE8.RADIUS_NUMBER]: {
shape: { $findFirstSiblingNotOperation: POLAR_AXIS_SHAPE2.CIRCLE },
innerRadiusRatio: 0.5
}
}
};
// packages/ag-charts-enterprise/src/series/radial-column/radialColumnModule.ts
var RadialColumnSeriesModule = {
type: "series",
name: "radial-column",
chartType: "polar",
enterprise: true,
stackable: true,
groupable: true,
version: VERSION46,
dependencies: [PolarChartModule5],
options: radialColumnSeriesOptionsDef,
defaultAxes: { angle: { type: POLAR_AXIS_TYPE9.ANGLE_CATEGORY }, radius: { type: POLAR_AXIS_TYPE9.RADIUS_NUMBER } },
axisKeys: { [ChartAxisDirection54.Angle]: "angleKeyAxis", [ChartAxisDirection54.Radius]: "radiusKeyAxis" },
themeTemplate: RADIAL_COLUMN_SERIES_THEME,
create: (ctx) => new RadialColumnSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/radial-gauge/radialGaugeModule.ts
import { VERSION as VERSION47 } from "ag-charts-community";
import {
FONT_SIZE_RATIO as FONT_SIZE_RATIO3,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS17,
SAFE_RANGE2_OPERATION as SAFE_RANGE2_OPERATION7,
SAFE_STROKE_FILL_OPERATION as SAFE_STROKE_FILL_OPERATION4,
radialGaugeSeriesOptionsDef as radialGaugeSeriesOptionsDef2
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radial-gauge/radialGaugeSeries.ts
import {
_ModuleSupport as _ModuleSupport202
} from "ag-charts-community";
import {
StateMachine as StateMachine15,
isBetweenAngles as isBetweenAngles2,
isNumberEqual as isNumberEqual10,
mergeDefaults as mergeDefaults21,
normalizeAngle360 as normalizeAngle3607,
normalizeAngle360Inclusive as normalizeAngle360Inclusive3,
tickFormat as tickFormat2,
toPlainText as toPlainText10,
toRadians as toRadians5
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/radial-gauge/radialGaugeNeedle.ts
import { _ModuleSupport as _ModuleSupport199 } from "ag-charts-community";
var { SvgPath, Rotatable, Translatable, Scalable: Scalable2 } = _ModuleSupport199;
var RadialGaugeNeedle = class extends Rotatable(Scalable2(Translatable(SvgPath))) {
constructor() {
super(...arguments);
this.scalingCenterX = 0.5;
this.scalingCenterY = 0.5;
this.rotationCenterX = 0.5;
this.rotationCenterY = 0.5;
}
};
RadialGaugeNeedle.defaultPathData = "M0.50245 0.53745C0.481767 0.53745 0.465 0.520683 0.465 0.5C0.465 0.479317 0.481767 0.46255 0.50245 0.46255L1 0.500012L0.50245 0.53745Z";
// packages/ag-charts-enterprise/src/series/radial-gauge/radialGaugeSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport200 } from "ag-charts-community";
import {
BaseProperties as BaseProperties34,
PropertiesArray as PropertiesArray8,
Property as Property86,
normalizeAngle360 as normalizeAngle3606,
normalizeAngle360Inclusive as normalizeAngle360Inclusive2,
toDegrees
} from "ag-charts-core";
var { getColorStops: getColorStops2 } = _ModuleSupport200;
var { makeSeriesTooltip: makeSeriesTooltip21, SeriesProperties: SeriesProperties12, AxisLabel: AxisLabel6, Label: Label16 } = _ModuleSupport200;
var RadialGaugeDefaultTargetLabelProperties = class extends Label16 {
};
__decorateClass([
Property86
], RadialGaugeDefaultTargetLabelProperties.prototype, "spacing", 2);
var RadialGaugeTargetProperties = class extends BaseProperties34 {
constructor() {
super(...arguments);
this.label = new RadialGaugeDefaultTargetLabelProperties();
}
getStyle() {
const {
fill = "black",
fillOpacity = 1,
stroke: stroke3 = "black",
strokeWidth = 0,
strokeOpacity = 1,
lineDash = [0],
lineDashOffset = 0
} = this;
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
};
}
};
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "text", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "value", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "shape", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "placement", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "spacing", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "size", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "rotation", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "fill", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "stroke", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "lineDash", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property86
], RadialGaugeTargetProperties.prototype, "label", 2);
var RadialGaugeBarProperties = class extends BaseProperties34 {
constructor() {
super(...arguments);
this.enabled = true;
this.fills = new PropertiesArray8(_ModuleSupport200.StopProperties);
this.fillMode = "continuous";
this.fillOpacity = 1;
this.stroke = "black";
this.strokeWidth = 0;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
}
getStyle(defaultColorRange, scale) {
const {
enabled,
fill,
fills,
fillMode,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
} = this;
const barFill = enabled ? fill ?? createConicGradient(fills, fillMode, defaultColorRange, scale) : "none";
return {
fill: barFill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
};
}
};
__decorateClass([
Property86
], RadialGaugeBarProperties.prototype, "enabled", 2);
__decorateClass([
Property86
], RadialGaugeBarProperties.prototype, "fills", 2);
__decorateClass([
Property86
], RadialGaugeBarProperties.prototype, "fillMode", 2);
__decorateClass([
Property86
], RadialGaugeBarProperties.prototype, "fill", 2);
__decorateClass([
Property86
], RadialGaugeBarProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property86
], RadialGaugeBarProperties.prototype, "stroke", 2);
__decorateClass([
Property86
], RadialGaugeBarProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property86
], RadialGaugeBarProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property86
], RadialGaugeBarProperties.prototype, "lineDash", 2);
__decorateClass([
Property86
], RadialGaugeBarProperties.prototype, "lineDashOffset", 2);
var RadialGaugeScaleIntervalProperties = class extends BaseProperties34 {
constructor() {
super(...arguments);
this.values = void 0;
this.step = void 0;
this.minSpacing = 0;
this.maxSpacing = 1e3;
}
};
__decorateClass([
Property86
], RadialGaugeScaleIntervalProperties.prototype, "values", 2);
__decorateClass([
Property86
], RadialGaugeScaleIntervalProperties.prototype, "step", 2);
__decorateClass([
Property86
], RadialGaugeScaleIntervalProperties.prototype, "minSpacing", 2);
__decorateClass([
Property86
], RadialGaugeScaleIntervalProperties.prototype, "maxSpacing", 2);
var RadialGaugeScaleLabelProperties = class extends AxisLabel6 {
};
var RadialGaugeScaleProperties = class extends BaseProperties34 {
constructor() {
super(...arguments);
this.min = 0;
this.max = 1;
this.fills = new PropertiesArray8(_ModuleSupport200.StopProperties);
this.fillMode = "continuous";
this.fillOpacity = 1;
this.stroke = "black";
this.strokeWidth = 0;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
this.defaultFill = "black";
this.interval = new RadialGaugeScaleIntervalProperties();
this.label = new RadialGaugeScaleLabelProperties();
}
getStyle(barEnabled, defaultColorRange, scale) {
const {
fill,
fills,
defaultFill,
fillMode,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
} = this;
const scaleFill = fill ?? (barEnabled && fills.length === 0 ? defaultFill : void 0) ?? createConicGradient(fills, fillMode, defaultColorRange, scale);
return {
fill: scaleFill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
};
}
};
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "min", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "max", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "fills", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "fillMode", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "fill", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "stroke", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "lineDash", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "defaultFill", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "interval", 2);
__decorateClass([
Property86
], RadialGaugeScaleProperties.prototype, "label", 2);
var RadialGaugeNeedleProperties = class extends BaseProperties34 {
constructor() {
super(...arguments);
this.enabled = true;
this.spacing = 0;
this.fill = "black";
this.fillOpacity = 1;
this.stroke = "black";
this.strokeWidth = 0;
this.strokeOpacity = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
}
};
__decorateClass([
Property86
], RadialGaugeNeedleProperties.prototype, "enabled", 2);
__decorateClass([
Property86
], RadialGaugeNeedleProperties.prototype, "radiusRatio", 2);
__decorateClass([
Property86
], RadialGaugeNeedleProperties.prototype, "spacing", 2);
__decorateClass([
Property86
], RadialGaugeNeedleProperties.prototype, "fill", 2);
__decorateClass([
Property86
], RadialGaugeNeedleProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property86
], RadialGaugeNeedleProperties.prototype, "stroke", 2);
__decorateClass([
Property86
], RadialGaugeNeedleProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property86
], RadialGaugeNeedleProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property86
], RadialGaugeNeedleProperties.prototype, "lineDash", 2);
__decorateClass([
Property86
], RadialGaugeNeedleProperties.prototype, "lineDashOffset", 2);
var RadialGaugeLabelProperties = class extends AutoSizedLabel {
};
__decorateClass([
Property86
], RadialGaugeLabelProperties.prototype, "text", 2);
var RadialGaugeSecondaryLabelProperties = class extends AutoSizedSecondaryLabel {
};
__decorateClass([
Property86
], RadialGaugeSecondaryLabelProperties.prototype, "text", 2);
var RadialGaugeSeriesProperties = class extends SeriesProperties12 {
constructor() {
super(...arguments);
this.startAngle = 0;
this.endAngle = 0;
this.segmentation = new GaugeSegmentationProperties();
this.defaultColorRange = [];
this.targets = new PropertiesArray8(RadialGaugeTargetProperties);
this.defaultTarget = new RadialGaugeTargetProperties();
this.outerRadiusRatio = 1;
this.innerRadiusRatio = 1;
this.cornerRadius = 0;
this.cornerMode = "container";
this.spacing = 0;
this.scale = new RadialGaugeScaleProperties();
this.bar = new RadialGaugeBarProperties();
this.needle = new RadialGaugeNeedleProperties();
this.label = new RadialGaugeLabelProperties();
this.secondaryLabel = new RadialGaugeSecondaryLabelProperties();
this.tooltip = makeSeriesTooltip21();
}
};
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "value", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "startAngle", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "endAngle", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "segmentation", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "defaultColorRange", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "targets", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "defaultTarget", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "outerRadiusRatio", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "innerRadiusRatio", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "outerRadius", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "innerRadius", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "cornerRadius", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "cornerMode", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "spacing", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "scale", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "bar", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "needle", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "label", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "secondaryLabel", 2);
__decorateClass([
Property86
], RadialGaugeSeriesProperties.prototype, "tooltip", 2);
function createConicGradient(fills, fillMode, defaultColorRange, scale) {
const { domain, range: range2 } = scale;
const [startAngle, endAngle] = range2;
const conicAngle = normalizeAngle3606((startAngle + endAngle) / 2 + Math.PI);
const sweepAngle = normalizeAngle360Inclusive2(endAngle - startAngle);
const colorStops = getColorStops2(fills, defaultColorRange, domain, fillMode).map(
({ color: color7, stop }) => {
stop = Math.min(Math.max(stop, 0), 1);
const angle = startAngle + sweepAngle * stop;
stop = (angle - conicAngle) / (2 * Math.PI);
stop = (stop % 1 + 1) % 1;
return { stop, color: color7 };
}
);
return {
type: "gradient",
gradient: "conic",
colorSpace: "oklch",
colorStops,
bounds: "series",
rotation: toDegrees(conicAngle) + 90
};
}
// packages/ag-charts-enterprise/src/series/radial-gauge/radialGaugeUtil.ts
import { _ModuleSupport as _ModuleSupport201 } from "ag-charts-community";
import { toPlainText as toPlainText9 } from "ag-charts-core";
var { SectorBox: SectorBox5 } = _ModuleSupport201;
function computeClipSector(datum) {
const { startAngle, endAngle, clipStartAngle, clipEndAngle, innerRadius, outerRadius } = datum;
if (clipStartAngle == null || clipEndAngle == null)
return;
return new SectorBox5(
Math.max(clipStartAngle, startAngle),
Math.min(clipEndAngle, endAngle),
innerRadius,
outerRadius
);
}
function clipSectorVisibility(startAngle, endAngle, clipSector) {
return Math.max(startAngle, clipSector.startAngle) <= Math.min(endAngle, clipSector.endAngle);
}
function hasClipSector(datum) {
return datum.clipStartAngle != null && datum.clipEndAngle != null;
}
function datumClipSector(datum, zero) {
const { clipStartAngle, clipEndAngle, innerRadius, outerRadius } = datum;
return new SectorBox5(clipStartAngle, zero ? clipStartAngle : clipEndAngle, innerRadius, outerRadius);
}
function prepareRadialGaugeSeriesAnimationFunctions(initialLoad, initialStartAngle) {
const phase = initialLoad ? "initial" : "update";
const node = {
fromFn(sect, datum) {
const previousDatum = sect.previousDatum;
let { startAngle, endAngle } = previousDatum ?? datum;
const previousClipSector = previousDatum != null && hasClipSector(previousDatum) ? datumClipSector(previousDatum, initialLoad) : void 0;
const nextClipSector = hasClipSector(datum) ? datumClipSector(datum, initialLoad) : void 0;
let clipSector;
if (previousClipSector != null && nextClipSector != null) {
clipSector = previousClipSector;
} else if (previousClipSector == null && nextClipSector != null) {
clipSector = nextClipSector;
startAngle = datum.startAngle;
endAngle = datum.endAngle;
} else if (previousClipSector != null && nextClipSector == null) {
clipSector = void 0;
startAngle = datum.startAngle;
endAngle = datum.endAngle;
} else if (initialLoad) {
endAngle = startAngle;
}
return { startAngle, endAngle, clipSector, phase };
},
toFn(_sect, datum) {
const { startAngle, endAngle } = datum;
let clipSector;
if (hasClipSector(datum)) {
clipSector = datumClipSector(datum, false);
}
return { startAngle, endAngle, clipSector };
},
applyFn(sect, params) {
const { startAngle, endAngle } = params;
let { clipSector } = params;
if (clipSector != null) {
clipSector = new SectorBox5(
Math.max(startAngle, clipSector.startAngle),
Math.min(endAngle, clipSector.endAngle),
clipSector.innerRadius,
clipSector.outerRadius
);
}
const visible = clipSector == null || clipSectorVisibility(startAngle, endAngle, clipSector);
sect.startAngle = startAngle;
sect.endAngle = endAngle;
sect.clipSector = clipSector;
sect.visible = visible;
}
};
const needle = {
fromFn(needleNode) {
let { angle: rotation } = needleNode.previousDatum ?? needleNode.datum;
if (initialLoad) {
rotation = initialStartAngle;
}
return { rotation, phase };
},
toFn(_needleNode, datum) {
const { angle: rotation } = datum;
return { rotation };
}
};
return { node, needle };
}
function resetRadialGaugeSeriesResetSectorFunction(_node, datum) {
const { startAngle, endAngle } = datum;
const clipSector = computeClipSector(datum);
const visible = clipSector == null || clipSectorVisibility(startAngle, endAngle, clipSector);
return { startAngle, endAngle, clipSector, visible };
}
function resetRadialGaugeSeriesResetNeedleFunction(_node, datum) {
const { angle } = datum;
return { rotation: angle };
}
var verticalAlignFactors3 = {
top: 0,
middle: 0.5,
bottom: 1
};
function formatRadialGaugeLabels(series, ctx, selection, opts, innerRadius, datumOverrides) {
const { padding: padding2, textAlign, verticalAlign } = opts;
let labelDatum;
let secondaryLabelDatum;
selection.each((_node, datum) => {
if (datum.label === "primary" /* Primary */) {
labelDatum = datum;
} else if (datum.label === "secondary" /* Secondary */) {
secondaryLabelDatum = datum;
}
});
if (labelDatum == null)
return;
const labelText = getLabelText(series.id, ctx, labelDatum, datumOverrides?.label);
if (labelText == null)
return;
const secondaryLabelText = secondaryLabelDatum == null ? void 0 : getLabelText(series.id, ctx, secondaryLabelDatum, datumOverrides?.secondaryLabel);
const params = { padding: padding2 };
const horizontalFactor = textAlign === "center" ? 2 : 1;
const verticalFactor = verticalAlign === "middle" ? 2 : 1;
const sizeFittingHeight = (height2) => ({
width: Math.sqrt(Math.max(innerRadius ** 2 - (height2 / verticalFactor) ** 2, 0)) * horizontalFactor,
height: Math.min(height2, verticalFactor * innerRadius),
meta: null
});
let labelLayout;
let secondaryLabelLayout;
let height;
if (secondaryLabelDatum != null && secondaryLabelText != null) {
const layout = formatStackedLabels(
toPlainText9(labelText),
labelDatum,
toPlainText9(secondaryLabelText),
secondaryLabelDatum,
params,
sizeFittingHeight
);
labelLayout = layout?.label;
secondaryLabelLayout = layout?.secondaryLabel;
height = layout?.height ?? 0;
} else {
const layout = formatSingleLabel(toPlainText9(labelText), labelDatum, params, sizeFittingHeight);
labelLayout = layout?.[0];
secondaryLabelLayout = void 0;
height = layout?.[0].height ?? 0;
}
const rectYOffset = height * verticalAlignFactors3[verticalAlign];
selection.each((label, datum) => {
let layout;
if (datum.label === "primary" /* Primary */) {
layout = labelLayout;
} else if (datum.label === "secondary" /* Secondary */) {
layout = secondaryLabelLayout;
}
if (layout == null) {
label.visible = false;
return;
}
label.visible = true;
label.text = layout.text;
label.fontSize = layout.fontSize;
label.lineHeight = layout.lineHeight;
label.textAlign = textAlign;
label.textBaseline = "middle";
const rectOriginInLabelRect = datum.label === "primary" /* Primary */ ? layout.height / 2 : height - layout.height / 2;
label.y = datum.centerY + rectOriginInLabelRect - rectYOffset;
label.x = datum.centerX;
});
}
// packages/ag-charts-enterprise/src/series/radial-gauge/radialGaugeSeries.ts
var {
fromToMotion: fromToMotion5,
resetMotion: resetMotion4,
SeriesNodePickMode: SeriesNodePickMode15,
createDatumId: createDatumId20,
sectorBox,
BBox: BBox25,
Group: Group20,
PointerEvents: PointerEvents12,
Selection: Selection16,
Sector: Sector6,
SectorBox: SectorBox6,
Transformable: Transformable4,
TransformableText: TransformableText3,
Text: Text9,
Marker: Marker6
} = _ModuleSupport202;
var targetPlacementRotation = {
inside: 90,
middle: 0,
outside: -90
};
var outsideLabelPlacements = [
{ textAlign: "left", textBaseline: "top" },
{ textAlign: "right", textBaseline: "top" },
{ textAlign: "right", textBaseline: "bottom" },
{ textAlign: "left", textBaseline: "bottom" }
];
var insideLabelPlacements = [
{ textAlign: "right", textBaseline: "bottom" },
{ textAlign: "left", textBaseline: "bottom" },
{ textAlign: "left", textBaseline: "top" },
{ textAlign: "right", textBaseline: "top" }
];
var RadialGaugeSeries = class extends _ModuleSupport202.Series {
constructor(moduleCtx) {
super({
moduleCtx,
pickModes: [SeriesNodePickMode15.EXACT_SHAPE_MATCH, SeriesNodePickMode15.NEAREST_NODE]
});
this.centerX = 0;
this.centerY = 0;
this.radius = 0;
this.textAlign = "center";
this.verticalAlign = "middle";
this.properties = new RadialGaugeSeriesProperties();
this.scale = new LinearAngleScale();
this.scaleGroup = this.contentGroup.appendChild(new Group20({ name: "scaleGroup" }));
this.itemGroup = this.contentGroup.appendChild(new Group20({ name: "itemGroup" }));
this.itemNeedleGroup = this.contentGroup.appendChild(new Group20({ name: "itemNeedleGroup" }));
this.itemTargetGroup = this.contentGroup.appendChild(new Group20({ name: "itemTargetGroup" }));
this.itemTargetLabelGroup = this.contentGroup.appendChild(new Group20({ name: "itemTargetLabelGroup" }));
this.itemLabelGroup = this.contentGroup.appendChild(new Group20({ name: "itemLabelGroup" }));
this.highlightTargetGroup = this.highlightGroup.appendChild(
new Group20({ name: "itemTargetLabelGroup" })
);
this.tickGroup = this.contentGroup.appendChild(new Group20({ name: "tickGroup" }));
this.scaleSelection = Selection16.select(
this.scaleGroup,
() => this.nodeFactory()
);
this.datumSelection = Selection16.select(
this.itemGroup,
() => this.nodeFactory()
);
this.needleSelection = Selection16.select(
this.itemNeedleGroup,
RadialGaugeNeedle
);
this.targetSelection = Selection16.select(
this.itemTargetGroup,
() => this.markerFactory()
);
this.targetLabelSelection = Selection16.select(this.itemTargetLabelGroup, Text9);
this.labelSelection = Selection16.select(
this.itemLabelGroup,
Text9
);
this.highlightTargetSelection = Selection16.select(this.highlightTargetGroup, () => this.markerFactory());
this.tickSelection = Selection16.select(this.tickGroup, _ModuleSupport202.TransformableText);
this.datumUnion = new DatumUnion();
this.animationState = new StateMachine15("empty", {
empty: {
update: {
target: "ready",
action: () => this.animateEmptyUpdateReady()
},
reset: "empty",
skip: "ready"
},
ready: {
updateData: "waiting",
clear: "clearing",
resize: () => this.animateReadyResize(),
reset: "empty",
skip: "ready"
},
waiting: {
update: {
target: "ready",
action: () => this.animateWaitingUpdateReady()
},
reset: "empty",
skip: "ready"
},
clearing: {
update: {
target: "empty"
},
reset: "empty",
skip: "ready"
}
});
this.scaleGroup.pointerEvents = PointerEvents12.None;
this.tickGroup.pointerEvents = PointerEvents12.None;
this.itemNeedleGroup.pointerEvents = PointerEvents12.None;
this.itemLabelGroup.pointerEvents = PointerEvents12.None;
}
get hasData() {
return this.properties.value != null;
}
nodeFactory() {
return new Sector6();
}
markerFactory() {
const marker = new Marker6();
marker.size = 1;
return marker;
}
processData() {
this.nodeDataRefresh = true;
this.animationState.transition("updateData");
}
formatLabel(value) {
const { min, max } = this.properties.scale;
return formatLabel(value, { min, max });
}
layoutScale() {
const { scale, properties } = this;
const { seriesRectWidth, seriesRectHeight } = this.nodeDataDependencies;
const { scale: scaleProps, outerRadius } = this.properties;
const { min, max, label, interval } = scaleProps;
const startAngle = toRadians5(properties.startAngle - 90);
const endAngle = toRadians5(properties.endAngle - 90);
const sweepAngle = normalizeAngle360Inclusive3(endAngle - startAngle);
const largerThanHalf = sweepAngle > Math.PI;
const containsTop = largerThanHalf || isBetweenAngles2(1.5 * Math.PI, startAngle, endAngle);
const containsRight = largerThanHalf || isBetweenAngles2(0 * Math.PI, startAngle, endAngle);
const containsBottom = largerThanHalf || isBetweenAngles2(0.5 * Math.PI, startAngle, endAngle);
const containsLeft = largerThanHalf || isBetweenAngles2(1 * Math.PI, startAngle, endAngle);
let textAlign;
if (containsLeft && !containsRight) {
textAlign = "right";
} else if (!containsLeft && containsRight) {
textAlign = "left";
} else {
textAlign = "center";
}
let verticalAlign;
if (containsTop && !containsBottom) {
verticalAlign = "bottom";
} else if (!containsTop && containsBottom) {
verticalAlign = "top";
} else {
verticalAlign = "middle";
}
const unitBox = sectorBox({
startAngle,
endAngle,
innerRadius: 0,
outerRadius: 0.5
});
const centerXOffset = -(unitBox.x + unitBox.width / 2) * 2;
const centerYOffset = -(unitBox.y + unitBox.height / 2) * 2;
const unitBoxSize = Math.min(seriesRectWidth / unitBox.width, seriesRectHeight / unitBox.height);
scale.domain = [min, max];
scale.range = [startAngle, endAngle];
scale.arcLength = unitBoxSize / 2;
const { maxSpacing, minSpacing } = interval;
const { arcLength } = scale;
const minTickCount = maxSpacing ? Math.floor(arcLength / maxSpacing) : 1;
const maxTickCount = minSpacing ? Math.floor(arcLength / minSpacing) : Infinity;
const preferredTickCount = Math.floor(4 / Math.PI * Math.abs(scale.range[0] - scale.range[1]));
const tickCount = Math.max(minTickCount, Math.min(maxTickCount, preferredTickCount));
const ticks = interval.values ?? scale.ticks({
nice: [false, false],
interval: interval.step,
minTickCount,
maxTickCount,
tickCount
})?.ticks ?? [];
const tickFormatter = tickFormat2(ticks, typeof label.format === "string" ? label.format : void 0);
const tickData = [];
for (const [index, value] of ticks.entries()) {
let text2;
if (label.formatter) {
text2 = formatWithContext(this.ctx, label.formatter, {
value,
index,
domain: scale.domain,
boundSeries: void 0
});
}
text2 ?? (text2 = tickFormatter?.(value));
if (text2 == null)
continue;
tickData.push({ index, value, text: text2 });
}
const baseRadius = 0.5 * unitBoxSize;
const labelInset = label.enabled && outerRadius == null && tickData.length > 0 ? this.getTickLabelInset({
tickData,
radius: baseRadius,
centerXOffset,
centerYOffset,
seriesRectWidth,
seriesRectHeight,
spacing: label.spacing,
rotation: toRadians5(label.rotation ?? 0)
}) : 0;
const radiusBounds = Math.max(
baseRadius - labelInset,
// seriesRect may have negative size
0
);
const radius = outerRadius ?? radiusBounds;
this.centerX = seriesRectWidth / 2 + centerXOffset * radius;
this.centerY = seriesRectHeight / 2 + centerYOffset * radius;
this.radius = radius;
this.textAlign = textAlign;
this.verticalAlign = verticalAlign;
return tickData;
}
getShapeFillBBox() {
const { centerX, centerY, radius } = this;
const bbox = new BBox25(centerX - radius, centerY - radius, 2 * radius, 2 * radius);
return {
series: bbox,
axis: bbox
};
}
getTargets() {
const { properties } = this;
const defaultTarget = properties.defaultTarget;
return properties.targets.map((target) => {
const {
text: text2 = defaultTarget.text,
value = defaultTarget.value ?? 0,
shape = defaultTarget.shape ?? "triangle",
rotation = defaultTarget.rotation ?? 0,
placement = defaultTarget.placement ?? "middle",
spacing = defaultTarget.spacing ?? 0,
size = defaultTarget.size ?? 0
} = target;
const {
enabled: labelEnabled = defaultTarget.label.enabled,
color: labelColor = defaultTarget.label.color ?? "black",
fontStyle: labelFontStyle = defaultTarget.label.fontStyle ?? "normal",
fontWeight: labelFontWeight = defaultTarget.label.fontWeight ?? "normal",
fontSize: labelFontSize = defaultTarget.label.fontSize,
fontFamily: labelFontFamily = defaultTarget.label.fontFamily,
spacing: labelSpacing = defaultTarget.label.spacing ?? 0
} = target.label;
return {
text: text2,
value,
shape,
placement,
spacing,
size,
rotation,
label: {
enabled: labelEnabled,
color: labelColor,
fontStyle: labelFontStyle,
fontWeight: labelFontWeight,
fontSize: labelFontSize,
fontFamily: labelFontFamily,
spacing: labelSpacing
},
style: target.getStyle()
};
});
}
getTargetRadius(target) {
const { radius, properties } = this;
const { innerRadiusRatio, outerRadiusRatio } = properties;
const { placement, spacing, size } = target;
const outerRadius = radius * outerRadiusRatio;
const innerRadius = radius * innerRadiusRatio;
switch (placement) {
case "inside":
return Math.max(innerRadius - spacing - size / 2, 0);
case "outside":
return outerRadius + spacing + size / 2;
default:
return (innerRadius + outerRadius) / 2;
}
}
getTargetLabel(target) {
const { scale } = this;
const { value, size, placement, label } = target;
const { spacing, color: fill, fontStyle, fontWeight, fontSize, fontFamily } = label;
const angle = scale.convert(value);
const quadrant = Math.trunc(normalizeAngle3607(angle) / (Math.PI / 2));
const offset = size / 2 + spacing;
let textAlign;
let textBaseline;
let offsetX;
let offsetY;
switch (placement) {
case "outside":
({ textAlign, textBaseline } = outsideLabelPlacements[quadrant]);
offsetX = offset * Math.cos(angle);
offsetY = offset * Math.sin(angle);
break;
case "inside":
({ textAlign, textBaseline } = insideLabelPlacements[quadrant]);
offsetX = -offset * Math.cos(angle);
offsetY = -offset * Math.sin(angle);
break;
default:
textAlign = "center";
textBaseline = "bottom";
offsetX = 0;
offsetY = -offset;
break;
}
return {
offsetX,
offsetY,
fill,
textAlign,
textBaseline,
fontStyle,
fontWeight,
fontSize,
fontFamily,
lineHeight: void 0
};
}
createNodeData() {
const tickData = this.layoutScale();
const { id: seriesId, scale, properties, radius, centerX, centerY } = this;
const {
value,
innerRadiusRatio,
outerRadiusRatio,
segmentation,
cornerRadius,
cornerMode,
needle,
bar,
scale: scaleProps,
label,
secondaryLabel
} = properties;
const {
outerRadius = radius * outerRadiusRatio,
innerRadius = radius * innerRadiusRatio,
defaultColorRange
} = properties;
const targets = this.getTargets();
const nodeData = [];
const targetData = [];
const needleData = [];
const labelData = [];
const scaleData = [];
const cornersOnAllItems = cornerMode === "item";
const containerStartAngle = scale.convert(scale.domain[0]);
const containerEndAngle = scale.convert(value);
const maxTicks = Math.ceil(normalizeAngle360Inclusive3(containerEndAngle - containerStartAngle) * radius);
let segments = segmentation.enabled ? segmentation.interval.getSegments(scale, maxTicks) : void 0;
const barStyle = bar.getStyle(defaultColorRange, scale);
const scaleStyle = scaleProps.getStyle(bar.enabled, defaultColorRange, scale);
if (segments == null && cornersOnAllItems) {
const segmentStart = Math.min(...scale.domain);
const segmentEnd = Math.max(...scale.domain);
const datum = { value, segmentStart, segmentEnd };
const appliedCornerRadius = Math.min(cornerRadius, (outerRadius - innerRadius) / 2);
const angleInset = appliedCornerRadius / ((innerRadius + outerRadius) / 2);
nodeData.push({
series: this,
itemId: `value`,
datum,
datumIndex: { type: 0 /* Node */ },
type: 0 /* Node */,
centerX,
centerY,
outerRadius,
innerRadius,
startAngle: containerStartAngle - angleInset,
endAngle: containerEndAngle + angleInset,
clipStartAngle: void 0,
clipEndAngle: void 0,
startCornerRadius: cornerRadius,
endCornerRadius: cornerRadius,
style: barStyle
});
scaleData.push({
series: this,
itemId: `scale`,
datum,
datumIndex: { type: 0 /* Node */ },
type: 0 /* Node */,
centerX,
centerY,
outerRadius,
innerRadius,
startAngle: scale.range[0] - angleInset,
endAngle: scale.range[1] + angleInset,
clipStartAngle: void 0,
clipEndAngle: void 0,
startCornerRadius: cornerRadius,
endCornerRadius: cornerRadius,
style: scaleStyle
});
} else {
segments ?? (segments = scale.domain);
for (let i = 0; i < segments.length - 1; i++) {
const segmentStart = segments[i];
const segmentEnd = segments[i + 1];
const datum = { value, segmentStart, segmentEnd };
const isStart = i === 0;
const isEnd = i === segments.length - 2;
const itemStartAngle = scale.convert(segmentStart);
const itemEndAngle = scale.convert(segmentEnd);
nodeData.push({
series: this,
itemId: `value-${i}`,
datum,
datumIndex: { type: 0 /* Node */ },
type: 0 /* Node */,
centerX,
centerY,
outerRadius,
innerRadius,
startAngle: itemStartAngle,
endAngle: itemEndAngle,
clipStartAngle: containerStartAngle,
clipEndAngle: containerEndAngle,
startCornerRadius: cornersOnAllItems || isStart ? cornerRadius : 0,
endCornerRadius: cornersOnAllItems || isEnd ? cornerRadius : 0,
style: barStyle
});
scaleData.push({
series: this,
itemId: `scale-${i}`,
datum,
datumIndex: { type: 0 /* Node */ },
type: 0 /* Node */,
centerX,
centerY,
outerRadius,
innerRadius,
startAngle: itemStartAngle,
endAngle: itemEndAngle,
clipStartAngle: void 0,
clipEndAngle: void 0,
startCornerRadius: cornersOnAllItems || isStart ? cornerRadius : 0,
endCornerRadius: cornersOnAllItems || isEnd ? cornerRadius : 0,
style: scaleStyle
});
}
}
if (!needle.enabled && label.enabled) {
const {
text: text2,
color: fill,
fontSize,
minimumFontSize,
fontStyle,
fontWeight,
fontFamily,
lineHeight,
formatter = (params) => this.formatLabel(params.value)
} = label;
labelData.push({
label: "primary" /* Primary */,
centerX,
centerY,
text: text2,
value,
fill,
fontSize,
minimumFontSize,
fontStyle,
fontWeight,
fontFamily,
lineHeight,
formatter
});
}
if (!needle.enabled && secondaryLabel.enabled) {
const {
text: text2,
color: fill,
fontSize,
minimumFontSize,
fontStyle,
fontWeight,
fontFamily,
lineHeight,
formatter
} = secondaryLabel;
labelData.push({
label: "secondary" /* Secondary */,
centerX,
centerY,
text: text2,
value,
fill,
fontSize,
minimumFontSize,
fontStyle,
fontWeight,
fontFamily,
lineHeight,
formatter
});
}
if (needle.enabled) {
let needleRadius = needle.radiusRatio == null ? innerRadius : radius * needle.radiusRatio;
needleRadius = Math.max(needleRadius - needle.spacing, 0);
const needleAngle = scale.convert(value);
needleData.push({
centerX,
centerY,
radius: needleRadius,
angle: needleAngle,
series: this
});
}
for (let i = 0; i < targets.length; i += 1) {
const target = targets[i];
const { value: targetValue, text: text2, size, shape, style } = target;
if (targetValue < Math.min(...scale.domain) || targetValue > Math.max(...scale.domain)) {
continue;
}
const targetRadius = this.getTargetRadius(target);
const targetAngle = scale.convert(targetValue);
const targetRotation = toRadians5(target.rotation + targetPlacementRotation[target.placement]);
targetData.push({
series: this,
itemId: `target-${i}`,
midPoint: {
x: targetRadius * Math.cos(targetAngle) + centerX,
y: targetRadius * Math.sin(targetAngle) + centerY
},
datum: { value: targetValue },
datumIndex: { type: 1 /* Target */, index: i },
type: 1 /* Target */,
value: targetValue,
text: text2,
centerX,
centerY,
shape,
radius: targetRadius,
angle: targetAngle,
rotation: targetRotation,
size,
label: this.getTargetLabel(target),
style
});
}
return {
itemId: seriesId,
nodeData,
needleData,
targetData,
labelData,
scaleData,
tickData
};
}
findNodeDatum(itemId) {
return findGaugeNodeDatum(this, itemId);
}
updateSelections(resize) {
if (this.nodeDataRefresh || resize) {
this.contextNodeData = this.createNodeData();
this.nodeDataRefresh = false;
}
}
highlightDatum(node) {
if (node?.series === this && node.type === 1 /* Target */) {
return node;
}
}
update({ seriesRect }) {
const {
datumSelection,
labelSelection,
needleSelection,
targetSelection,
targetLabelSelection,
scaleSelection,
highlightTargetSelection,
tickSelection
} = this;
const resize = this.checkResize(seriesRect);
this.updateSelections(resize);
this.contentGroup.visible = this.visible;
this.contentGroup.opacity = this.getOpacity();
const nodeData = this.contextNodeData?.nodeData ?? [];
const labelData = this.contextNodeData?.labelData ?? [];
const needleData = this.contextNodeData?.needleData ?? [];
const targetData = this.contextNodeData?.targetData ?? [];
const scaleData = this.contextNodeData?.scaleData ?? [];
const tickData = this.contextNodeData?.tickData ?? [];
const highlightTargetDatum = this.highlightDatum(this.ctx.highlightManager.getActiveHighlight());
this.scaleSelection = this.updateScaleSelection({ scaleData, scaleSelection });
this.updateScaleNodes({ scaleSelection });
this.needleSelection = this.updateNeedleSelection({ needleData, needleSelection });
this.updateNeedleNodes({ needleSelection });
this.targetSelection = this.updateTargetSelection({ targetData, targetSelection });
this.updateTargetStyles({ targetSelection, isHighlight: false });
this.updateTargetNodes({ targetSelection });
this.targetLabelSelection = this.updateTargetLabelSelection({ targetData, targetLabelSelection });
this.updateTargetLabelNodes({ targetLabelSelection });
this.datumSelection = this.updateDatumSelection({ nodeData, datumSelection });
this.updateDatumNodes({ datumSelection });
this.labelSelection = this.updateLabelSelection({ labelData, labelSelection });
this.updateLabelNodes({ labelSelection });
this.highlightTargetSelection = this.updateTargetSelection({
targetData: highlightTargetDatum == null ? [] : [highlightTargetDatum],
targetSelection: highlightTargetSelection
});
this.updateTargetStyles({ targetSelection: highlightTargetSelection, isHighlight: true });
this.updateTargetNodes({ targetSelection: highlightTargetSelection });
this.tickSelection = this.updateTickSelection({ tickData, tickSelection });
this.updateTickNodes({ tickSelection });
if (resize) {
this.animationState.transition("resize");
}
this.animationState.transition("update");
}
updateDatumSelection(opts) {
return opts.datumSelection.update(opts.nodeData, void 0, (datum) => {
return createDatumId20(opts.nodeData.length, datum.itemId);
});
}
updateDatumNodes(opts) {
const { datumSelection } = opts;
const { ctx, properties } = this;
const { segmentation } = properties;
const sectorSpacing = segmentation.spacing ?? 0;
const animationDisabled = ctx.animationManager.isSkipped();
const fillBBox = this.getShapeFillBBox();
datumSelection.each((sector, datum) => {
const { centerX, centerY, innerRadius, outerRadius, startCornerRadius, endCornerRadius } = datum;
sector.centerX = centerX;
sector.centerY = centerY;
sector.innerRadius = innerRadius;
sector.outerRadius = outerRadius;
sector.pointerEvents = this.properties.bar.enabled ? _ModuleSupport202.PointerEvents.All : _ModuleSupport202.PointerEvents.None;
sector.setStyleProperties(datum.style, fillBBox);
sector.startOuterCornerRadius = startCornerRadius;
sector.startInnerCornerRadius = startCornerRadius;
sector.endOuterCornerRadius = endCornerRadius;
sector.endInnerCornerRadius = endCornerRadius;
sector.radialEdgeInset = (sectorSpacing + sector.strokeWidth) / 2;
sector.concentricEdgeInset = sector.strokeWidth / 2;
datum.midPoint = sector.getBBox().computeCenter();
if (animationDisabled || sector.previousDatum == null) {
sector.setProperties(resetRadialGaugeSeriesResetSectorFunction(sector, datum));
}
});
this.datumUnion.update(datumSelection, this.itemGroup, _ModuleSupport202.Sector, (node, first, last) => {
node.clipSector ?? (node.clipSector = new SectorBox6(Number.NaN, Number.NaN, Number.NaN, Number.NaN));
node.centerX = first.centerX;
node.centerY = first.centerY;
node.outerRadius = node.clipSector.outerRadius = first.outerRadius;
node.innerRadius = node.clipSector.innerRadius = first.innerRadius;
node.startAngle = node.clipSector.startAngle = first.startAngle;
node.startInnerCornerRadius = first.startInnerCornerRadius;
node.startOuterCornerRadius = first.startOuterCornerRadius;
node.endAngle = last.endAngle;
node.clipSector.endAngle = last.clipSector?.endAngle ?? last.endAngle;
node.endInnerCornerRadius = last.endInnerCornerRadius;
node.endOuterCornerRadius = last.endOuterCornerRadius;
node.pointerEvents = _ModuleSupport202.PointerEvents.None;
});
}
updateScaleSelection(opts) {
return opts.scaleSelection.update(opts.scaleData, void 0, (datum) => {
return createDatumId20(opts.scaleData.length, datum.itemId);
});
}
updateScaleNodes(opts) {
const { scaleSelection } = opts;
const { segmentation } = this.properties;
const sectorSpacing = segmentation.spacing ?? 0;
const fillBBox = this.getShapeFillBBox();
scaleSelection.each((sector, datum) => {
const { centerX, centerY, innerRadius, outerRadius, startCornerRadius, endCornerRadius } = datum;
sector.centerX = centerX;
sector.centerY = centerY;
sector.innerRadius = innerRadius;
sector.outerRadius = outerRadius;
sector.setStyleProperties(datum.style, fillBBox);
sector.startOuterCornerRadius = startCornerRadius;
sector.startInnerCornerRadius = startCornerRadius;
sector.endOuterCornerRadius = endCornerRadius;
sector.endInnerCornerRadius = endCornerRadius;
sector.radialEdgeInset = (sectorSpacing + sector.strokeWidth) / 2;
sector.concentricEdgeInset = sector.strokeWidth / 2;
sector.setProperties(resetRadialGaugeSeriesResetSectorFunction(sector, datum));
});
}
updateNeedleSelection(opts) {
return opts.needleSelection.update(opts.needleData, void 0, () => createDatumId20(0));
}
updateNeedleNodes(opts) {
const { needleSelection } = opts;
const { fill, fillOpacity, stroke: stroke3, strokeOpacity, strokeWidth, lineDash, lineDashOffset } = this.properties.needle;
const animationDisabled = this.ctx.animationManager.isSkipped();
needleSelection.each((needle, datum) => {
const { centerX, centerY, radius } = datum;
const scale = radius * 2;
needle.d = RadialGaugeNeedle.defaultPathData;
needle.setStyleProperties({
fill,
fillOpacity,
stroke: stroke3,
strokeOpacity,
strokeWidth: strokeWidth / scale,
lineDash: lineDash.map((d) => d / scale),
lineDashOffset: lineDashOffset / scale
});
needle.translationX = centerX;
needle.translationY = centerY;
needle.scalingX = scale;
needle.scalingY = scale;
if (animationDisabled) {
needle.setProperties(resetRadialGaugeSeriesResetNeedleFunction(needle, datum));
}
});
}
updateTargetSelection(opts) {
return opts.targetSelection.update(opts.targetData, void 0, (target) => target.itemId);
}
updateTargetStyles({
targetSelection,
isHighlight
}) {
targetSelection.each((_, datum) => {
datum.style = this.getTargetStyle(isHighlight, datum);
});
}
updateTargetNodes({
targetSelection
}) {
targetSelection.each((target, datum) => {
const { centerX, centerY, angle, radius, shape, size, rotation } = datum;
target.setStyleProperties(datum.style);
target.size = size;
target.shape = shape === "line" ? lineMarker : shape;
target.translationX = centerX + radius * Math.cos(angle);
target.translationY = centerY + radius * Math.sin(angle);
target.rotation = angle + rotation;
});
}
getTargetStyle(isHighlight, { datumIndex, style }) {
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
return mergeDefaults21(highlightStyle, {
...style,
opacity: 1
});
}
updateTargetLabelSelection(opts) {
return opts.targetLabelSelection.update(opts.targetData, void 0, (target) => target.itemId);
}
updateTargetLabelNodes(opts) {
const { targetLabelSelection } = opts;
targetLabelSelection.each((label, target) => {
const { centerX, centerY, radius, angle, text: text2 } = target;
const { offsetX, offsetY, fill, fontStyle, fontWeight, fontSize, fontFamily, textAlign, textBaseline } = target.label;
if (text2 == null) {
label.visible = false;
return;
}
label.visible = true;
label.x = centerX + radius * Math.cos(angle) + offsetX;
label.y = centerY + radius * Math.sin(angle) + offsetY;
label.text = text2;
label.fill = fill;
label.fontStyle = fontStyle;
label.fontWeight = fontWeight;
label.fontSize = fontSize;
label.fontFamily = fontFamily;
label.textAlign = textAlign;
label.textBaseline = textBaseline;
});
}
updateLabelSelection(opts) {
return opts.labelSelection.update(opts.labelData, void 0, (datum) => datum.label);
}
updateLabelNodes(opts) {
const { labelSelection } = opts;
const animationDisabled = this.ctx.animationManager.isSkipped();
labelSelection.each((label, datum) => {
label.fill = datum.fill;
label.fontStyle = datum.fontStyle;
label.fontWeight = datum.fontWeight;
label.fontFamily = datum.fontFamily;
});
if (animationDisabled || this.labelsHaveExplicitText()) {
this.formatLabelText();
}
}
updateTickSelection(opts) {
return opts.tickSelection.update(opts.tickData, void 0, (datum) => datum.index);
}
updateTickNodes(opts) {
const { scale, radius, centerX, centerY, properties } = this;
const { enabled, color: color7, fontFamily, fontSize, fontStyle, fontWeight, spacing } = properties.scale.label;
const rotation = toRadians5(properties.scale.label.rotation ?? 0);
opts.tickSelection.each((label, datum) => {
if (!enabled) {
label.visible = false;
return;
}
label.visible = true;
label.text = datum.text;
label.fill = color7;
label.fontFamily = fontFamily;
label.fontSize = fontSize;
label.fontStyle = fontStyle;
label.fontWeight = fontWeight;
const angle = scale.convert(datum.value);
const { textAlign, textBaseline } = this.getTickLabelAlign(angle);
const x0 = centerX + (radius + spacing) * Math.cos(angle);
const y0 = centerY + (radius + spacing) * Math.sin(angle);
label.textAlign = textAlign;
label.textBaseline = textBaseline;
label.x = x0;
label.y = y0;
label.rotationCenterX = x0;
label.rotationCenterY = y0;
label.rotation = rotation;
});
}
getTickLabelAlign(tickAngle) {
const cos = Math.cos(tickAngle);
const sin = Math.sin(tickAngle);
let textAlign;
let textBaseline;
const isCos0 = isNumberEqual10(cos, 0);
const isSin0 = isNumberEqual10(sin, 0);
const isCosPositive = cos > 0 && !isCos0;
const isSinPositive = sin > 0 && !isSin0;
textAlign = "right";
if (isCos0) {
textAlign = "center";
} else if (isCosPositive) {
textAlign = "left";
}
textBaseline = "bottom";
if (isSin0) {
textBaseline = "middle";
} else if (isSinPositive) {
textBaseline = "top";
}
return { textAlign, textBaseline };
}
getTickLabelInset(params) {
const { tickData, radius, centerXOffset, centerYOffset, seriesRectWidth, seriesRectHeight, spacing, rotation } = params;
const { label } = this.properties.scale;
const centerX = seriesRectWidth / 2 + centerXOffset * radius;
const centerY = seriesRectHeight / 2 + centerYOffset * radius;
const tempText = new TransformableText3();
tempText.fontFamily = label.fontFamily;
tempText.fontSize = label.fontSize;
tempText.fontStyle = label.fontStyle;
tempText.fontWeight = label.fontWeight;
tempText.rotation = rotation;
const minComponent = 1e-6;
let inset = 0;
for (const datum of tickData) {
const angle = this.scale.convert(datum.value);
const cos = Math.cos(angle);
const sin = Math.sin(angle);
const x = centerX + (radius + spacing) * cos;
const y = centerY + (radius + spacing) * sin;
const { textAlign, textBaseline } = this.getTickLabelAlign(angle);
tempText.text = datum.text;
tempText.x = x;
tempText.y = y;
tempText.textAlign = textAlign;
tempText.textBaseline = textBaseline;
tempText.rotationCenterX = x;
tempText.rotationCenterY = y;
const box = rotation ? Transformable4.toCanvas(tempText) : tempText.getBBox();
if (box == null)
continue;
const minX = box.x;
const maxX = box.x + box.width;
const minY = box.y;
const maxY = box.y + box.height;
const overflowLeft = Math.max(0, -minX);
const overflowRight = Math.max(0, maxX - seriesRectWidth);
const overflowTop = Math.max(0, -minY);
const overflowBottom = Math.max(0, maxY - seriesRectHeight);
const dxPerRadius = centerXOffset + cos;
if (Math.abs(dxPerRadius) > minComponent) {
if (overflowRight > 0 && dxPerRadius > 0) {
inset = Math.max(inset, overflowRight / dxPerRadius);
} else if (overflowLeft > 0 && dxPerRadius < 0) {
inset = Math.max(inset, overflowLeft / -dxPerRadius);
}
}
const dyPerRadius = centerYOffset + sin;
if (Math.abs(dyPerRadius) > minComponent) {
if (overflowBottom > 0 && dyPerRadius > 0) {
inset = Math.max(inset, overflowBottom / dyPerRadius);
} else if (overflowTop > 0 && dyPerRadius < 0) {
inset = Math.max(inset, overflowTop / -dyPerRadius);
}
}
}
return inset;
}
labelsHaveExplicitText() {
for (const { datum } of this.labelSelection) {
if (datum.text == null) {
return false;
}
}
return true;
}
formatLabelText(datum) {
const { labelSelection, radius, textAlign, verticalAlign } = this;
const { spacing: padding2, innerRadiusRatio } = this.properties;
formatRadialGaugeLabels(
this,
this.ctx,
labelSelection,
{ padding: padding2, textAlign, verticalAlign },
radius * innerRadiusRatio,
datum
);
}
resetAllAnimation() {
this.ctx.animationManager.stopByAnimationGroupId(this.id);
resetMotion4([this.datumSelection], resetRadialGaugeSeriesResetSectorFunction);
resetMotion4([this.needleSelection], resetRadialGaugeSeriesResetNeedleFunction);
this.formatLabelText();
}
resetAnimation(phase) {
if (phase === "initial") {
this.animationState.transition("reset");
} else if (phase === "ready") {
this.animationState.transition("skip");
}
}
animateLabelText(params = {}) {
const { animationManager } = this.ctx;
let labelFrom;
let labelTo;
let secondaryLabelFrom;
let secondaryLabelTo;
this.labelSelection.each((label, datum) => {
label.opacity = 1;
if (datum.label === "primary" /* Primary */) {
labelFrom = label.previousDatum?.value ?? params.from ?? datum.value;
labelTo = datum.value;
} else if (datum.label === "secondary" /* Secondary */) {
secondaryLabelFrom = label.previousDatum?.value ?? params.from ?? datum.value;
secondaryLabelTo = datum.value;
}
});
if (this.labelsHaveExplicitText()) {
} else if (labelTo == null || secondaryLabelTo == null) {
this.formatLabelText();
} else if (labelFrom === labelTo && secondaryLabelFrom === secondaryLabelTo) {
this.formatLabelText({ label: labelTo, secondaryLabel: secondaryLabelTo });
} else {
const animationId = `${this.id}_labels`;
animationManager.animate({
id: animationId,
groupId: "label",
from: { label: labelFrom, secondaryLabel: secondaryLabelFrom },
to: { label: labelTo, secondaryLabel: secondaryLabelTo },
phase: params.phase ?? "update",
onUpdate: (datum) => this.formatLabelText(datum),
onStop: () => this.formatLabelText({ label: labelTo, secondaryLabel: secondaryLabelTo })
});
}
}
animateEmptyUpdateReady() {
const { animationManager } = this.ctx;
const { node, needle } = prepareRadialGaugeSeriesAnimationFunctions(true, this.scale.range[0]);
fromToMotion5(this.id, "node", animationManager, [this.datumSelection], node, (_sector, datum) => datum.itemId);
fromToMotion5(this.id, "needle", animationManager, [this.needleSelection], needle, () => "needle");
fromToMotion5(
this.id,
"label",
animationManager,
[this.labelSelection],
fadeInFns,
(_label, datum) => datum.label
);
this.animateLabelText({
from: this.properties.scale.min,
phase: "initial"
});
}
animateWaitingUpdateReady() {
const { animationManager } = this.ctx;
const { node, needle } = prepareRadialGaugeSeriesAnimationFunctions(false, this.scale.range[0]);
fromToMotion5(this.id, "node", animationManager, [this.datumSelection], node, (_sector, datum) => datum.itemId);
fromToMotion5(this.id, "needle", animationManager, [this.needleSelection], needle, () => "needle");
this.animateLabelText();
}
animateReadyResize() {
this.resetAllAnimation();
}
dataCount() {
return Number.NaN;
}
getSeriesDomain() {
return { domain: [Number.NaN, Number.NaN] };
}
getSeriesRange() {
return [Number.NaN, Number.NaN];
}
getLegendData() {
return [];
}
getTooltipContent(datumIndex) {
const { id: seriesId, properties } = this;
const { tooltip } = properties;
let value;
let text2;
let fallbackLabel;
if (datumIndex.type === 0 /* Node */) {
value = properties.value;
text2 = properties.label.text;
fallbackLabel = this.ctx.localeManager.t("ariaLabelGaugeValue");
} else {
({ value, text: text2 } = properties.targets[datumIndex.index]);
fallbackLabel = this.ctx.localeManager.t("ariaLabelGaugeTarget");
}
if (value == null)
return;
return this.formatTooltipWithContext(
tooltip,
{
data: [{ label: text2, fallbackLabel, value: this.formatLabel(value) }]
},
{ seriesId, title: void 0, datum: void 0, value }
);
}
pickNodeClosestDatum(point) {
return pickGaugeNearestDatum(this, point);
}
pickFocus(opts) {
return pickGaugeFocus(this, opts);
}
getCaptionText() {
const { value } = this.properties;
const description = [];
description.push(this.formatLabel(value));
this.labelSelection.each((_label, datum) => {
const text2 = getLabelText(this.id, this.ctx, datum);
if (text2 != null) {
description.push(toPlainText10(text2));
}
});
return description.join(". ");
}
getCategoryValue(_datumIndex) {
return;
}
datumIndexForCategoryValue(_categoryValue) {
return;
}
hasItemStylers() {
return this.properties.label.itemStyler != null;
}
};
RadialGaugeSeries.className = "RadialGaugeSeries";
RadialGaugeSeries.type = "radial-gauge";
// packages/ag-charts-enterprise/src/series/radial-gauge/radialGaugeModule.ts
var RadialGaugeModule = {
type: "series",
name: "radial-gauge",
chartType: "standalone",
enterprise: true,
dependencies: [GaugePresetModule],
version: VERSION47,
options: radialGaugeSeriesOptionsDef2,
themeTemplate: {
minWidth: 200,
minHeight: 200,
tooltip: {
enabled: false
},
series: {
outerRadiusRatio: 1,
innerRadiusRatio: 0.8,
startAngle: 270,
endAngle: 270 + 180,
defaultColorRange: {
$if: [
{ $eq: [{ $palette: "type" }, "inbuilt"] },
{ $interpolate: [{ $palette: "secondDivergingColors" }, 5] },
SAFE_RANGE2_OPERATION7
]
},
scale: {
defaultFill: { $path: ["/1", { $palette: "fill" }, { $palette: "hierarchyColors" }] },
// TODO: mix backgroundColor and foregroundColor?
stroke: { $path: ["/2", SAFE_STROKE_FILL_OPERATION4, { $palette: "hierarchyColors" }] },
// TODO: mix backgroundColor and foregroundColor?
strokeWidth: { $isUserOption: ["./stroke", 2, 0] },
label: {
fontWeight: { $ref: "fontWeight" },
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
color: { $ref: "textColor" },
spacing: 12
}
},
bar: {
strokeWidth: { $isUserOption: ["./stroke", 2, 0] }
},
segmentation: {
enabled: false,
interval: {},
spacing: 2
},
defaultTarget: {
fill: { $ref: "foregroundColor" },
stroke: { $ref: "foregroundColor" },
size: 10,
shape: "triangle",
placement: "outside",
spacing: 5,
label: {
enabled: true,
fontWeight: { $ref: "fontWeight" },
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
color: { $ref: "textColor" },
spacing: 5
}
},
needle: {
enabled: false,
fill: { $ref: "foregroundColor" },
spacing: 10
},
label: {
...LABEL_BOXING_DEFAULTS17,
enabled: true,
fontWeight: { $ref: "fontWeight" },
fontSize: 56,
minimumFontSize: 18 / 56,
fontFamily: { $ref: "fontFamily" },
color: { $ref: "textColor" }
},
secondaryLabel: {
...LABEL_BOXING_DEFAULTS17,
enabled: true,
fontWeight: { $ref: "fontWeight" },
fontSize: { $rem: FONT_SIZE_RATIO3.LARGE },
minimumFontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
color: { $ref: "subtleTextColor" }
},
tooltip: {
range: { $path: ["/tooltip/range", 10] }
}
}
},
create: (ctx) => new RadialGaugeSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/sankey/sankeyModule.ts
import { VERSION as VERSION48 } from "ag-charts-community";
import {
FILL_GRADIENT_LINEAR_DEFAULTS as FILL_GRADIENT_LINEAR_DEFAULTS8,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS17,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS12,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS18,
SAFE_FILLS_OPERATION
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/sankey/sankeySeries.ts
import {
_ModuleSupport as _ModuleSupport205
} from "ag-charts-community";
import {
Logger as Logger22,
cachedTextMeasurer as cachedTextMeasurer12,
calcLineHeight as calcLineHeight7,
mergeDefaults as mergeDefaults22,
toPlainText as toPlainText11,
wrapText as wrapText4
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/sankey/sankeyLink.ts
import { _ModuleSupport as _ModuleSupport203 } from "ag-charts-community";
import { SceneChangeDetection as SceneChangeDetection9, Vec2 as Vec220, clamp as clamp13 } from "ag-charts-core";
var { BBox: BBox26, Path: Path14 } = _ModuleSupport203;
var SankeyLink = class extends Path14 {
constructor() {
super(...arguments);
this.x1 = 0;
this.x2 = 0;
this.y1 = 0;
this.y2 = 0;
this.height = 0;
this.inset = 0;
this.elbows = [];
}
computeBBox() {
const x = Math.min(this.x1, this.x2);
const width = Math.max(this.x1, this.x2) - x;
const y = Math.min(this.y1, this.y2);
const height = Math.max(this.y1, this.y2) - y + this.height;
return new BBox26(x, y, width, height);
}
updatePath() {
const { path, inset } = this;
path.clear();
const height = this.height - 2 * this.inset;
const offset = height / 2;
let x1 = this.x1 + inset;
let y1 = this.y1 + inset;
path.moveTo(x1, y1);
for (const elbow of this.elbows) {
this.updatePathSection(x1, y1, elbow.x, elbow.y, height, -offset);
x1 = elbow.x;
y1 = elbow.y;
}
const x2 = this.x2 - inset;
const y2 = this.y2 + inset;
this.updatePathSection(x1, y1, x2, y2, height, -offset);
path.lineTo(x2, y2 + height);
x1 = x2;
y1 = y2;
for (const elbow of this.elbows.toReversed()) {
this.updatePathSection(x1, y1, elbow.x, elbow.y, height, offset);
x1 = elbow.x;
y1 = elbow.y;
}
this.updatePathSection(x1, y1, this.x1 + inset, this.y1 + inset, height, offset);
path.closePath();
}
updatePathSection(x1, y1, x2, y2, height, yOffset) {
const { path } = this;
const start = Vec220.from(x1, y1 + yOffset + height / 2);
const end = Vec220.from(x2, y2 + yOffset + height / 2);
if (Math.abs(end.y - start.y) < 2) {
path.lineTo(end.x, end.y);
return;
}
let angle = Vec220.angle(Vec220.sub(end, start));
if (angle < 0)
angle = 2 * Math.PI + angle;
const right = 0;
const down = Math.PI / 2;
const left = Math.PI;
const up = Math.PI * 1.5;
const innerArc = getArcValues(start, end, 0);
const outerArc = getArcValues(start, end, height);
if (innerArc.radius < height) {
path.cubicCurveTo((start.x + end.x) / 2, start.y, (start.x + end.x) / 2, end.y, end.x, end.y);
return;
}
if (angle >= up) {
path.arc(start.x, y1 - innerArc.radius, innerArc.radius, down, down + outerArc.angle, true);
path.arc(end.x, y2 + outerArc.radius, outerArc.radius, up + outerArc.angle, up);
path.lineTo(end.x, end.y);
} else if (angle > right && angle <= down) {
path.arc(start.x, y1 + outerArc.radius, outerArc.radius, up, up + outerArc.angle);
path.arc(end.x, y2 - innerArc.radius, innerArc.radius, down + innerArc.angle, down, true);
path.lineTo(end.x, end.y);
} else if (angle > down && angle <= left) {
path.arc(start.x, y1 + outerArc.radius, outerArc.radius - height, up, up + outerArc.angle, true);
path.arc(end.x, y2 - innerArc.radius, innerArc.radius + height, down + innerArc.angle, down);
path.lineTo(end.x, end.y);
} else {
path.arc(start.x, y1 - innerArc.radius, innerArc.radius + height, down, down + innerArc.angle);
path.arc(end.x, y2 + outerArc.radius, outerArc.radius - height, up + outerArc.angle, up, true);
path.lineTo(end.x, end.y);
}
}
};
__decorateClass([
SceneChangeDetection9()
], SankeyLink.prototype, "x1", 2);
__decorateClass([
SceneChangeDetection9()
], SankeyLink.prototype, "x2", 2);
__decorateClass([
SceneChangeDetection9()
], SankeyLink.prototype, "y1", 2);
__decorateClass([
SceneChangeDetection9()
], SankeyLink.prototype, "y2", 2);
__decorateClass([
SceneChangeDetection9()
], SankeyLink.prototype, "height", 2);
__decorateClass([
SceneChangeDetection9()
], SankeyLink.prototype, "inset", 2);
function getArcValues(start, end, minRadius) {
const lineAngle = Vec220.angle(Vec220.sub(end, start));
const chordLength = Vec220.distance(start, end);
const bisect = Vec220.add(start, Vec220.rotate(Vec220.from(chordLength / 2, 0), lineAngle));
const gradient = -1 / Vec220.gradient(start, end);
const intercept = Vec220.intercept(bisect, gradient);
const offset = lerpClamp(0.1, 0.5, Math.PI / 2 - Math.abs(Vec220.gradient(start, end)));
const center = Vec220.intersectAtX(gradient, intercept, start.x);
const radius = Math.max(minRadius, Vec220.distance(start, center) * offset);
const angle = Vec220.angle(Vec220.sub(center, start), Vec220.sub(center, bisect)) / -(1.1 - offset);
return { angle, radius };
}
function lerpClamp(a, b, ratio8) {
return clamp13(a, (b - a) * ratio8 + a, b);
}
// packages/ag-charts-enterprise/src/series/sankey/sankeySeriesProperties.ts
import {
_ModuleSupport as _ModuleSupport204
} from "ag-charts-community";
import { BaseProperties as BaseProperties35, Property as Property87 } from "ag-charts-core";
var { FillGradientDefaults: FillGradientDefaults3, FillPatternDefaults: FillPatternDefaults3, FillImageDefaults: FillImageDefaults3, makeSeriesTooltip: makeSeriesTooltip22, SeriesProperties: SeriesProperties13, Label: Label17 } = _ModuleSupport204;
var SankeySeriesLabelProperties = class extends Label17 {
constructor() {
super(...arguments);
this.spacing = 1;
this.placement = void 0;
this.edgePlacement = void 0;
}
};
__decorateClass([
Property87
], SankeySeriesLabelProperties.prototype, "spacing", 2);
__decorateClass([
Property87
], SankeySeriesLabelProperties.prototype, "placement", 2);
__decorateClass([
Property87
], SankeySeriesLabelProperties.prototype, "edgePlacement", 2);
var SankeySeriesLinkProperties = class extends BaseProperties35 {
constructor() {
super(...arguments);
this.fill = void 0;
this.fillOpacity = 1;
this.stroke = void 0;
this.strokeOpacity = 1;
this.strokeWidth = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
}
};
__decorateClass([
Property87
], SankeySeriesLinkProperties.prototype, "fill", 2);
__decorateClass([
Property87
], SankeySeriesLinkProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property87
], SankeySeriesLinkProperties.prototype, "stroke", 2);
__decorateClass([
Property87
], SankeySeriesLinkProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property87
], SankeySeriesLinkProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property87
], SankeySeriesLinkProperties.prototype, "lineDash", 2);
__decorateClass([
Property87
], SankeySeriesLinkProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property87
], SankeySeriesLinkProperties.prototype, "itemStyler", 2);
var SankeySeriesNodeProperties = class extends BaseProperties35 {
constructor() {
super(...arguments);
this.spacing = 1;
this.minSpacing = 0;
this.width = 1;
this.alignment = "justify";
this.verticalAlignment = "center";
this.sort = "auto";
this.fill = void 0;
this.fillOpacity = 1;
this.stroke = void 0;
this.strokeOpacity = 1;
this.strokeWidth = 1;
this.lineDash = [0];
this.lineDashOffset = 0;
}
};
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "spacing", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "minSpacing", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "width", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "alignment", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "verticalAlignment", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "sort", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "fill", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "stroke", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "lineDash", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "lineDashOffset", 2);
__decorateClass([
Property87
], SankeySeriesNodeProperties.prototype, "itemStyler", 2);
var SankeySeriesProperties = class extends SeriesProperties13 {
constructor() {
super(...arguments);
this.nodes = void 0;
this.idKey = "";
this.idName = void 0;
this.labelKey = void 0;
this.labelName = void 0;
this.sizeKey = void 0;
this.sizeName = void 0;
this.fillGradientDefaults = new FillGradientDefaults3();
this.fillPatternDefaults = new FillPatternDefaults3();
this.fillImageDefaults = new FillImageDefaults3();
this.defaultColorRange = [];
this.defaultPatternFills = [];
this.fills = [];
this.strokes = [];
this.label = new SankeySeriesLabelProperties();
this.link = new SankeySeriesLinkProperties();
this.node = new SankeySeriesNodeProperties();
this.tooltip = makeSeriesTooltip22();
}
getStyle(isLink, fills, strokes, index) {
const {
fillOpacity,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset,
fill = fills[index % fills.length],
stroke: stroke3 = strokes[index % fills.length]
} = isLink ? this.link : this.node;
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
lineDash,
lineDashOffset
};
}
};
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "nodes", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "fromKey", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "toKey", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "idKey", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "idName", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "labelKey", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "labelName", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "sizeKey", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "sizeName", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "fillGradientDefaults", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "fillPatternDefaults", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "fillImageDefaults", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "defaultColorRange", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "defaultPatternFills", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "fills", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "strokes", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "label", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "link", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "node", 2);
__decorateClass([
Property87
], SankeySeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/sankey/sankeySeries.ts
var { Transformable: Transformable5, SeriesNodePickMode: SeriesNodePickMode16, createDatumId: createDatumId21, getShapeStyle: getShapeStyle2, getLabelStyles: getLabelStyles6, Rect: Rect9, BBox: BBox27 } = _ModuleSupport205;
var SankeySeries = class extends FlowProportionSeries {
constructor(moduleCtx) {
super({
moduleCtx,
pickModes: [SeriesNodePickMode16.NEAREST_NODE, SeriesNodePickMode16.EXACT_SHAPE_MATCH]
});
this.properties = new SankeySeriesProperties();
}
isLabelEnabled() {
return (this.properties.labelKey != null || this.nodes == null) && this.properties.label.enabled;
}
linkFactory() {
return new SankeyLink();
}
nodeFactory() {
return new Rect9();
}
createNodeData() {
const seriesRectWidth = this._nodeDataDependencies?.seriesRectWidth ?? 0;
const nodeWidth = this.properties.node.width;
const {
nodeGraph: baseNodeGraph,
links,
maxPathLength
} = this.getNodeGraph(this.createNode.bind(this, nodeWidth), this.createLink, {
includeCircularReferences: false
});
const nodeGraph = baseNodeGraph;
if (nodeGraph.size === 0)
return;
const columns = this.initialiseColumns(maxPathLength);
this.assignNodesToColumns(nodeGraph, columns, maxPathLength);
const measurer3 = cachedTextMeasurer12(this.properties.label);
const { columnLabelInsetBefore, columnLabelInsetAfter } = this.getColumnLabelInsets(
columns,
measurer3,
maxPathLength
);
const columnWidth = (seriesRectWidth - nodeWidth - columnLabelInsetBefore - columnLabelInsetAfter) / (maxPathLength - 1);
this.positionNodesInColumnsX(columns, columnWidth, columnLabelInsetBefore);
this.createGhostNodesAndColumnDiffs(nodeGraph, columns);
this.weightNodes(columns);
const minSize = 1;
const { sizeScale, nodeSpacing } = this.getScaleAndSpacing(columns, minSize);
if (sizeScale < 0) {
Logger22.warnOnce(
"There was insufficient space to display the Sankey Series. Reduce [node.spacing], [node.minSpacing], or provide a larger container."
);
return;
}
this.positionNodesInColumnsY(columns, minSize, sizeScale, nodeSpacing);
this.sortAndPositionLinks(nodeGraph, sizeScale);
const nodeData = [];
const labelData = [];
this.createNodesNodeData(nodeData, nodeGraph, columns, columnWidth, measurer3, labelData);
this.createLinksNodeData(nodeData, links, minSize, sizeScale);
return {
itemId: this.id,
nodeData,
labelData
};
}
createNode(nodeWidth, node) {
return {
...node,
x: Number.NaN,
y: Number.NaN,
width: nodeWidth,
height: Number.NaN
};
}
createLink(link) {
return {
...link,
x1: Number.NaN,
x2: Number.NaN,
y1: Number.NaN,
y2: Number.NaN,
height: Number.NaN,
elbows: []
};
}
initialiseColumns(maxPathLength) {
const columns = [];
for (let index = 0; index < maxPathLength; index += 1) {
columns.push({ index, size: 0, nodes: [], x: 0 });
}
return columns;
}
assignNodesToColumns(nodeGraph, columns, maxPathLength) {
const { fromKey, toKey, sizeKey, labelKey } = this.properties;
for (const graphNode of nodeGraph.values()) {
const { datum: node, linksBefore, linksAfter } = graphNode;
const size = Math.max(
linksBefore.reduce((acc, { link }) => acc + link.size, 0),
linksAfter.reduce((acc, { link }) => acc + link.size, 0)
);
if (linksBefore.length === 0 && linksAfter.length === 0 || size === 0) {
graphNode.columnIndex = -1;
continue;
}
const column = this.getNodeColumn(columns, graphNode, maxPathLength);
node.size = size;
const { label } = this.properties;
const labelText = label.enabled ? this.getLabelText(
node.label,
node.datum,
labelKey,
"label",
[],
this.properties.label,
{ datum: node.datum, value: node.label, fromKey, toKey, sizeKey, size }
) : void 0;
node.label = toPlainText11(labelText);
column.nodes.push(graphNode);
column.size += size;
graphNode.columnIndex = column.index;
}
}
getNodeColumn(columns, graphNode, maxPathLength) {
const {
node: { alignment }
} = this.properties;
const { linksBefore, linksAfter, maxPathLengthBefore, maxPathLengthAfter } = graphNode;
let column;
switch (alignment) {
case "left":
column = columns[maxPathLengthBefore];
break;
case "right":
column = columns[maxPathLength - 1 - maxPathLengthAfter];
break;
case "center": {
if (linksBefore.length !== 0) {
column = columns[maxPathLengthBefore];
} else if (linksAfter.length === 0) {
column = columns[0];
} else {
const columnIndex = linksAfter.reduce((acc, link) => Math.min(acc, link.node.maxPathLengthBefore), maxPathLength) - 1;
column = columns[columnIndex];
}
break;
}
case "justify": {
column = linksAfter.length === 0 ? columns[maxPathLength - 1] : columns[maxPathLengthBefore];
break;
}
}
return column;
}
getColumnLabelInsets(columns, measurer3, maxPathLength) {
const {
label: { spacing: labelSpacing, placement: labelPlacement, edgePlacement: edgeLabelPlacement },
node: { width: nodeWidth }
} = this.properties;
const seriesRectWidth = this._nodeDataDependencies?.seriesRectWidth ?? 0;
let columnLabelInsetBefore = 0;
let columnLabelInsetAfter = 0;
if (this.isLabelEnabled() && (edgeLabelPlacement === "outside" || edgeLabelPlacement == null)) {
const reduceLabelWidthFn = (acc, n) => {
const node = n;
if (node.datum.label == null || node.datum.label === "")
return acc;
let maxWidth = (seriesRectWidth - nodeWidth) / (maxPathLength - 1) - labelSpacing;
if (labelPlacement === "center" && edgeLabelPlacement == null)
maxWidth /= 2;
const text2 = wrapText4(node.datum.label, {
maxWidth,
maxHeight: node.datum.height,
font: this.properties.label,
textWrap: "never"
});
let { width } = measurer3.measureLines(text2);
if (labelPlacement === "center" && edgeLabelPlacement == null)
width /= 2;
return Math.max(acc, width);
};
if (labelPlacement !== "right" || edgeLabelPlacement === "outside") {
columnLabelInsetBefore = nodeWidth + columns[0].nodes.reduce(reduceLabelWidthFn, 0);
}
if (labelPlacement !== "left" || edgeLabelPlacement === "outside") {
columnLabelInsetAfter = nodeWidth + columns.at(-1).nodes.reduce(reduceLabelWidthFn, 0);
}
}
return { columnLabelInsetBefore, columnLabelInsetAfter };
}
positionNodesInColumnsX(columns, columnWidth, columnLabelInsetBefore) {
for (let index = 0; index < columns.length; index++) {
const column = columns[index];
column.x = columnLabelInsetBefore + index * columnWidth;
for (const graphNode of column.nodes) {
graphNode.datum.x = column.x;
}
}
}
createGhostNodesAndColumnDiffs(nodeGraph, columns) {
for (const graphNode of nodeGraph.values()) {
graphNode.weight = 0;
let closestColumnDiff = Infinity;
for (const link of graphNode.linksAfter) {
const node = link.node;
closestColumnDiff = Math.min(closestColumnDiff, node.columnIndex - graphNode.columnIndex);
}
if (closestColumnDiff === Infinity) {
for (const link of graphNode.linksBefore) {
const node = link.node;
closestColumnDiff = Math.min(closestColumnDiff, graphNode.columnIndex - node.columnIndex);
}
}
graphNode.closestColumnDiff = closestColumnDiff;
this.createNodeGhostNodes(graphNode, columns, closestColumnDiff);
}
}
createNodeGhostNodes(graphNode, columns, closestColumnDiff) {
for (const link of graphNode.linksAfter) {
const node = link.node;
if (node.columnIndex <= graphNode.columnIndex)
continue;
for (let i = node.columnIndex - 1; i > graphNode.columnIndex; i--) {
const size = link.link.size;
const ghostNode = {
ghost: true,
datum: { ...graphNode.datum, size, y: 0, height: 0 },
weight: 0,
linksBefore: [{ node: { columnIndex: i - 1, datum: { size } } }],
linksAfter: [{ node: { columnIndex: i + 1, datum: { size } } }],
link: link.link,
columnIndex: graphNode.columnIndex,
size: graphNode.datum.size,
closestColumnDiff,
fromNode: { y: node.datum.y },
toNode: { y: 0 }
};
columns[i].size += size;
columns[i].nodes.push(ghostNode);
}
}
}
weightNodes(columns) {
const { properties } = this;
if (properties.node.sort === "data")
return;
if (properties.node.sort !== "auto") {
for (const column of columns) {
column.nodes.sort((a, b) => this.sortNodes(a, b));
}
return;
}
const sortedColumns = columns.toSorted((a, b) => {
const aMax = a.nodes.reduce((acc, n) => Math.max(acc, n.datum.size), 0);
const bMax = b.nodes.reduce((acc, n) => Math.max(acc, n.datum.size), 0);
return bMax - aMax;
});
const columnWeights = {};
for (let i = 0; i < sortedColumns.length; i++) {
columnWeights[sortedColumns[i].index] = Math.pow(10, sortedColumns.length - i - 1);
}
for (const column of columns) {
for (const node of column.nodes) {
if ("ghost" in node && node.ghost) {
node.weight = node.size / column.size * columnWeights[column.index];
continue;
}
node.weight = node.datum.size / column.size * columnWeights[column.index];
}
column.nodes.sort((a, b) => a.weight - b.weight);
}
for (const column of columns) {
for (const node of column.nodes) {
if ("ghost" in node && node.ghost) {
continue;
}
node.weight += node.linksBefore.reduce((acc, before) => {
if (before.node.columnIndex !== column.index - 1)
return acc;
const weight = columns[before.node.columnIndex].nodes.indexOf(before.node) * columnWeights[before.node.columnIndex];
return Math.max(acc, weight);
}, 0);
node.weight += node.linksAfter.reduce((acc, after) => {
if (after.node.columnIndex !== column.index + 1)
return acc;
const weight = columns[after.node.columnIndex].nodes.indexOf(after.node) * columnWeights[after.node.columnIndex];
return Math.max(acc, weight);
}, 0);
}
column.nodes.sort((a, b) => this.sortNodes(a, b));
}
}
getScaleAndSpacing(columns, minSize) {
const seriesRectHeight = this._nodeDataDependencies?.seriesRectHeight ?? 0;
const getSizeScale = (spacing) => {
return columns.reduce((acc, { size, nodes }) => {
const spacingAccomodation = seriesRectHeight - nodes.length * minSize;
const spacingOccupation = (nodes.length - 1) * spacing / spacingAccomodation;
const columnSizeScale = (1 - spacingOccupation) / size;
return Math.min(acc, columnSizeScale);
}, Infinity);
};
let nodeSpacing = this.properties.node.spacing;
let sizeScale = getSizeScale(nodeSpacing);
while (sizeScale < 0 && nodeSpacing > this.properties.node.minSpacing) {
nodeSpacing -= 1;
sizeScale = getSizeScale(nodeSpacing);
}
return { nodeSpacing, sizeScale };
}
positionNodesInColumnsY(columns, minSize, sizeScale, nodeSpacing) {
const seriesRectHeight = this._nodeDataDependencies?.seriesRectHeight ?? 0;
for (const column of columns) {
let columnNodesHeight = 0;
for (const node of column.nodes) {
const height = seriesRectHeight * node.datum.size * sizeScale;
node.datum.height = Math.max(minSize, height);
columnNodesHeight += height;
}
const spacingOccupation = nodeSpacing * (column.nodes.length - 1);
let y = 0;
if (this.properties.node.verticalAlignment === "bottom") {
y = seriesRectHeight - columnNodesHeight - spacingOccupation;
} else if (this.properties.node.verticalAlignment === "center") {
y = (seriesRectHeight - columnNodesHeight - spacingOccupation) / 2;
}
for (const node of column.nodes) {
node.datum.y = y;
y += seriesRectHeight * node.datum.size * sizeScale + nodeSpacing;
if ("ghost" in node && node.ghost) {
node.link.elbows.push({ x: column.x, y: node.datum.y });
}
}
}
}
sortAndPositionLinks(nodeGraph, sizeScale) {
const seriesRectHeight = this._nodeDataDependencies?.seriesRectHeight ?? 0;
for (const { datum, linksBefore, linksAfter } of nodeGraph.values()) {
let y2 = datum.y;
linksBefore.sort(
(a, b) => this.sortNodes(a.node, b.node)
);
for (const { link } of linksBefore) {
link.y2 = y2;
y2 += link.size * seriesRectHeight * sizeScale;
}
let y1 = datum.y;
linksAfter.sort(
(a, b) => this.sortNodes(a.node, b.node, {
invertColumnSort: true
})
);
for (const { link } of linksAfter) {
link.y1 = y1;
y1 += link.size * seriesRectHeight * sizeScale;
}
}
}
createNodesNodeData(nodeData, nodeGraph, columns, columnWidth, measurer3, labelData) {
for (const [index, column] of columns.entries()) {
const leading = index === 0;
const trailing = index === columns.length - 1;
let bottom = -Infinity;
column.nodes.sort((a, b) => a.datum.y - b.datum.y);
for (const n of column.nodes) {
if ("ghost" in n && n.ghost)
continue;
const { datum: node } = n;
node.midPoint = {
x: node.x + node.width / 2,
y: node.y + node.height / 2
};
nodeData.push(node);
bottom = this.createNodeLabelData(
nodeGraph,
columnWidth,
measurer3,
labelData,
node,
leading,
trailing,
bottom
);
}
}
}
createNodeLabelData(nodeGraph, columnWidth, measurer3, labelData, node, leading, trailing, bottom) {
if (node.label == null)
return bottom;
const {
label: { spacing: labelSpacing, edgePlacement: edgeLabelPlacement, fontSize }
} = this.properties;
const seriesRectWidth = this._nodeDataDependencies?.seriesRectWidth ?? 0;
const y = node.y + node.height / 2;
let text2;
if (!leading && !trailing) {
const lineHeight = calcLineHeight7(fontSize);
const y12 = y - lineHeight;
const y2 = y + lineHeight;
let maxX = seriesRectWidth;
for (const { datum } of nodeGraph.values()) {
const intersectsLabel = datum.x > node.x && Math.max(datum.y, y12) <= Math.min(datum.y + datum.height, y2);
if (intersectsLabel) {
maxX = Math.min(maxX, datum.x - labelSpacing);
}
}
const maxWidth = maxX - node.x - 2 * labelSpacing;
text2 = wrapText4(node.label, {
maxWidth,
maxHeight: node.height,
font: this.properties.label,
textWrap: "never",
overflow: "hide"
});
}
if (text2 == null || text2 === "") {
const labelInset = edgeLabelPlacement == null && (leading || trailing) ? labelSpacing : labelSpacing * 2;
text2 = wrapText4(node.label, {
maxWidth: columnWidth - labelInset,
maxHeight: node.height,
font: this.properties.label,
textWrap: "never"
});
}
if (text2 === "")
return bottom;
const { height } = measurer3.measureLines(text2);
const y0 = y - height / 2;
const y1 = y + height / 2;
const { x, textAlign } = this.getNodeLabelPlacement(node, leading, trailing);
if (y0 >= bottom) {
labelData.push({
x,
y,
textAlign,
text: text2,
size: node.size,
nodeDatum: node,
datumIndex: node.datumIndex
});
bottom = y1;
}
return bottom;
}
getNodeLabelPlacement(node, leading, trailing) {
const {
label: { spacing: labelSpacing, placement: labelPlacement, edgePlacement: edgeLabelPlacement }
} = this.properties;
let x = node.x + node.width + labelSpacing;
let textAlign = "left";
let placement = labelPlacement;
if (leading && edgeLabelPlacement == null && labelPlacement == null) {
placement = "left";
}
if (edgeLabelPlacement === "outside") {
if (leading)
placement = "left";
if (trailing)
placement = "right";
} else if (edgeLabelPlacement === "inside") {
if (leading)
placement = "right";
if (trailing)
placement = "left";
}
if (placement === "left") {
x = node.x - labelSpacing;
textAlign = "right";
} else if (placement === "center") {
x = node.x + node.width / 2;
textAlign = "center";
}
return { x, textAlign };
}
createLinksNodeData(nodeData, links, minSize, sizeScale) {
const seriesRectHeight = this._nodeDataDependencies?.seriesRectHeight ?? 0;
const nodeWidth = this.properties.node.width;
for (const link of links) {
const { fromNode, toNode, size } = link;
link.height = Math.max(minSize, seriesRectHeight * size * sizeScale);
link.x1 = fromNode.x + nodeWidth;
link.x2 = toNode.x;
link.midPoint = {
x: (link.x1 + link.x2) / 2,
y: (link.y1 + link.y2) / 2 + link.height / 2
};
nodeData.push(link);
}
}
sortNodes(a, b, opts) {
const { properties } = this;
if (properties.node.sort === "ascending") {
return (a.datum.label ?? "").localeCompare(b.datum.label ?? "");
} else if (properties.node.sort === "descending") {
return (b.datum.label ?? "").localeCompare(a.datum.label ?? "");
} else if (properties.node.sort === "data") {
return 0;
}
if (a.columnIndex < b.columnIndex)
return opts?.invertColumnSort ? 1 : -1;
if (a.columnIndex > b.columnIndex)
return opts?.invertColumnSort ? -1 : 1;
if (a.weight === b.weight) {
return a.datum.size - b.datum.size;
}
if (a.closestColumnDiff < b.closestColumnDiff)
return 1;
if (a.closestColumnDiff > b.closestColumnDiff)
return -1;
return a.weight - b.weight;
}
updateLabelSelection(opts) {
const labels = this.isLabelEnabled() ? opts.labelData : [];
return opts.labelSelection.update(labels);
}
updateLabelNodes(opts) {
const activeHighlightDatum = this.getHighlightedDatum();
opts.labelSelection.each((label, datum) => {
const { x, y, textAlign, text: text2, datumIndex, nodeDatum } = datum;
const params = {
fromKey: this.properties.fromKey,
size: datum.size,
sizeKey: this.properties.sizeKey,
toKey: this.properties.toKey
};
const isHighlight = this.isLabelHighlighted(nodeDatum, activeHighlightDatum);
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
const style = getLabelStyles6(
this,
void 0,
params,
this.properties.label,
isHighlight,
activeHighlightDatum
);
const { color: fill, fontStyle, fontWeight, fontSize, fontFamily } = style;
label.visible = true;
label.x = x;
label.y = y;
label.text = text2;
label.fill = fill;
label.fontStyle = fontStyle;
label.fontWeight = fontWeight;
label.fontSize = fontSize;
label.fontFamily = fontFamily;
label.textAlign = textAlign;
label.textBaseline = "middle";
const opacity = highlightStyle.opacity ?? 1;
label.opacity = opacity;
label.fillOpacity = opacity;
label.setBoxing(style);
});
}
updateNodeSelection(opts) {
return opts.datumSelection.update(opts.nodeData, void 0, (datum) => createDatumId21(datum.type, datum.id));
}
getNodeStyle(nodeDatum, fromNodeDatumIndex, isHighlight) {
const { properties } = this;
const {
fills,
strokes,
defaultColorRange,
defaultPatternFills,
fillGradientDefaults: fillGradientDefaults3,
fillPatternDefaults: fillPatternDefaults3,
fillImageDefaults: fillImageDefaults3
} = properties;
const { itemStyler } = properties.node;
const defaultColorStops = defaultColorRange[fromNodeDatumIndex % defaultColorRange.length].map((color7) => ({
color: color7
}));
const defaultPatternFill = defaultPatternFills[fromNodeDatumIndex % defaultPatternFills.length];
const highlightStyle = this.getHighlightStyle(isHighlight, nodeDatum.datumIndex);
const baseStyle = mergeDefaults22(highlightStyle, properties.getStyle(false, fills, strokes, fromNodeDatumIndex));
const hasNodeFill = properties.node.fill != null;
let style = getShapeStyle2(
baseStyle,
hasNodeFill ? fillGradientDefaults3 : { ...fillGradientDefaults3.toJson(), colorStops: defaultColorStops },
hasNodeFill ? fillPatternDefaults3 : { ...fillPatternDefaults3.toJson(), fill: defaultPatternFill, stroke: defaultPatternFill },
fillImageDefaults3
);
if (itemStyler != null && nodeDatum.datumIndex != null) {
const overrides = this.cachedDatumCallback(
createDatumId21(nodeDatum.datumIndex.index, "node", isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(nodeDatum, isHighlight, style);
return this.callWithContext(itemStyler, params);
}
);
if (overrides) {
style = mergeDefaults22(
overrides,
style,
{ ...fillGradientDefaults3.toJson(), colorStops: defaultColorStops },
{ ...fillPatternDefaults3.toJson(), fill: defaultPatternFill, stroke: defaultPatternFill },
fillImageDefaults3
);
}
}
style.opacity = 1;
return style;
}
makeItemStylerParams({ datum, datumIndex, size = 0, label }, isHighlight, style) {
const { id: seriesId } = this;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightState = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum,
highlightState,
...style,
size,
label,
fill
};
}
updateNodeNodes(opts) {
const { datumSelection, isHighlight } = opts;
const fillBBox = this.getShapeFillBBox();
datumSelection.each((rect, datum) => {
const { datumIndex } = datum;
const style = this.getNodeStyle(datum, datumIndex.index, isHighlight);
rect.x = datum.x;
rect.y = datum.y;
rect.width = Math.max(datum.width, 0);
rect.height = Math.max(datum.height, 0);
rect.setStyleProperties(style, fillBBox);
});
}
getShapeFillBBox() {
const width = this._nodeDataDependencies?.seriesRectWidth ?? 0;
const height = this._nodeDataDependencies?.seriesRectHeight ?? 0;
const bbox = new BBox27(0, 0, width, height);
return { series: bbox, axis: bbox };
}
updateLinkSelection(opts) {
return opts.datumSelection.update(
opts.nodeData,
void 0,
(datum) => createDatumId21(datum.type, datum.index, datum.fromNode.id, datum.toNode.id)
);
}
getLinkStyle({ datumIndex, datum }, fromNodeDatumIndex, isHighlight) {
const { id: seriesId, properties } = this;
const {
fills,
strokes,
defaultColorRange,
defaultPatternFills,
fillGradientDefaults: fillGradientDefaults3,
fillPatternDefaults: fillPatternDefaults3,
fillImageDefaults: fillImageDefaults3
} = properties;
const { itemStyler } = properties.link;
const defaultColorStops = defaultColorRange[fromNodeDatumIndex.index % defaultColorRange.length].map(
(color7) => ({
color: color7
})
);
const defaultPatternFill = defaultPatternFills[fromNodeDatumIndex.index % defaultPatternFills.length];
const highlightStyle = this.getHighlightStyle(isHighlight, datumIndex);
const baseStyle = mergeDefaults22(
highlightStyle,
properties.getStyle(true, fills, strokes, fromNodeDatumIndex.index)
);
const hasLinkFill = properties.link.fill != null;
let style = getShapeStyle2(
baseStyle,
hasLinkFill ? fillGradientDefaults3 : { ...fillGradientDefaults3.toJson(), colorStops: defaultColorStops },
hasLinkFill ? fillPatternDefaults3 : { ...fillPatternDefaults3.toJson(), fill: defaultPatternFill, stroke: defaultPatternFill },
fillImageDefaults3
);
if (itemStyler != null && datumIndex != null) {
const overrides = this.cachedDatumCallback(
createDatumId21(datumIndex.index, "link", isHighlight ? "highlight" : "node"),
() => {
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const highlightState = this.getHighlightStateString(activeHighlight, isHighlight, datumIndex);
return this.callWithContext(itemStyler, {
seriesId,
datum,
highlightState,
...style
});
}
);
if (overrides) {
style = mergeDefaults22(
overrides,
style,
{ ...fillGradientDefaults3.toJson(), colorStops: defaultColorStops },
{ ...fillPatternDefaults3.toJson(), fill: defaultPatternFill, stroke: defaultPatternFill },
fillImageDefaults3
);
}
}
style.opacity = 1;
return style;
}
updateLinkNodes(opts) {
const { datumSelection, isHighlight } = opts;
const fillBBox = this.getShapeFillBBox();
datumSelection.each((link, datum) => {
const fromNodeDatumIndex = datum.fromNode.datumIndex;
const style = this.getLinkStyle(datum, fromNodeDatumIndex, isHighlight);
link.x1 = datum.x1;
link.y1 = datum.y1;
link.x2 = datum.x2;
link.y2 = datum.y2;
link.height = datum.height;
link.elbows = datum.elbows;
link.setStyleProperties(style, fillBBox);
link.inset = link.strokeWidth / 2;
});
}
getTooltipContent(datumIndex) {
const {
id: seriesId,
linksProcessedData,
nodesProcessedData,
properties,
ctx: { formatManager }
} = this;
const { fromKey, toKey, sizeKey, sizeName, tooltip } = properties;
const seriesDatum = this.contextNodeData?.nodeData.find(
(d) => d.datumIndex.type === datumIndex.type && d.datumIndex.index === datumIndex.index
);
if (seriesDatum == null)
return;
const nodeIndex = seriesDatum.type === 0 /* Link */ ? seriesDatum.fromNode.index : seriesDatum.index;
const title = seriesDatum.type === 0 /* Link */ ? `${seriesDatum.fromNode.label} - ${seriesDatum.toNode.label}` : seriesDatum.label;
const datum = datumIndex.type === 0 /* Link */ ? linksProcessedData?.dataSources.get(this.id)?.data[datumIndex.index] : nodesProcessedData?.dataSources.get(this.id)?.data[datumIndex.index];
const size = seriesDatum.size;
let format;
if (seriesDatum.type === 0 /* Link */) {
const fromNodeDatumIndex = seriesDatum.fromNode.datumIndex;
format = this.getLinkStyle({ datumIndex, datum }, fromNodeDatumIndex, false);
} else {
format = this.getNodeStyle({ datumIndex, datum }, datumIndex.index, false);
}
const data = [];
if (sizeKey != null) {
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: size,
datum,
seriesId,
legendItemName: void 0,
key: sizeKey,
source: "tooltip",
property: "size",
domain: [],
boundSeries: this.getFormatterContext("size"),
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: sizeName, fallbackLabel: sizeKey, value: content ?? String(size) });
}
return this.formatTooltipWithContext(
tooltip,
{
title,
symbol: this.legendItemSymbol(seriesDatum.type, nodeIndex, format),
data
},
{
seriesId,
datum,
title,
fromKey,
toKey,
sizeKey,
sizeName,
size,
...format
}
);
}
computeFocusBounds(node) {
if (node instanceof Rect9) {
const { x, y, width, height } = node;
const bbox = new BBox27(x, y, width, height);
return Transformable5.toCanvas(this.contentGroup, bbox);
}
return node;
}
hasItemStylers() {
return this.properties.node.itemStyler != null || this.properties.link.itemStyler != null || this.properties.label.itemStyler != null;
}
};
SankeySeries.className = "SankeySeries";
SankeySeries.type = "sankey";
// packages/ag-charts-enterprise/src/series/sankey/sankeySeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport206 } from "ag-charts-community";
import {
arrayOf as arrayOf4,
color as color5,
commonSeriesOptionsDefs as commonSeriesOptionsDefs21,
constant as constant22,
fillGradientDefaults as fillGradientDefaults2,
fillImageDefaults as fillImageDefaults2,
fillPatternDefaults as fillPatternDefaults2,
required as required22,
string as string22,
undocumented as undocumented17
} from "ag-charts-core";
var { sankeySeriesThemeableOptionsDef } = _ModuleSupport206;
var sankeySeriesOptionsDef = {
...sankeySeriesThemeableOptionsDef,
...commonSeriesOptionsDefs21,
type: required22(constant22("sankey")),
fromKey: required22(string22),
toKey: required22(string22),
sizeKey: string22,
sizeName: string22
};
sankeySeriesOptionsDef.fillGradientDefaults = undocumented17(fillGradientDefaults2);
sankeySeriesOptionsDef.fillPatternDefaults = undocumented17(fillPatternDefaults2);
sankeySeriesOptionsDef.fillImageDefaults = undocumented17(fillImageDefaults2);
sankeySeriesOptionsDef.defaultColorRange = undocumented17(arrayOf4(arrayOf4(color5)));
sankeySeriesOptionsDef.defaultPatternFills = undocumented17(arrayOf4(color5));
// packages/ag-charts-enterprise/src/series/sankey/sankeyModule.ts
var SankeySeriesModule = {
type: "series",
name: "sankey",
chartType: "standalone",
enterprise: true,
solo: true,
version: VERSION48,
dependencies: [StandaloneChartModule],
options: sankeySeriesOptionsDef,
themeTemplate: {
seriesArea: {
padding: {
top: 10,
bottom: 10
}
},
series: {
fills: { $palette: "fills" },
strokes: { $palette: "strokes" },
fillGradientDefaults: FILL_GRADIENT_LINEAR_DEFAULTS8,
fillPatternDefaults: FILL_PATTERN_DEFAULTS12,
fillImageDefaults: FILL_IMAGE_DEFAULTS17,
defaultColorRange: { $palette: "gradients" },
defaultPatternFills: SAFE_FILLS_OPERATION,
highlight: {
unhighlightedItem: {
opacity: 0.5
}
},
label: {
...LABEL_BOXING_DEFAULTS18,
enabled: true,
fontFamily: { $ref: "fontFamily" },
fontSize: { $ref: "fontSize" },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "textColor" },
spacing: 10
},
node: {
spacing: { $if: [{ $greaterThan: [{ $path: "./minSpacing" }, 20] }, { $path: "./minSpacing" }, 20] },
minSpacing: 0,
width: 10,
strokeWidth: { $isUserOption: ["./stroke", 2, 0] }
},
link: {
fillOpacity: 0.5,
strokeWidth: { $isUserOption: ["./stroke", 2, 0] }
}
},
legend: {
enabled: false,
toggleSeries: false
}
},
create: (ctx) => new SankeySeries(ctx)
};
// packages/ag-charts-enterprise/src/series/sunburst/sunburstModule.ts
import { VERSION as VERSION49 } from "ag-charts-community";
import {
BASE_FONT_SIZE,
FILL_GRADIENT_RADIAL_REVERSED_SERIES_DEFAULTS,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS18,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS13,
FONT_SIZE_RATIO as FONT_SIZE_RATIO4,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS19
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/sunburst/sunburstSeries.ts
import {
_ModuleSupport as _ModuleSupport208
} from "ag-charts-community";
import {
formatValue as formatValue2,
isGradientFill as isGradientFill4,
mergeDefaults as mergeDefaults23,
normalizeAngle360 as normalizeAngle3608,
toPlainText as toPlainText12
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/sunburst/sunburstSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport207 } from "ag-charts-community";
import { BaseProperties as BaseProperties36, Property as Property88 } from "ag-charts-core";
var { HierarchySeriesProperties, makeSeriesTooltip: makeSeriesTooltip23, HighlightProperties } = _ModuleSupport207;
var SunburstSeriesHighlightStyle = class extends BaseProperties36 {
};
__decorateClass([
Property88
], SunburstSeriesHighlightStyle.prototype, "fill", 2);
__decorateClass([
Property88
], SunburstSeriesHighlightStyle.prototype, "fillOpacity", 2);
__decorateClass([
Property88
], SunburstSeriesHighlightStyle.prototype, "stroke", 2);
__decorateClass([
Property88
], SunburstSeriesHighlightStyle.prototype, "strokeWidth", 2);
__decorateClass([
Property88
], SunburstSeriesHighlightStyle.prototype, "strokeOpacity", 2);
__decorateClass([
Property88
], SunburstSeriesHighlightStyle.prototype, "opacity", 2);
var SunburstSeriesHighlight = class extends HighlightProperties {
constructor() {
super(...arguments);
this.highlightedBranch = new SunburstSeriesHighlightStyle();
this.unhighlightedBranch = new SunburstSeriesHighlightStyle();
}
};
__decorateClass([
Property88
], SunburstSeriesHighlight.prototype, "highlightedBranch", 2);
__decorateClass([
Property88
], SunburstSeriesHighlight.prototype, "unhighlightedBranch", 2);
var SunburstSeriesProperties = class extends HierarchySeriesProperties {
constructor() {
super(...arguments);
this.fillOpacity = 1;
this.strokeWidth = 0;
this.strokeOpacity = 1;
this.cornerRadius = 0;
this.highlight = new SunburstSeriesHighlight();
this.label = new AutoSizedLabel();
this.secondaryLabel = new AutoSizedSecondaryLabel();
this.tooltip = makeSeriesTooltip23();
}
getStyle(index) {
const { fills, strokes, fillOpacity, strokeWidth, strokeOpacity } = this;
return {
fill: fills[index % fills.length],
fillOpacity,
stroke: strokes[index % strokes.length],
strokeWidth,
strokeOpacity,
opacity: 1
};
}
};
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "sizeName", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "labelKey", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "secondaryLabelKey", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "fillOpacity", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "strokeWidth", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "strokeOpacity", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "cornerRadius", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "sectorSpacing", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "padding", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "highlight", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "label", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "secondaryLabel", 2);
__decorateClass([
Property88
], SunburstSeriesProperties.prototype, "tooltip", 2);
// packages/ag-charts-enterprise/src/series/sunburst/sunburstSeries.ts
var {
fromToMotion: fromToMotion6,
createDatumId: createDatumId22,
PointerEvents: PointerEvents13,
Sector: Sector7,
Group: Group21,
ScalableGroup,
Selection: Selection17,
TransformableText: TransformableText4,
BBox: BBox28,
getLabelStyles: getLabelStyles7,
toHierarchyHighlightString
} = _ModuleSupport208;
var SunburstNode = class extends _ModuleSupport208.HierarchyNode {
constructor() {
super(...arguments);
this.label = void 0;
this.secondaryLabel = void 0;
this.contentHeight = 0;
this.bbox = void 0;
// cspell:ignore bbox
this.startAngle = 0;
this.endAngle = 0;
}
};
function setAngleData(node, startAngle = 0, angleScale = 2 * Math.PI / node.sumSize) {
for (const child of node.children) {
const endAngle = startAngle + child.sumSize * angleScale;
child.startAngle = startAngle;
child.endAngle = endAngle;
setAngleData(child, startAngle, angleScale);
startAngle = endAngle;
}
}
var SunburstSeries = class extends _ModuleSupport208.HierarchySeries {
constructor(moduleCtx) {
super(moduleCtx);
this.NodeClass = SunburstNode;
this.properties = new SunburstSeriesProperties();
this.scalingGroup = this.contentGroup.appendChild(new ScalableGroup());
this.sectorGroup = this.scalingGroup.appendChild(new Group21());
this.highlightSectorGroup = this.scalingGroup.appendChild(new Group21());
this.sectorLabelGroup = this.scalingGroup.appendChild(new Group21());
this.datumSelection = Selection17.select(this.sectorGroup, Sector7);
this.labelSelection = Selection17.select(
this.sectorLabelGroup,
Group21
);
this.highlightSelection = Selection17.select(
this.highlightSectorGroup,
Sector7
);
this.sectorLabelGroup.pointerEvents = PointerEvents13.None;
}
processData() {
super.processData();
setAngleData(this.rootNode);
}
updateSelections() {
const highlightedNode = this.getActiveHighlightNode();
this.highlightSelection.update(
highlightedNode == null ? [] : [highlightedNode],
void 0,
(node) => this.getDatumId(node)
);
if (!this.nodeDataRefresh)
return;
this.nodeDataRefresh = false;
const { chart } = this;
if (chart == null)
return;
const seriesRect = chart.seriesRect;
if (seriesRect == null)
return;
const descendants = Array.from(this.rootNode);
const updateLabelGroup = (group) => {
group.append([
new TransformableText4({ tag: 0 /* Primary */ }),
new TransformableText4({ tag: 1 /* Secondary */ })
]);
};
this.datumSelection.update(descendants, void 0, (node) => this.getDatumId(node));
this.labelSelection.update(descendants, updateLabelGroup, (node) => this.getDatumId(node));
}
getItemStyle(nodeDatum, isHighlight) {
const { properties, colorScale } = this;
const { itemStyler } = properties;
const rootIndex = nodeDatum.datumIndex?.[0] ?? 0;
const highlightedNode = this.getActiveHighlightNode();
const highlightState = this.getHierarchyHighlightState(isHighlight, highlightedNode, nodeDatum);
const highlightStyles = this.getHierarchyHighlightStyles(highlightState, this.properties.highlight);
const baseStyle = mergeDefaults23(highlightStyles, properties.getStyle(rootIndex));
if (nodeDatum.colorValue != null && highlightStyles?.fill == null) {
baseStyle.fill = colorScale.convert(nodeDatum.colorValue);
}
let style = baseStyle;
if (itemStyler != null && nodeDatum != null) {
const overrides = this.cachedDatumCallback(
createDatumId22(this.getDatumId(nodeDatum), isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(
nodeDatum,
style,
toHierarchyHighlightString(highlightState)
);
return this.callWithContext(itemStyler, params);
}
);
if (overrides) {
style = mergeDefaults23(overrides, style);
}
}
return style;
}
makeItemStylerParams(nodeDatum, style, highlightState) {
const { id: seriesId } = this;
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum: nodeDatum.datum,
depth: nodeDatum.depth ?? 0,
highlightState,
...style,
fill
};
}
updateNodes() {
const { chart, data, maxDepth } = this;
if (chart == null || data == null) {
return;
}
const { width, height } = chart.seriesRect;
const {
sectorSpacing = 0,
padding: padding2 = 0,
cornerRadius,
childrenKey,
colorKey,
colorName,
labelKey,
secondaryLabelKey,
sizeKey,
sizeName
} = this.properties;
this.contentGroup.translationX = width / 2;
this.contentGroup.translationY = height / 2;
const baseInset = sectorSpacing * 0.5;
const radius = Math.min(width, height) / 2;
const radiusScale = radius / (maxDepth + 1);
const angleOffset = -Math.PI / 2;
const seriesFillBBox = {
series: new BBox28(-radius, -radius, 2 * radius, 2 * radius),
axis: new BBox28(-radius, -radius, 2 * radius, 2 * radius)
};
this.rootNode?.walk((node) => {
const { startAngle, endAngle } = node;
if (node.depth != null) {
const midAngle = (startAngle + endAngle) / 2 + angleOffset;
const midRadius = (node.depth + 0.5) * radiusScale;
node.midPoint.x = Math.cos(midAngle) * midRadius;
node.midPoint.y = Math.sin(midAngle) * midRadius;
}
});
this.rootNode?.walk((node) => {
const { datum, depth, startAngle, endAngle, parent, sumSize } = node;
node.label = void 0;
node.secondaryLabel = void 0;
node.contentHeight = 0;
let labelValue;
if (datum != null && depth != null && labelKey != null) {
const value = datum[labelKey];
labelValue = this.getLabelText(
value,
datum,
labelKey,
"label",
[],
this.properties.label,
{
depth,
datum,
childrenKey,
colorKey,
colorName,
labelKey,
secondaryLabelKey,
sizeKey,
sizeName,
value
}
);
}
if (labelValue === "") {
labelValue = void 0;
}
let secondaryLabelValue;
if (datum != null && depth != null && secondaryLabelKey != null) {
const value = datum[secondaryLabelKey];
secondaryLabelValue = this.getLabelText(
value,
datum,
secondaryLabelKey,
"secondaryLabel",
[],
this.properties.secondaryLabel,
{
depth,
datum,
childrenKey,
colorKey,
colorName,
labelKey,
secondaryLabelKey,
sizeKey,
sizeName,
value
}
);
}
if (secondaryLabelValue === "") {
secondaryLabelValue = void 0;
}
if (depth == null)
return;
const innerRadius = depth * radiusScale + baseInset;
const outerRadius = (depth + 1) * radiusScale - baseInset;
const innerAngleOffset = innerRadius > baseInset ? baseInset / innerRadius : baseInset;
const outerAngleOffset = outerRadius > baseInset ? baseInset / outerRadius : baseInset;
const innerStartAngle = startAngle + innerAngleOffset;
const innerEndAngle = endAngle + innerAngleOffset;
const deltaInnerAngle = innerEndAngle - innerStartAngle;
const outerStartAngle = startAngle + outerAngleOffset;
const outerEndAngle = endAngle + outerAngleOffset;
const deltaOuterAngle = outerEndAngle - outerStartAngle;
const sizeFittingHeight = (labelHeight2) => {
const isCenterCircle = depth === 0 && parent?.sumSize === sumSize;
if (isCenterCircle) {
const labelWidth2 = 2 * Math.sqrt(outerRadius ** 2 - (labelHeight2 * 0.5) ** 2);
return { width: labelWidth2, height: labelHeight2, meta: 0 /* CenterCircle */ };
}
const parallelHeight = labelHeight2;
const availableWidthUntilItHitsTheOuterRadius = 2 * Math.sqrt(outerRadius ** 2 - (innerRadius + parallelHeight) ** 2);
const availableWidthUntilItHitsTheStraightEdges = deltaInnerAngle < Math.PI ? 2 * innerRadius * Math.tan(deltaInnerAngle * 0.5) : Infinity;
const parallelWidth = Math.min(
availableWidthUntilItHitsTheOuterRadius,
availableWidthUntilItHitsTheStraightEdges
);
const maxPerpendicularAngle = Math.PI / 4;
let perpendicularHeight;
let perpendicularWidth;
if (depth === 0) {
perpendicularHeight = labelHeight2;
perpendicularWidth = Math.sqrt(outerRadius ** 2 - (perpendicularHeight / 2) ** 2) - labelHeight2 / (2 * Math.tan(deltaOuterAngle * 0.5));
} else if (normalizeAngle3608(deltaInnerAngle) < maxPerpendicularAngle) {
perpendicularHeight = 2 * innerRadius * Math.tan(deltaInnerAngle * 0.5);
perpendicularWidth = Math.sqrt(outerRadius ** 2 - (perpendicularHeight / 2) ** 2) - innerRadius;
} else {
perpendicularWidth = 0;
perpendicularHeight = 0;
}
return parallelWidth >= perpendicularWidth ? { width: parallelWidth, height: parallelHeight, meta: 1 /* Parallel */ } : { width: perpendicularWidth, height: perpendicularHeight, meta: 2 /* Perpendicular */ };
};
const formatting = formatLabels(
toPlainText12(labelValue),
this.properties.label,
toPlainText12(secondaryLabelValue),
this.properties.secondaryLabel,
{ padding: padding2 },
sizeFittingHeight
);
if (formatting == null)
return;
const { width: labelWidth, height: labelHeight, meta: labelPlacement, label, secondaryLabel } = formatting;
const theta = angleOffset + (startAngle + endAngle) / 2;
const top = Math.sin(theta) >= 0;
const right = Math.cos(theta) >= 0;
const circleQuarter = (top ? 3 /* Top */ : 12 /* Bottom */) & (right ? 6 /* Right */ : 9 /* Left */);
let labelRadius;
switch (labelPlacement) {
case 0 /* CenterCircle */:
labelRadius = 0;
break;
case 1 /* Parallel */: {
const opticalCentering = 0.58;
const idealRadius = outerRadius - (radiusScale - labelHeight) * opticalCentering;
const maximumRadius = Math.sqrt((outerRadius - padding2) ** 2 - (labelWidth / 2) ** 2);
labelRadius = Math.min(idealRadius, maximumRadius);
break;
}
case 2 /* Perpendicular */:
if (depth === 0) {
const minimumRadius = labelHeight / (2 * Math.tan(deltaInnerAngle * 0.5)) + labelWidth * 0.5;
const maximumRadius = Math.sqrt(outerRadius ** 2 - (labelHeight * 0.5) ** 2) - labelWidth * 0.5;
labelRadius = (minimumRadius + maximumRadius) * 0.5;
} else {
labelRadius = (innerRadius + outerRadius) * 0.5;
}
break;
}
if (label != null) {
const {
fontStyle = "normal",
fontFamily,
fontWeight = "normal",
color: color7 = "black"
} = this.properties.label;
node.label = {
...label,
fontStyle,
fontFamily,
fontWeight,
color: color7,
labelPlacement,
circleQuarter,
radius: labelRadius,
theta
};
}
if (secondaryLabel != null) {
const {
fontStyle = "normal",
fontFamily,
fontWeight = "normal",
color: color7 = "black"
} = this.properties.secondaryLabel;
node.secondaryLabel = {
...secondaryLabel,
fontStyle,
fontFamily,
fontWeight,
color: color7,
labelPlacement,
circleQuarter,
radius: labelRadius,
theta
};
}
node.contentHeight = formatting.height;
});
const updateSector = (nodeDatum, sector, highlighted) => {
const { depth, startAngle, endAngle } = nodeDatum;
if (depth == null) {
sector.visible = false;
return;
}
sector.visible = true;
const style = this.getItemStyle(nodeDatum, highlighted);
const fill = style.fill;
const strokeWidth = style.strokeWidth;
const fillBBox = isGradientFill4(fill) && fill.bounds !== "item" ? seriesFillBBox : void 0;
sector.setStyleProperties(style, fillBBox);
sector.centerX = 0;
sector.centerY = 0;
sector.innerRadius = depth * radiusScale;
sector.outerRadius = (depth + 1) * radiusScale;
sector.startAngle = startAngle + angleOffset;
sector.endAngle = endAngle + angleOffset;
sector.inset = baseInset + strokeWidth * 0.5;
sector.cornerRadius = cornerRadius;
};
this.datumSelection.each((sector, datum) => {
updateSector(datum, sector, false);
});
this.highlightSelection.each((rect, datum) => {
updateSector(datum, rect, true);
});
const highlightedNode = this.getActiveHighlightNode();
const updateText = (node, text2, tag, highlighted) => {
const { depth, contentHeight } = node;
const primary = tag === 0 /* Primary */;
const label = primary ? node.label : node.secondaryLabel;
if (depth == null || label == null) {
text2.visible = false;
return;
}
const { labelPlacement, circleQuarter, radius: textRadius, theta } = label;
const highlightState = this.getHierarchyHighlightState(highlighted, highlightedNode, node);
const { opacity: highlightOpacity } = this.getHierarchyHighlightStyles(highlightState, this.properties.highlight) ?? {};
const params = {
childrenKey: this.properties.childrenKey,
colorKey: this.properties.colorKey,
colorName: this.properties.colorName ?? this.properties.colorKey,
depth: node.depth ?? Number.NaN,
labelKey: this.properties.labelKey,
secondaryLabelKey: this.properties.secondaryLabelKey,
sizeKey: this.properties.sizeKey,
sizeName: this.properties.sizeName ?? this.properties.sizeKey
};
const baseLabelStyle = primary ? this.properties.label : this.properties.secondaryLabel;
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const style = getLabelStyles7(this, node, params, baseLabelStyle, highlighted, activeHighlight);
text2.text = label.text;
text2.fontSize = label.fontSize;
text2.lineHeight = label.lineHeight;
text2.fontStyle = label.fontStyle;
text2.fontFamily = label.fontFamily;
text2.fontWeight = label.fontWeight;
text2.fillOpacity = highlightOpacity ?? 1;
text2.fill = style.color;
text2.setBoxing(style);
switch (labelPlacement) {
case 0 /* CenterCircle */:
text2.textAlign = "center";
text2.textBaseline = "top";
text2.translationX = 0;
text2.translationY = (primary ? 0 : contentHeight - label.height) - contentHeight * 0.5;
text2.rotation = 0;
break;
case 1 /* Parallel */: {
const topHalf = (circleQuarter & 3 /* Top */) !== 0;
const translationRadius = primary === !topHalf ? textRadius : textRadius - (contentHeight - label.height);
text2.textAlign = "center";
text2.textBaseline = topHalf ? "bottom" : "top";
text2.translationX = Math.cos(theta) * translationRadius;
text2.translationY = Math.sin(theta) * translationRadius;
text2.rotation = topHalf ? theta - Math.PI * 0.5 : theta + Math.PI * 0.5;
break;
}
case 2 /* Perpendicular */: {
const rightHalf = (circleQuarter & 6 /* Right */) !== 0;
const translation = primary === !rightHalf ? (contentHeight - label.height) * 0.5 : (label.height - contentHeight) * 0.5;
text2.textAlign = "center";
text2.textBaseline = "middle";
text2.translationX = Math.cos(theta) * textRadius + Math.cos(theta + Math.PI / 2) * translation;
text2.translationY = Math.sin(theta) * textRadius + Math.sin(theta + Math.PI / 2) * translation;
text2.rotation = rightHalf ? theta : theta + Math.PI;
break;
}
}
text2.visible = true;
};
const highlightedDatum = this.getActiveHighlightNode();
for (const text2 of this.labelSelection.selectByClass(TransformableText4)) {
const datum = text2.closestDatum();
updateText(datum, text2, text2.tag, datum === highlightedDatum);
}
}
getTooltipContent(datumIndex) {
const { id: seriesId, properties, ctx } = this;
const { labelKey, secondaryLabelKey, childrenKey, sizeKey, sizeName, colorKey, colorName, tooltip } = properties;
const { formatManager } = ctx;
const nodeDatum = datumIndex.reduce((n, i) => n?.children[i], this.rootNode);
if (nodeDatum == null)
return;
const { datum, depth } = nodeDatum;
if (datum == null || depth == null)
return;
const data = [];
const datumSize = sizeKey == null ? void 0 : datum[sizeKey];
if (datumSize != null) {
const sizeDomain = [0, this.rootNode?.sumSize ?? 0];
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: datumSize,
datum,
seriesId,
legendItemName: void 0,
key: sizeKey,
source: "tooltip",
property: "size",
boundSeries: this.getFormatterContext("size"),
domain: sizeDomain,
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: sizeName, fallbackLabel: sizeKey, value: content ?? formatValue2(datumSize) });
}
const datumColor = colorKey == null ? void 0 : datum[colorKey];
if (datumColor != null) {
const { colorDomain } = this;
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: datumColor,
datum,
seriesId,
legendItemName: void 0,
key: colorKey,
source: "tooltip",
property: "color",
boundSeries: this.getFormatterContext("color"),
domain: colorDomain,
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: colorName, fallbackLabel: colorKey, value: content ?? formatValue2(datumColor) });
}
const format = this.getItemStyle(
{ ...nodeDatum, colorValue: datumColor ?? nodeDatum.colorValue },
false
);
const color7 = format.fill;
const markerStyle = {
shape: "square",
fill: color7,
fillOpacity: 1,
stroke: void 0,
strokeWidth: 0,
strokeOpacity: 1,
lineDash: [0],
lineDashOffset: 0
};
if (isGradientFill4(markerStyle.fill)) {
markerStyle.fill = { ...markerStyle.fill, gradient: "linear", rotation: 0, reverse: false };
}
return this.formatTooltipWithContext(
tooltip,
{
title: labelKey == null ? void 0 : datum[labelKey],
symbol: {
marker: markerStyle
},
data
},
{
seriesId,
datum,
title: void 0,
depth,
labelKey,
secondaryLabelKey,
childrenKey,
sizeKey,
sizeName,
colorKey,
colorName,
...format
}
);
}
createNodeData() {
return void 0;
}
pickNodeClosestDatum(point) {
return this.pickNodeNearestDistantObject(point, this.datumSelection.nodes());
}
animateEmptyUpdateReady() {
fromToMotion6(this.id, "nodes", this.ctx.animationManager, [this.scalingGroup], {
toFn() {
return { scalingX: 1, scalingY: 1 };
},
fromFn() {
return { scalingX: 0, scalingY: 0 };
}
});
}
computeFocusBounds(node) {
return node;
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.label.itemStyler != null;
}
};
SunburstSeries.className = "SunburstSeries";
SunburstSeries.type = "sunburst";
// packages/ag-charts-enterprise/src/series/sunburst/sunburstSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport209 } from "ag-charts-community";
import { commonSeriesOptionsDefs as commonSeriesOptionsDefs22, constant as constant23, required as required23, string as string23, without as without9 } from "ag-charts-core";
var { sunburstSeriesThemeableOptionsDef } = _ModuleSupport209;
var sunburstSeriesOptionsDef = {
...sunburstSeriesThemeableOptionsDef,
...without9(commonSeriesOptionsDefs22, ["highlightStyle", "highlight", "showInLegend"]),
type: required23(constant23("sunburst")),
labelKey: string23,
secondaryLabelKey: string23,
childrenKey: string23,
sizeKey: string23,
colorKey: string23,
sizeName: string23,
colorName: string23
};
// packages/ag-charts-enterprise/src/series/sunburst/sunburstModule.ts
var themeTemplate3 = {
series: {
fills: {
$applyCycle: [
{ $size: { $path: ["./data", { $path: "/data" }] } },
{ $palette: "fills" },
{
$applySwitch: [
{ $path: ["/type", void 0, { $value: "$1" }] },
{ $value: "$1" },
["gradient", FILL_GRADIENT_RADIAL_REVERSED_SERIES_DEFAULTS],
["pattern", FILL_PATTERN_DEFAULTS13],
["image", FILL_IMAGE_DEFAULTS18]
]
}
]
},
strokes: {
$applyCycle: [{ $size: { $path: ["./data", { $path: "/data" }] } }, { $palette: "strokes" }]
},
colorRange: { $palette: "divergingColors" },
strokeWidth: { $isUserOption: ["./strokes/0", 2, 0] },
label: {
...LABEL_BOXING_DEFAULTS19,
enabled: true,
fontFamily: { $ref: "fontFamily" },
fontSize: { $rem: FONT_SIZE_RATIO4.LARGE },
minimumFontSize: { $rem: 9 / BASE_FONT_SIZE },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "chartBackgroundColor" },
overflowStrategy: "ellipsis",
wrapping: "never",
spacing: 2
},
secondaryLabel: {
...LABEL_BOXING_DEFAULTS19,
enabled: true,
fontFamily: { $ref: "fontFamily" },
fontSize: { $rem: FONT_SIZE_RATIO4.SMALLEST },
minimumFontSize: { $rem: 7 / BASE_FONT_SIZE },
fontWeight: { $ref: "fontWeight" },
color: { $ref: "chartBackgroundColor" },
overflowStrategy: "ellipsis",
wrapping: "never"
},
sectorSpacing: 2,
padding: 3,
highlight: {
unhighlightedItem: {
fillOpacity: 0.6,
strokeOpacity: 0.6
},
unhighlightedBranch: {
fillOpacity: 0.2,
strokeOpacity: 0.2
}
}
},
gradientLegend: {
enabled: { $if: [{ $path: "../series/0/colorKey" }, true, false] }
}
};
var SunburstSeriesModule = {
type: "series",
name: "sunburst",
chartType: "standalone",
enterprise: true,
solo: true,
version: VERSION49,
dependencies: [StandaloneChartModule],
options: sunburstSeriesOptionsDef,
themeTemplate: themeTemplate3,
create: (ctx) => new SunburstSeries(ctx)
};
// packages/ag-charts-enterprise/src/series/treemap/treemapModule.ts
import { VERSION as VERSION50 } from "ag-charts-community";
import {
FILL_GRADIENT_LINEAR_DEFAULTS as FILL_GRADIENT_LINEAR_DEFAULTS9,
FILL_IMAGE_DEFAULTS as FILL_IMAGE_DEFAULTS19,
FILL_PATTERN_DEFAULTS as FILL_PATTERN_DEFAULTS14,
FONT_SIZE_RATIO as FONT_SIZE_RATIO5,
LABEL_BOXING_DEFAULTS as LABEL_BOXING_DEFAULTS20
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/treemap/treemapSeries.ts
import {
_ModuleSupport as _ModuleSupport211
} from "ag-charts-community";
import {
cachedTextMeasurer as cachedTextMeasurer13,
calcLineHeight as calcLineHeight8,
formatValue as formatValue3,
isGradientFill as isGradientFill5,
isNumberEqual as isNumberEqual11,
mergeDefaults as mergeDefaults24,
toPlainText as toPlainText13,
wrapText as wrapText5
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/series/treemap/treemapSeriesProperties.ts
import { _ModuleSupport as _ModuleSupport210 } from "ag-charts-community";
import { BaseProperties as BaseProperties37, Property as Property89 } from "ag-charts-core";
var { HierarchySeriesProperties: HierarchySeriesProperties2, makeSeriesTooltip: makeSeriesTooltip24, Label: Label18 } = _ModuleSupport210;
var TreemapGroupLabel = class extends Label18 {
constructor() {
super(...arguments);
this.spacing = 0;
}
};
__decorateClass([
Property89
], TreemapGroupLabel.prototype, "spacing", 2);
var TreemapSeriesGroupHighlightStyle = class extends BaseProperties37 {
};
__decorateClass([
Property89
], TreemapSeriesGroupHighlightStyle.prototype, "fill", 2);
__decorateClass([
Property89
], TreemapSeriesGroupHighlightStyle.prototype, "fillOpacity", 2);
__decorateClass([
Property89
], TreemapSeriesGroupHighlightStyle.prototype, "stroke", 2);
__decorateClass([
Property89
], TreemapSeriesGroupHighlightStyle.prototype, "strokeWidth", 2);
__decorateClass([
Property89
], TreemapSeriesGroupHighlightStyle.prototype, "strokeOpacity", 2);
__decorateClass([
Property89
], TreemapSeriesGroupHighlightStyle.prototype, "opacity", 2);
var TreemapSeriesGroupHighlight = class extends BaseProperties37 {
constructor() {
super(...arguments);
this.highlightedItem = new TreemapSeriesGroupHighlightStyle();
this.unhighlightedItem = new TreemapSeriesGroupHighlightStyle();
}
};
__decorateClass([
Property89
], TreemapSeriesGroupHighlight.prototype, "highlightedItem", 2);
__decorateClass([
Property89
], TreemapSeriesGroupHighlight.prototype, "unhighlightedItem", 2);
var TreemapSeriesTileHighlightStyle = class extends BaseProperties37 {
};
__decorateClass([
Property89
], TreemapSeriesTileHighlightStyle.prototype, "fill", 2);
__decorateClass([
Property89
], TreemapSeriesTileHighlightStyle.prototype, "fillOpacity", 2);
__decorateClass([
Property89
], TreemapSeriesTileHighlightStyle.prototype, "stroke", 2);
__decorateClass([
Property89
], TreemapSeriesTileHighlightStyle.prototype, "strokeWidth", 2);
__decorateClass([
Property89
], TreemapSeriesTileHighlightStyle.prototype, "strokeOpacity", 2);
__decorateClass([
Property89
], TreemapSeriesTileHighlightStyle.prototype, "opacity", 2);
var TreemapSeriesTileHighlight = class extends BaseProperties37 {
constructor() {
super(...arguments);
this.highlightedBranch = new TreemapSeriesTileHighlightStyle();
this.highlightedItem = new TreemapSeriesTileHighlightStyle();
this.unhighlightedItem = new TreemapSeriesTileHighlightStyle();
this.unhighlightedBranch = new TreemapSeriesTileHighlightStyle();
}
};
__decorateClass([
Property89
], TreemapSeriesTileHighlight.prototype, "highlightedBranch", 2);
__decorateClass([
Property89
], TreemapSeriesTileHighlight.prototype, "highlightedItem", 2);
__decorateClass([
Property89
], TreemapSeriesTileHighlight.prototype, "unhighlightedItem", 2);
__decorateClass([
Property89
], TreemapSeriesTileHighlight.prototype, "unhighlightedBranch", 2);
var TreemapSeriesGroup = class extends BaseProperties37 {
constructor() {
super(...arguments);
this.fill = void 0;
this.fillOpacity = 1;
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.cornerRadius = 0;
this.textAlign = "center";
this.gap = 0;
this.padding = 0;
this.interactive = true;
this.label = new TreemapGroupLabel();
this.highlight = new TreemapSeriesGroupHighlight();
}
};
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "fill", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "fillOpacity", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "stroke", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "strokeWidth", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "strokeOpacity", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "cornerRadius", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "textAlign", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "gap", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "padding", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "interactive", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "label", 2);
__decorateClass([
Property89
], TreemapSeriesGroup.prototype, "highlight", 2);
var TreemapSeriesTile = class extends BaseProperties37 {
constructor() {
super(...arguments);
this.fill = void 0;
this.fillOpacity = 1;
this.strokeWidth = 1;
this.strokeOpacity = 1;
this.cornerRadius = 0;
this.textAlign = "center";
this.verticalAlign = "middle";
this.gap = 0;
this.padding = 0;
this.label = new AutoSizedLabel();
this.secondaryLabel = new AutoSizedSecondaryLabel();
this.highlight = new TreemapSeriesTileHighlight();
}
};
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "fill", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "fillOpacity", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "stroke", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "strokeWidth", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "strokeOpacity", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "cornerRadius", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "textAlign", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "verticalAlign", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "gap", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "padding", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "label", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "secondaryLabel", 2);
__decorateClass([
Property89
], TreemapSeriesTile.prototype, "highlight", 2);
var TreemapSeriesProperties = class extends HierarchySeriesProperties2 {
constructor() {
super(...arguments);
this.tooltip = makeSeriesTooltip24();
this.group = new TreemapSeriesGroup();
this.tile = new TreemapSeriesTile();
this.undocumentedGroupFills = [];
this.undocumentedGroupStrokes = [];
}
getStyle(isLeaf, fills, strokes, index) {
const {
fillOpacity,
strokeWidth,
strokeOpacity,
fill = isLeaf ? fills[index % fills.length] : fills[Math.min(index, fills.length)],
stroke: stroke3 = isLeaf ? strokes[index % fills.length] : strokes[Math.min(index, strokes.length)]
} = isLeaf ? this.tile : this.group;
return {
fill,
fillOpacity,
stroke: stroke3,
strokeWidth,
strokeOpacity,
opacity: 1
};
}
};
__decorateClass([
Property89
], TreemapSeriesProperties.prototype, "sizeName", 2);
__decorateClass([
Property89
], TreemapSeriesProperties.prototype, "labelKey", 2);
__decorateClass([
Property89
], TreemapSeriesProperties.prototype, "secondaryLabelKey", 2);
__decorateClass([
Property89
], TreemapSeriesProperties.prototype, "itemStyler", 2);
__decorateClass([
Property89
], TreemapSeriesProperties.prototype, "tooltip", 2);
__decorateClass([
Property89
], TreemapSeriesProperties.prototype, "group", 2);
__decorateClass([
Property89
], TreemapSeriesProperties.prototype, "tile", 2);
__decorateClass([
Property89
], TreemapSeriesProperties.prototype, "undocumentedGroupFills", 2);
__decorateClass([
Property89
], TreemapSeriesProperties.prototype, "undocumentedGroupStrokes", 2);
// packages/ag-charts-enterprise/src/series/treemap/treemapSeries.ts
var {
createDatumId: createDatumId23,
Rect: Rect10,
Group: Group22,
BBox: BBox29,
Selection: Selection18,
Text: Text10,
Transformable: Transformable6,
getLabelStyles: getLabelStyles8,
HierarchyHighlightState,
toHierarchyHighlightString: toHierarchyHighlightString2
} = _ModuleSupport211;
var TreemapNode = class extends _ModuleSupport211.HierarchyNode {
constructor() {
super(...arguments);
this.labelValue = void 0;
this.secondaryLabelValue = void 0;
this.label = void 0;
this.secondaryLabel = void 0;
this.bbox = void 0;
this.padding = void 0;
}
};
function nodeSize(node) {
return node.children.length > 0 ? node.sumSize - node.sizeValue : node.sizeValue;
}
var textAlignFactors2 = {
left: 0,
center: 0.5,
right: 1
};
var verticalAlignFactors4 = {
top: 0,
middle: 0.5,
bottom: 1
};
var DistantGroup = class extends _ModuleSupport211.Group {
distanceSquared(x, y) {
return this.getBBox().distanceSquared(x, y);
}
};
var TreemapSeries = class extends _ModuleSupport211.HierarchySeries {
constructor() {
super(...arguments);
this.NodeClass = TreemapNode;
this.properties = new TreemapSeriesProperties();
this.rectGroup = this.contentGroup.appendChild(new Group22());
this.datumSelection = Selection18.select(this.rectGroup, Rect10);
this.labelSelection = Selection18.select(this.labelGroup, Group22);
this.highlightSelection = Selection18.select(
this.rectGroup,
Rect10
);
}
groupTitleHeight(node, bbox) {
const heightRatioThreshold = 3;
const { label } = this.properties.group;
const { labelValue } = node;
const { fontSize } = label;
if (label.enabled && labelValue != null && fontSize <= bbox.width / heightRatioThreshold && fontSize <= bbox.height / heightRatioThreshold) {
const { height: fontHeight } = cachedTextMeasurer13(label).measureLines(labelValue);
return Math.max(fontHeight, fontSize);
}
}
getNodePadding(node, bbox) {
if (node.parent == null) {
return { top: 0, right: 0, bottom: 0, left: 0 };
} else if (node.children.length === 0) {
const { padding: padding3 } = this.properties.tile;
return { top: padding3, right: padding3, bottom: padding3, left: padding3 };
}
const {
padding: padding2,
label: { spacing }
} = this.properties.group;
const fontHeight = this.groupTitleHeight(node, bbox);
const titleHeight = fontHeight == null ? 0 : fontHeight + spacing;
return {
top: padding2 + titleHeight,
right: padding2,
bottom: padding2,
left: padding2
};
}
sortChildren({ children }) {
const sortedChildrenIndices = Array.from(children, (_, i) => i).filter((i) => nodeSize(children[i]) > 0).sort((aIndex, bIndex) => nodeSize(children[bIndex]) - nodeSize(children[aIndex]));
const childAt = (i) => {
const sortedIndex = sortedChildrenIndices[i];
return children[sortedIndex];
};
return { sortedChildrenIndices, childAt };
}
/**
* Squarified Treemap algorithm
* https://www.win.tue.nl/~vanwijk/stm.pdf
*/
squarify(node, bbox) {
const { datum, children } = node;
if (bbox.width <= 0 || bbox.height <= 0) {
node.bbox = void 0;
node.padding = void 0;
node.midPoint.x = Number.NaN;
node.midPoint.y = Number.NaN;
return;
}
const padding2 = datum == null ? { top: 0, right: 0, bottom: 0, left: 0 } : this.getNodePadding(node, bbox);
if (node.parent == null) {
node.bbox = void 0;
node.padding = void 0;
node.midPoint.x = Number.NaN;
node.midPoint.y = Number.NaN;
} else {
node.bbox = bbox;
node.padding = padding2;
node.midPoint.x = bbox.x + bbox.width / 2;
node.midPoint.y = bbox.y;
}
const { sortedChildrenIndices, childAt } = this.sortChildren(node);
const allLeafNodes = sortedChildrenIndices.every((sortedIndex) => children[sortedIndex].children.length === 0);
const targetTileAspectRatio = 1;
const width = bbox.width - padding2.left - padding2.right;
const height = bbox.height - padding2.top - padding2.bottom;
if (width <= 0 || height <= 0)
return;
const numChildren = sortedChildrenIndices.length;
let stackSum = 0;
let startIndex = 0;
let minRatioDiff = Infinity;
let partitionSum = sortedChildrenIndices.reduce((sum, sortedIndex) => sum + nodeSize(children[sortedIndex]), 0);
const innerBox = new BBox29(bbox.x + padding2.left, bbox.y + padding2.top, width, height);
const partition = innerBox.clone();
let i = 0;
while (i < numChildren) {
const value = nodeSize(childAt(i));
const firstValue = nodeSize(childAt(startIndex));
const isVertical2 = partition.width < partition.height;
stackSum += value;
const partThickness = isVertical2 ? partition.height : partition.width;
const partLength = isVertical2 ? partition.width : partition.height;
const firstTileLength = partLength * firstValue / stackSum;
let stackThickness = partThickness * stackSum / partitionSum;
const ratio8 = Math.max(firstTileLength, stackThickness) / Math.min(firstTileLength, stackThickness);
const diff8 = Math.abs(targetTileAspectRatio - ratio8);
if (diff8 < minRatioDiff) {
minRatioDiff = diff8;
i++;
continue;
}
stackSum -= value;
stackThickness = partThickness * stackSum / partitionSum;
let start2 = isVertical2 ? partition.x : partition.y;
for (let j = startIndex; j < i; j++) {
const child = childAt(j);
const childSize = nodeSize(child);
const x = isVertical2 ? start2 : partition.x;
const y = isVertical2 ? partition.y : start2;
const length = partLength * childSize / stackSum;
const stackWidth = isVertical2 ? length : stackThickness;
const stackHeight = isVertical2 ? stackThickness : length;
const childBbox = new BBox29(x, y, stackWidth, stackHeight);
this.applyGap(innerBox, childBbox, allLeafNodes);
this.squarify(child, childBbox);
partitionSum -= childSize;
start2 += length;
}
if (isVertical2) {
partition.y += stackThickness;
partition.height -= stackThickness;
} else {
partition.x += stackThickness;
partition.width -= stackThickness;
}
startIndex = i;
stackSum = 0;
minRatioDiff = Infinity;
}
const isVertical = partition.width < partition.height;
let start = isVertical ? partition.x : partition.y;
for (let childIdx = startIndex; childIdx < numChildren; childIdx++) {
const child = childAt(childIdx);
const x = isVertical ? start : partition.x;
const y = isVertical ? partition.y : start;
const part = nodeSize(child) / partitionSum;
const childWidth = partition.width * (isVertical ? part : 1);
const childHeight = partition.height * (isVertical ? 1 : part);
const childBox = new BBox29(x, y, childWidth, childHeight);
this.applyGap(innerBox, childBox, allLeafNodes);
this.squarify(child, childBox);
start += isVertical ? childWidth : childHeight;
}
}
applyGap(innerBox, childBox, allLeafNodes) {
const gap = allLeafNodes ? this.properties.tile.gap * 0.5 : this.properties.group.gap * 0.5;
const getBounds = (box) => ({
left: box.x,
top: box.y,
right: box.x + box.width,
bottom: box.y + box.height
});
const innerBounds = getBounds(innerBox);
const childBounds = getBounds(childBox);
const sides = ["top", "right", "bottom", "left"];
for (const side of sides) {
if (!isNumberEqual11(innerBounds[side], childBounds[side])) {
childBox.shrink(gap, side);
}
}
}
createNodeData() {
return void 0;
}
getItemStyle(nodeDatum, isLeaf, isHighlight) {
const { properties, colorScale } = this;
const { itemStyler } = properties;
const rootIndex = nodeDatum.datumIndex?.[0] ?? 0;
const fills = isLeaf ? properties.fills : properties.undocumentedGroupFills;
const strokes = isLeaf ? properties.strokes : properties.undocumentedGroupStrokes;
const index = isLeaf ? rootIndex : nodeDatum.depth ?? -1;
const highlightedNode = this.getActiveHighlightNode();
const tileHighlightState = this.getHierarchyHighlightState(isHighlight, highlightedNode, nodeDatum);
const groupHighlightState = this.getGroupHighlightState(isHighlight, highlightedNode, nodeDatum);
const highlightState = isLeaf ? tileHighlightState : groupHighlightState;
const highlightStyle = isLeaf ? this.getTileHighlightStyle(tileHighlightState, groupHighlightState, highlightedNode) : this.getGroupHighlightStyle(groupHighlightState);
const baseStyle = mergeDefaults24(highlightStyle, properties.getStyle(isLeaf, fills, strokes, index));
if (isLeaf && nodeDatum.colorValue != null && highlightStyle?.fill == null) {
baseStyle.fill = colorScale.convert(nodeDatum.colorValue);
}
let style = baseStyle;
if (itemStyler != null && nodeDatum != null) {
const overrides = this.cachedDatumCallback(
createDatumId23(this.getDatumId(nodeDatum), isHighlight ? "highlight" : "node"),
() => {
const params = this.makeItemStylerParams(
nodeDatum,
style,
toHierarchyHighlightString2(highlightState)
);
return this.callWithContext(itemStyler, params);
}
);
if (overrides) {
style = mergeDefaults24(overrides, style);
}
}
return style;
}
makeItemStylerParams(nodeDatum, style, highlightState) {
const { id: seriesId } = this;
const fill = this.filterItemStylerFillParams(style.fill) ?? style.fill;
return {
seriesId,
datum: nodeDatum.datum,
depth: nodeDatum.depth ?? -1,
highlightState,
...style,
fill
};
}
updateSelections() {
const highlightedNode = this.getActiveHighlightNode();
this.highlightSelection.update(
highlightedNode == null ? [] : [highlightedNode],
void 0,
(node) => this.getDatumId(node)
);
if (!this.nodeDataRefresh) {
return;
}
this.nodeDataRefresh = false;
const { seriesRect } = this.chart ?? {};
if (!seriesRect)
return;
const descendants = Array.from(this.rootNode);
const updateLabelGroup = (group) => {
group.append([new Text10({ tag: 0 /* Primary */ }), new Text10({ tag: 1 /* Secondary */ })]);
};
this.datumSelection.update(descendants, void 0, (node) => this.getDatumId(node));
this.labelSelection.update(descendants, updateLabelGroup, (node) => this.getDatumId(node));
}
getActiveHighlightNode() {
const highlightedNode = super.getActiveHighlightNode();
if (highlightedNode?.children.length && !this.properties.group.interactive) {
return void 0;
}
return highlightedNode;
}
updateNodes() {
const { rootNode, data } = this;
const { childrenKey, colorKey, colorName, labelKey, secondaryLabelKey, sizeKey, sizeName, tile, group } = this.properties;
const { seriesRect } = this.chart ?? {};
if (!seriesRect || !data)
return;
this.rootNode?.walk((node) => {
const { datum, depth, children } = node;
const isLeaf = children.length === 0;
const labelStyle = isLeaf ? tile.label : group.label;
let labelValue;
if (labelStyle.enabled && datum != null && depth != null && labelKey != null) {
const value = datum[labelKey];
labelValue = this.getLabelText(
value,
datum,
labelKey,
"label",
[],
labelStyle,
{
depth,
datum,
childrenKey,
colorKey,
colorName,
labelKey,
secondaryLabelKey,
sizeKey,
sizeName,
value
}
);
}
if (labelValue === "") {
labelValue = void 0;
}
let secondaryLabelValue;
if (tile.secondaryLabel.enabled && isLeaf && datum != null && depth != null && secondaryLabelKey != null) {
const value = datum[secondaryLabelKey];
secondaryLabelValue = this.getLabelText(
value,
datum,
secondaryLabelKey,
"secondaryLabel",
[],
tile.secondaryLabel,
{
depth,
datum,
childrenKey,
colorKey,
colorName,
labelKey,
secondaryLabelKey,
sizeKey,
sizeName,
value
}
);
}
if (secondaryLabelValue === "") {
secondaryLabelValue = void 0;
}
node.labelValue = toPlainText13(labelValue);
node.secondaryLabelValue = toPlainText13(secondaryLabelValue);
});
const { width, height } = seriesRect;
this.squarify(rootNode, new BBox29(0, 0, width, height));
this.rootNode?.walk((node) => {
const { bbox, children, labelValue, secondaryLabelValue } = node;
node.label = void 0;
node.secondaryLabel = void 0;
if (bbox == null)
return;
if (children.length === 0) {
const layout = {
width: bbox.width,
height: bbox.height,
meta: null
};
const formatting = formatLabels(
labelValue,
this.properties.tile.label,
secondaryLabelValue,
this.properties.tile.secondaryLabel,
{ padding: tile.padding },
() => layout
);
if (formatting == null) {
return;
}
const { height: labelHeight, label, secondaryLabel } = formatting;
const { textAlign, verticalAlign, padding: padding2 } = tile;
const textAlignFactor = textAlignFactors2[textAlign] ?? 0.5;
const labelX = bbox.x + padding2 + (bbox.width - 2 * padding2) * textAlignFactor;
const verticalAlignFactor = verticalAlignFactors4[verticalAlign] ?? 0.5;
const labelYStart = bbox.y + padding2 + labelHeight * 0.5 + (bbox.height - 2 * padding2 - labelHeight) * verticalAlignFactor;
if (label != null) {
const {
fontStyle = "normal",
fontFamily,
fontWeight = "normal",
color: color7 = "black"
} = this.properties.tile.label;
node.label = {
text: label.text,
fontSize: label.fontSize,
lineHeight: label.lineHeight,
fontStyle,
fontFamily,
fontWeight,
color: color7,
textAlign,
verticalAlign: "middle",
x: labelX,
y: labelYStart - (labelHeight - label.height) * 0.5
};
}
if (secondaryLabel != null) {
const {
fontStyle = "normal",
fontFamily,
fontWeight = "normal",
color: color7 = "black"
} = this.properties.tile.secondaryLabel;
node.secondaryLabel = {
text: secondaryLabel.text,
fontSize: secondaryLabel.fontSize,
lineHeight: secondaryLabel.fontSize,
fontStyle,
fontFamily,
fontWeight,
color: color7,
textAlign,
verticalAlign: "middle",
x: labelX,
y: labelYStart + (labelHeight - secondaryLabel.height) * 0.5
};
}
} else if (labelValue == null) {
return;
} else {
const { padding: padding2, textAlign } = group;
const groupTitleHeight = this.groupTitleHeight(node, bbox);
if (groupTitleHeight == null)
return;
const innerWidth = bbox.width - 2 * padding2;
const text2 = wrapText5(labelValue, {
maxWidth: bbox.width - 2 * padding2,
font: group.label,
textWrap: "never"
});
const textAlignFactor = textAlignFactors2[textAlign] ?? 0.5;
const {
fontStyle = "normal",
fontFamily,
fontWeight = "normal",
color: color7 = "black"
} = this.properties.group.label;
node.label = {
text: text2,
fontSize: group.label.fontSize,
lineHeight: calcLineHeight8(group.label.fontSize),
fontStyle,
fontFamily,
fontWeight,
color: color7,
textAlign,
verticalAlign: "middle",
x: bbox.x + padding2 + innerWidth * textAlignFactor,
y: bbox.y + padding2 + groupTitleHeight * 0.5
};
}
});
const fillBBox = {
series: new BBox29(0, 0, width, height),
axis: new BBox29(0, 0, width, height)
};
const updateRectFn = (node, rect, isHighlight) => {
const { bbox } = node;
if (bbox == null) {
rect.visible = false;
return;
}
const { depth = -1 } = node;
const isLeaf = node.children.length === 0;
const style = this.getItemStyle(node, isLeaf, isHighlight);
rect.crisp = true;
rect.setStyleProperties(style, fillBBox);
rect.cornerRadius = isLeaf ? tile.cornerRadius : group.cornerRadius;
rect.zIndex = [0, depth, isHighlight ? 1 : 0];
const onlyLeaves = node.parent?.children.every((n) => n.children.length === 0);
const parentBbox = node.parent == null ? void 0 : node.parent.bbox;
const parentPadding = node.parent == null ? void 0 : node.parent.padding;
if (onlyLeaves === true && parentBbox != null && parentPadding != null) {
rect.clipBBox = bbox;
rect.x = parentBbox.x + parentPadding.left;
rect.y = parentBbox.y + parentPadding.top;
rect.width = parentBbox.width - (parentPadding.left + parentPadding.right);
rect.height = parentBbox.height - (parentPadding.top + parentPadding.bottom);
} else {
rect.clipBBox = void 0;
rect.x = bbox.x;
rect.y = bbox.y;
rect.width = bbox.width;
rect.height = bbox.height;
}
rect.visible = true;
};
this.datumSelection.each((rect, datum) => updateRectFn(datum, rect, false));
this.highlightSelection.each((rect, datum) => {
updateRectFn(datum, rect, true);
});
const updateLabelFn = (node, text2, tag, highlighted) => {
const isLeaf = node.children.length === 0;
const label = tag === 0 /* Primary */ ? node.label : node.secondaryLabel;
if (label == null) {
text2.visible = false;
return;
}
let labelProps;
let labelPath;
if (tag === 0 /* Primary */) {
labelProps = isLeaf ? tile.label : group.label;
labelPath = ["series", `${this.declarationOrder}`, isLeaf ? "tile" : "group", "label"];
} else {
labelProps = tile.secondaryLabel;
labelPath = ["series", `${this.declarationOrder}`, "tile", "secondaryLabel"];
}
const { opacity: highlightOpacity } = this.getItemStyle(node, isLeaf, highlighted) ?? {};
const params = {
childrenKey: this.properties.childrenKey,
colorKey: this.properties.colorKey,
colorName: this.properties.colorName ?? this.properties.colorKey,
depth: node.depth ?? Number.NaN,
labelKey: this.properties.labelKey,
secondaryLabelKey: this.properties.secondaryLabelKey,
sizeKey: this.properties.sizeKey,
sizeName: this.properties.sizeName ?? this.properties.sizeKey
};
const activeHighlight = this.ctx.highlightManager?.getActiveHighlight();
const style = getLabelStyles8(this, node, params, labelProps, highlighted, activeHighlight, labelPath);
text2.text = label.text;
text2.fontSize = label.fontSize;
text2.lineHeight = label.lineHeight;
text2.fontStyle = label.fontStyle;
text2.fontFamily = label.fontFamily;
text2.fontWeight = label.fontWeight;
text2.fillOpacity = highlightOpacity ?? 1;
text2.fill = style.color;
text2.setBoxing(style);
text2.textAlign = label.textAlign;
text2.textBaseline = label.verticalAlign;
text2.x = label.x;
text2.y = label.y;
text2.visible = true;
text2.zIndex = 1;
};
const highlightedDatum = this.getActiveHighlightNode();
for (const text2 of this.labelSelection.selectByClass(Text10)) {
const datum = text2.closestDatum();
updateLabelFn(datum, text2, text2.tag, datum === highlightedDatum);
}
}
getGroupHighlightState(isHighlight, highlightedNode, nodeDatum) {
const nodeIndex = nodeDatum.datumIndex;
const highlightedIndex = highlightedNode?.datumIndex;
const isDescendant = this.isDescendantDatumIndex(nodeIndex, highlightedIndex);
if (nodeDatum.children?.length === 0) {
if (nodeIndex == null || highlightedNode == null || highlightedNode.children?.length === 0) {
return HierarchyHighlightState.None;
}
return isDescendant ? HierarchyHighlightState.Item : HierarchyHighlightState.OtherItem;
}
if (highlightedNode == null || highlightedNode.children?.length === 0) {
return HierarchyHighlightState.None;
}
const isSibling = nodeDatum.depth != null && highlightedNode.depth != null && nodeDatum.depth === highlightedNode.depth;
if (isDescendant && !isSibling) {
return HierarchyHighlightState.None;
}
return isHighlight ? HierarchyHighlightState.Item : HierarchyHighlightState.OtherItem;
}
getTileHighlightStyle(tileHighlightState, groupHighlightState, highlightedNode) {
const isGroupHighlighted = highlightedNode?.children && highlightedNode.children.length > 0;
if (isGroupHighlighted) {
const groupStyle = this.getGroupHighlightStyle(groupHighlightState);
if (groupStyle?.fillOpacity == null && groupStyle?.strokeOpacity == null) {
return void 0;
}
return { fillOpacity: groupStyle.fillOpacity, strokeOpacity: groupStyle.strokeOpacity };
}
return this.getHierarchyHighlightStyles(tileHighlightState, this.properties.tile.highlight);
}
getGroupHighlightStyle(highlightState) {
const { highlight } = this.properties.group;
switch (highlightState) {
case HierarchyHighlightState.Item:
return highlight.highlightedItem;
case HierarchyHighlightState.OtherItem:
return highlight.unhighlightedItem;
default:
return void 0;
}
}
getHighlightStateString(_datum, isHighlight, datumIndex) {
if (datumIndex == null) {
return toHierarchyHighlightString2(HierarchyHighlightState.None);
}
const nodeDatum = datumIndex.reduce((node, idx) => node?.children[idx], this.rootNode);
const highlightedNode = this.getActiveHighlightNode();
if (nodeDatum == null) {
return toHierarchyHighlightString2(HierarchyHighlightState.None);
}
const isLeaf = (nodeDatum.children?.length ?? 0) === 0;
if (isLeaf) {
const tileState = this.getHierarchyHighlightState(isHighlight ?? false, highlightedNode, nodeDatum);
return toHierarchyHighlightString2(tileState);
}
const groupState = this.getGroupHighlightState(isHighlight ?? false, highlightedNode, nodeDatum);
return toHierarchyHighlightString2(groupState);
}
isDescendantDatumIndex(nodeIndex, ancestorIndex) {
if (ancestorIndex == null || ancestorIndex.length === 0) {
return true;
}
if (nodeIndex == null || nodeIndex.length < ancestorIndex.length) {
return false;
}
for (let i = 0; i < ancestorIndex.length; i += 1) {
if (nodeIndex[i] !== ancestorIndex[i]) {
return false;
}
}
return true;
}
pickNodesExactShape(point) {
const nodes = super.pickNodesExactShape(point);
nodes.sort((a, b) => b.datumIndex.length - a.datumIndex.length);
return nodes;
}
pickNodeClosestDatum(point) {
const exactMatch = this.pickNodesExactShape(point);
if (exactMatch.length !== 0) {
return { datum: exactMatch[0], distance: 0 };
}
return this.pickNodeNearestDistantObject(point, this.datumSelection.nodes());
}
getTooltipContent(datumIndex) {
const { id: seriesId, properties, ctx } = this;
const { formatManager } = ctx;
const { labelKey, secondaryLabelKey, childrenKey, sizeKey, sizeName, colorKey, colorName, tooltip } = properties;
const nodeDatum = datumIndex.reduce((n, i) => n?.children[i], this.rootNode);
if (nodeDatum == null)
return;
const { datum, depth, children } = nodeDatum;
if (datum == null || depth == null)
return;
const isLeaf = children.length === 0;
const data = [];
const datumSize = sizeKey == null ? void 0 : datum[sizeKey];
if (datumSize != null) {
const sizeDomain = [0, this.rootNode?.sumSize ?? 0];
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: datumSize,
datum,
seriesId,
legendItemName: void 0,
key: sizeKey,
source: "tooltip",
property: "size",
boundSeries: this.getFormatterContext("size"),
domain: sizeDomain,
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: sizeName, fallbackLabel: sizeKey, value: content ?? formatValue3(datumSize) });
}
const datumColor = colorKey == null ? void 0 : datum[colorKey];
if (datumColor != null) {
const { colorDomain } = this;
const content = formatManager.format(this.callWithContext.bind(this), {
type: "number",
value: datumColor,
datum,
seriesId,
legendItemName: void 0,
key: colorKey,
source: "tooltip",
property: "color",
boundSeries: this.getFormatterContext("color"),
domain: colorDomain,
fractionDigits: void 0,
visibleDomain: void 0
});
data.push({ label: colorName, fallbackLabel: colorKey, value: content ?? formatValue3(datumColor) });
}
const format = this.getItemStyle(
{ ...nodeDatum, colorValue: datumColor ?? nodeDatum.colorValue },
isLeaf,
false
);
const color7 = format.fill;
const markerStyle = {
shape: "square",
fill: color7,
fillOpacity: 1,
stroke: void 0,
strokeWidth: 0,
strokeOpacity: 1,
lineDash: [0],
lineDashOffset: 0
};
if (isGradientFill5(markerStyle.fill)) {
markerStyle.fill = { ...markerStyle.fill, gradient: "linear", rotation: 0, reverse: false };
}
const symbol = isLeaf ? { marker: markerStyle } : void 0;
return this.formatTooltipWithContext(
tooltip,
{
title: labelKey == null ? void 0 : datum[labelKey],
symbol,
data
},
{
seriesId,
datum,
title: void 0,
depth,
labelKey,
secondaryLabelKey,
childrenKey,
sizeKey,
sizeName,
colorKey,
colorName,
...format
}
);
}
computeFocusBounds(node) {
return Transformable6.toCanvas(this.contentGroup, node.getBBox());
}
hasItemStylers() {
return this.properties.itemStyler != null || this.properties.tile.label.itemStyler != null || this.properties.group.label.itemStyler != null;
}
};
TreemapSeries.className = "TreemapSeries";
TreemapSeries.type = "treemap";
// packages/ag-charts-enterprise/src/series/treemap/treemapSeriesOptionsDef.ts
import { _ModuleSupport as _ModuleSupport212 } from "ag-charts-community";
import {
arrayOf as arrayOf5,
color as color6,
commonSeriesOptionsDefs as commonSeriesOptionsDefs23,
constant as constant24,
required as required24,
string as string24,
undocumented as undocumented18,
without as without10
} from "ag-charts-core";
var { treemapSeriesThemeableOptionsDef } = _ModuleSupport212;
var treemapSeriesOptionsDef = {
...treemapSeriesThemeableOptionsDef,
...without10(commonSeriesOptionsDefs23, ["highlightStyle", "highlight", "showInLegend"]),
type: required24(constant24("treemap")),
labelKey: string24,
secondaryLabelKey: string24,
childrenKey: string24,
sizeKey: string24,
colorKey: string24,
sizeName: string24,
colorName: string24
};
treemapSeriesOptionsDef.undocumentedGroupFills = undocumented18(arrayOf5(color6));
treemapSeriesOptionsDef.undocumentedGroupStrokes = undocumented18(arrayOf5(color6));
// packages/ag-charts-enterprise/src/series/treemap/treemapModule.ts
var TreemapSeriesModule = {
type: "series",
name: "treemap",
chartType: "standalone",
enterprise: true,
solo: true,
version: VERSION50,
dependencies: [StandaloneChartModule],
options: treemapSeriesOptionsDef,
themeTemplate: {
series: {
fills: {
$applyCycle: [
{ $size: { $path: ["./data", { $path: "/data" }] } },
{ $palette: "fills" },
{
$applySwitch: [
{ $path: ["/type", void 0, { $value: "$1" }] },
{ $value: "$1" },
["gradient", FILL_GRADIENT_LINEAR_DEFAULTS9],
["pattern", FILL_PATTERN_DEFAULTS14],
["image", FILL_IMAGE_DEFAULTS19]
]
}
]
},
strokes: {
$applyCycle: [{ $size: { $path: ["./data", { $path: "/data" }] } }, { $palette: "strokes" }]
},
colorRange: { $palette: "divergingColors" },
undocumentedGroupFills: { $palette: "hierarchyColors" },
undocumentedGroupStrokes: { $palette: "secondHierarchyColors" },
group: {
label: {
...LABEL_BOXING_DEFAULTS20,
enabled: true,
color: { $ref: "textColor" },
fontStyle: void 0,
fontWeight: { $ref: "fontWeight" },
fontSize: { $ref: "fontSize" },
fontFamily: { $ref: "fontFamily" },
spacing: 4
},
fill: void 0,
// Override default fill
stroke: void 0,
// Override default stroke
strokeWidth: 1,
padding: 4,
gap: 2,
textAlign: "left",
highlight: {
unhighlightedItem: {
opacity: 0.2,
fillOpacity: 0.2,
strokeOpacity: 0.2
}
}
},
tile: {
label: {
...LABEL_BOXING_DEFAULTS20,
enabled: true,
color: { $ref: "chartBackgroundColor" },
fontStyle: void 0,
fontWeight: { $ref: "fontWeight" },
fontSize: { $rem: 1.5 },
minimumFontSize: { $rem: FONT_SIZE_RATIO5.SMALLER },
fontFamily: { $ref: "fontFamily" },
wrapping: "on-space",
overflowStrategy: "ellipsis",
spacing: 2
},
secondaryLabel: {
...LABEL_BOXING_DEFAULTS20,
enabled: true,
color: { $ref: "chartBackgroundColor" },
fontStyle: void 0,
fontWeight: void 0,
fontSize: { $ref: "fontSize" },
minimumFontSize: { $rem: FONT_SIZE_RATIO5.SMALLER },
fontFamily: { $ref: "fontFamily" },
wrapping: "never",
overflowStrategy: "ellipsis"
},
fill: void 0,
// Override default fill
stroke: void 0,
// Override default stroke
strokeWidth: { $isUserOption: ["../strokes/0", 2, { $isUserOption: ["./stroke", 2, 0] }] },
padding: 3,
gap: 1,
highlight: {
unhighlightedItem: {
fillOpacity: 0.6,
strokeOpacity: 0.6
},
unhighlightedBranch: {
fillOpacity: 0.2,
strokeOpacity: 0.2
}
}
}
},
gradientLegend: {
enabled: { $if: [{ $path: "../series/0/colorKey" }, true, false] }
}
},
create: (ctx) => new TreemapSeries(ctx)
};
// packages/ag-charts-enterprise/src/module-bundles/all.ts
import { AllCommunityModule } from "ag-charts-community";
// packages/ag-charts-enterprise/src/module-bundles/cartesian-axes.ts
import { AllCartesianAxesModule as AllCommunityCartesianAxesModule } from "ag-charts-community";
var AllCartesianAxesModule = [
AllCommunityCartesianAxesModule,
OrdinalTimeAxisModule
].flat();
// packages/ag-charts-enterprise/src/module-bundles/cartesian-series.ts
import { AllCartesianSeriesModule as AllCommunityCartesianSeriesModule } from "ag-charts-community";
var AllCartesianSeriesModule = [
AllCommunityCartesianSeriesModule,
BoxPlotSeriesModule,
CandlestickSeriesModule,
ConeFunnelSeriesModule,
FunnelSeriesModule,
HeatmapSeriesModule,
OhlcSeriesModule,
RangeAreaSeriesModule,
RangeBarSeriesModule,
WaterfallSeriesModule
].flat();
// packages/ag-charts-enterprise/src/module-bundles/cartesian.ts
var AllCartesianModule = [
AllCartesianAxesModule,
AllCartesianSeriesModule,
AnimationModule,
AnnotationsModule,
BandHighlightModule,
ChartToolbarModule,
ContextMenuModule,
CrosshairModule,
DataSourceModule,
ErrorBarsModule,
FlashOnUpdateModule,
GradientLegendModule,
NavigatorModule,
RangesModule,
ScrollbarModule,
StatusBarModule,
SyncModule,
ZoomModule
].flat();
// packages/ag-charts-enterprise/src/module-bundles/financial.ts
import { BarSeriesModule as BarSeriesModule2, LineSeriesModule as LineSeriesModule2, NumberAxisModule, TimeAxisModule } from "ag-charts-community";
// packages/ag-charts-enterprise/src/preset/priceVolumePresetModules.ts
import { VERSION as VERSION51 } from "ag-charts-community";
import {
array as array3,
boolean as boolean20,
commonChartOptionsDefs as commonChartOptionsDefs2,
defined as defined2,
positiveNumber as positiveNumber10,
string as string25,
tooltipOptionsDefs as tooltipOptionsDefs2,
undocumented as undocumented19,
union as union5
} from "ag-charts-core";
// packages/ag-charts-enterprise/src/preset/priceVolumePreset.ts
import "ag-charts-community";
import { Logger as Logger23, SAFE_STROKE_FILL_OPERATION as SAFE_STROKE_FILL_OPERATION5, mergeDefaults as mergeDefaults25 } from "ag-charts-core";
// packages/ag-charts-enterprise/src/preset/priceVolumePresetTheme.ts
import * as ThemeSymbols2 from "ag-charts-core";
import { FONT_SIZE_RATIO as FONT_SIZE_RATIO6 } from "ag-charts-core";
var {
DEFAULT_ANNOTATION_HANDLE_FILL: DEFAULT_ANNOTATION_HANDLE_FILL2,
DEFAULT_ANNOTATION_STATISTICS_COLOR: DEFAULT_ANNOTATION_STATISTICS_COLOR2,
DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE: DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE2,
DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL: DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL2,
DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE: DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE2,
DEFAULT_ANNOTATION_STATISTICS_FILL: DEFAULT_ANNOTATION_STATISTICS_FILL2,
DEFAULT_ANNOTATION_STATISTICS_STROKE: DEFAULT_ANNOTATION_STATISTICS_STROKE2,
DEFAULT_FIBONACCI_STROKES: DEFAULT_FIBONACCI_STROKES2,
DEFAULT_FINANCIAL_CHARTS_ANNOTATION_BACKGROUND_FILL: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_BACKGROUND_FILL2,
DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR2,
DEFAULT_TEXTBOX_COLOR: DEFAULT_TEXTBOX_COLOR2,
DEFAULT_TEXTBOX_FILL: DEFAULT_TEXTBOX_FILL2,
DEFAULT_TEXTBOX_STROKE: DEFAULT_TEXTBOX_STROKE2,
DEFAULT_TEXT_ANNOTATION_COLOR
} = ThemeSymbols2;
var stroke2 = {
stroke: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR2
};
var handle2 = {
fill: DEFAULT_ANNOTATION_HANDLE_FILL2
};
var axisLabel2 = {
color: "white",
fill: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR2
};
var lineText2 = {
color: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR2
};
var font2 = {
color: DEFAULT_TEXT_ANNOTATION_COLOR,
fontSize: { $rem: FONT_SIZE_RATIO6.LARGE },
fontFamily: { $ref: "fontFamily" }
};
var measurerStatistics2 = {
...font2,
fontSize: { $ref: "fontSize" },
color: DEFAULT_ANNOTATION_STATISTICS_COLOR2,
fill: DEFAULT_ANNOTATION_STATISTICS_FILL2,
stroke: DEFAULT_ANNOTATION_STATISTICS_STROKE2,
strokeWidth: 1,
divider: {
stroke: DEFAULT_ANNOTATION_STATISTICS_DIVIDER_STROKE2,
strokeWidth: 1,
strokeOpacity: 0.5
}
};
var measurer2 = {
...stroke2,
background: {
fill: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_BACKGROUND_FILL2,
fillOpacity: 0.2
},
handle: { ...handle2 },
text: { ...lineText2 },
statistics: { ...measurerStatistics2 }
};
var annotationsTheme2 = {
// Lines
line: {
...stroke2,
handle: { ...handle2 },
text: { ...lineText2 }
},
"horizontal-line": {
...stroke2,
handle: { ...handle2 },
axisLabel: { ...axisLabel2 },
text: { ...lineText2 }
},
"vertical-line": {
...stroke2,
handle: { ...handle2 },
axisLabel: { ...axisLabel2 },
text: { ...lineText2 }
},
// Channels
"disjoint-channel": {
...stroke2,
background: {
fill: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_BACKGROUND_FILL2,
fillOpacity: 0.2
},
handle: { ...handle2 },
text: { ...lineText2 }
},
"parallel-channel": {
...stroke2,
background: {
fill: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_BACKGROUND_FILL2,
fillOpacity: 0.2
},
handle: { ...handle2 },
text: { ...lineText2 }
},
// Fibonnaccis
"fibonacci-retracement": {
...stroke2,
strokes: DEFAULT_FIBONACCI_STROKES2,
rangeStroke: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR2,
handle: { ...handle2 },
text: { ...lineText2, position: "center" },
label: {
...font2,
color: void 0,
fontSize: { $rem: FONT_SIZE_RATIO6.SMALLER }
}
},
"fibonacci-retracement-trend-based": {
...stroke2,
strokes: DEFAULT_FIBONACCI_STROKES2,
rangeStroke: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR2,
handle: { ...handle2 },
text: { ...lineText2, position: "center" },
label: {
...font2,
color: void 0,
fontSize: { $rem: FONT_SIZE_RATIO6.SMALLER }
}
},
// Texts
callout: {
...stroke2,
...font2,
color: { $ref: "textColor" },
handle: { ...handle2 },
fill: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_BACKGROUND_FILL2,
fillOpacity: 0.2
},
comment: {
...font2,
color: "white",
fontWeight: 700,
handle: { ...handle2 },
fill: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR2
},
note: {
...font2,
color: DEFAULT_TEXTBOX_COLOR2,
fill: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR2,
stroke: { $ref: "chartBackgroundColor" },
strokeWidth: 1,
strokeOpacity: 1,
handle: { ...handle2 },
background: {
fill: DEFAULT_TEXTBOX_FILL2,
stroke: DEFAULT_TEXTBOX_STROKE2,
strokeWidth: 1
}
},
text: {
...font2,
handle: { ...handle2 }
},
// Shapes
arrow: {
...stroke2,
handle: { ...handle2 },
text: { ...lineText2 }
},
"arrow-up": {
fill: { $palette: "up.fill" },
handle: { ...handle2, stroke: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR2 }
},
"arrow-down": {
fill: { $palette: "down.fill" },
handle: { ...handle2, stroke: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_COLOR2 }
},
// Measurers
"date-range": {
...measurer2
},
"price-range": {
...measurer2
},
"date-price-range": {
...measurer2
},
"quick-date-price-range": {
up: {
...stroke2,
fill: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_BACKGROUND_FILL2,
fillOpacity: 0.2,
handle: { ...handle2 },
statistics: {
...measurerStatistics2,
color: "#fff",
fill: DEFAULT_FINANCIAL_CHARTS_ANNOTATION_BACKGROUND_FILL2,
strokeWidth: 0,
divider: {
stroke: "#fff",
strokeWidth: 1,
strokeOpacity: 0.5
}
}
},
down: {
...stroke2,
stroke: DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE2,
fill: DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL2,
fillOpacity: 0.2,
handle: {
...handle2,
stroke: DEFAULT_ANNOTATION_STATISTICS_DOWN_STROKE2
},
statistics: {
...measurerStatistics2,
color: "#fff",
fill: DEFAULT_ANNOTATION_STATISTICS_DOWN_FILL2,
strokeWidth: 0,
divider: {
stroke: "#fff",
strokeWidth: 1,
strokeOpacity: 0.5
}
}
}
},
axesButtons: {
enabled: true
}
};
// packages/ag-charts-enterprise/src/preset/priceVolumePreset.ts
var chartTypes = ["ohlc", "line", "step-line", "hlc", "high-low", "candlestick", "hollow-candlestick"];
var toolbarButtons = [
{
icon: "trend-line-drawing",
tooltip: "toolbarAnnotationsLineAnnotations",
value: "line-menu"
},
{
icon: "fibonacci-retracement-drawing",
tooltip: "toolbarAnnotationsFibonacciAnnotations",
value: "fibonacci-menu"
},
{
icon: "text-annotation",
tooltip: "toolbarAnnotationsTextAnnotations",
value: "text-menu"
},
{
icon: "arrow-drawing",
tooltip: "toolbarAnnotationsShapeAnnotations",
value: "shape-menu"
},
{
icon: "measurer-drawing",
tooltip: "toolbarAnnotationsMeasurerAnnotations",
value: "measurer-menu"
},
{
icon: "delete",
tooltip: "toolbarAnnotationsClearAll",
value: "clear"
}
];
function priceVolume(opts, _presetTheme, getTheme) {
const {
dateKey = "date",
highKey = "high",
openKey = "open",
lowKey = "low",
closeKey = "close",
volumeKey = "volume",
chartType = "candlestick",
navigator = false,
volume = true,
rangeButtons = true,
statusBar = true,
toolbar: toolbar2 = true,
zoom = true,
sync = false,
theme,
data,
formatter,
...unusedOpts
} = opts;
const priceSeries = createPriceSeries(chartType, dateKey, highKey, lowKey, openKey, closeKey);
const volumeSeries = createVolumeSeries(getTheme, dateKey, openKey, closeKey, volume, volumeKey);
const miniChart = volume ? {
miniChart: {
enabled: navigator,
series: [
{
type: "line",
xKey: dateKey,
yKey: volumeKey,
stroke: SAFE_STROKE_FILL_OPERATION5,
marker: { enabled: false }
}
]
},
height: 40,
minHandle: {
height: 46
},
maxHandle: {
height: 46
}
} : null;
const navigatorOpts = {
navigator: {
enabled: navigator,
...miniChart
}
};
const annotationOpts = {
annotations: {
enabled: toolbar2,
optionsToolbar: {
enabled: toolbar2
},
// @ts-expect-error undocumented option
snap: true,
toolbar: {
enabled: toolbar2,
buttons: toolbarButtons,
padding: 0
},
data,
xKey: dateKey,
volumeKey: volume ? volumeKey : void 0
}
};
const statusBarOpts = statusBar ? {
statusBar: {
enabled: true,
highKey,
openKey,
lowKey,
closeKey,
volumeKey: volume ? volumeKey : void 0
}
} : null;
const zoomOpts = {
zoom: {
enabled: zoom,
autoScaling: {
enabled: true
},
onDataChange: {
stickToEnd: true
},
// @ts-expect-error undocumented option
enableIndependentAxes: true
}
};
const toolbarOpts = {
ranges: {
enabled: rangeButtons
}
};
const syncGroup = sync ? {
sync: {
enabled: sync,
nodeInteraction: true,
zoom: true
}
} : null;
const volumeAxis = volume ? {
yVolume: {
type: "number",
position: "left",
label: { enabled: false },
crosshair: { enabled: false },
gridLine: { enabled: false },
nice: false,
// @ts-expect-error undocumented option
layoutConstraints: {
stacked: false,
width: 20,
unit: "percent",
align: "end"
}
}
} : {};
return {
theme: {
baseTheme: typeof theme === "string" ? theme : "ag-financial",
...mergeDefaults25(typeof theme === "object" ? theme : null, {
overrides: {
common: {
title: { padding: 4 },
padding: {
top: 6,
right: 8,
bottom: 6
},
chartToolbar: {
enabled: toolbar2
},
annotations: { ...annotationsTheme2 },
axes: {
number: {
interval: { maxSpacing: 45 },
label: { format: ".2f" }
},
category: {
gridLine: { enabled: true }
},
time: {
gridLine: { enabled: true }
},
"unit-time": {
gridLine: { enabled: true }
},
"ordinal-time": {
gridLine: { enabled: true }
}
}
},
bar: {
series: {
fillOpacity: 0.5,
highlight: { unhighlightedItem: { opacity: 1 }, unhighlightedSeries: { opacity: 1 } }
}
},
line: {
series: {
marker: { enabled: false },
highlight: { unhighlightedSeries: { opacity: 1 } },
...inlineSwitch(chartType, {
hlc: {
stroke: { $palette: "altNeutral.stroke" },
strokeWidth: 2
},
line: {
stroke: { $palette: "neutral.stroke" }
},
"step-line": {
stroke: { $palette: "neutral.stroke" },
interpolation: { type: "step" }
}
})
}
},
candlestick: {
series: {
highlight: { unhighlightedItem: { opacity: 1 }, unhighlightedSeries: { opacity: 1 } },
...inlineSwitch(chartType, {
"hollow-candlestick": {
item: {
up: { fill: "transparent" }
}
}
})
}
},
ohlc: {
series: {
highlight: { unhighlightedItem: { opacity: 1 }, unhighlightedSeries: { opacity: 1 } }
}
},
"range-area": {
series: {
fillOpacity: 0.3,
strokeWidth: 2,
highlight: {
bringToFront: false,
unhighlightedItem: { opacity: 1 },
unhighlightedSeries: { opacity: 1 }
},
...inlineSwitch(chartType, {
hlc: {
fill: {
$if: [
{ $eq: [{ $value: "$index" }, 1] },
{ $palette: "up.fill" },
{ $palette: "down.fill" }
]
},
stroke: {
$if: [
{ $eq: [{ $value: "$index" }, 1] },
{ $palette: "up.stroke" },
{ $palette: "down.stroke" }
]
}
}
})
}
},
"range-bar": {
series: {
highlight: {
unhighlightedItem: { opacity: 1 },
unhighlightedSeries: { opacity: 1 }
},
...inlineSwitch(chartType, {
"high-low": {
fill: { $palette: "neutral.fill" },
stroke: { $palette: "neutral.stroke" }
}
})
}
}
}
})
},
animation: { enabled: false },
legend: { enabled: false },
series: [...volumeSeries, ...priceSeries],
axes: {
y: {
type: "number",
position: "right",
crosshair: {
enabled: true,
snap: false
},
// @ts-expect-error undocumented option
layoutConstraints: {
stacked: false,
width: 100,
unit: "percent",
align: "start"
}
},
...volumeAxis,
x: {
type: "ordinal-time",
position: "bottom",
line: {
enabled: false
},
label: {
enabled: true
},
crosshair: {
enabled: true
}
}
},
tooltip: { enabled: false },
data,
formatter,
...annotationOpts,
...navigatorOpts,
...statusBarOpts,
...zoomOpts,
...toolbarOpts,
...syncGroup,
...unusedOpts
};
}
function createVolumeSeries(getTheme, xKey, openKey, closeKey, volume, volumeKey) {
if (!volume)
return [];
return [
{
type: "bar",
xKey,
yKey: volumeKey,
yKeyAxis: "yVolume",
tooltip: { enabled: false },
// @ts-expect-error undocumented options: simpleItemStyler, focusPriority
simpleItemStyler(datum) {
const { up, down } = getTheme().palette;
return { fill: datum[openKey] < datum[closeKey] ? up?.fill : down?.fill };
},
focusPriority: 1,
highlight: { unhighlightedSeries: { opacity: 1 } }
}
];
}
var RANGE_AREA_TYPE = "range-area";
function createPriceSeries(chartType, xKey, highKey, lowKey, openKey, closeKey) {
const keys = {
xKey,
openKey,
closeKey,
highKey,
lowKey
};
const singleKeys = {
xKey,
yKey: closeKey
};
const common = {
pickOutsideVisibleMinorAxis: true
};
switch (chartType ?? "candlestick") {
case "ohlc":
return createPriceSeriesOHLC(common, keys);
case "line":
case "step-line":
return createPriceSeriesLine(common, singleKeys);
case "hlc":
return createPriceSeriesHLC(common, singleKeys, keys);
case "high-low":
return createPriceSeriesHighLow(common, keys);
case "candlestick":
case "hollow-candlestick":
return createPriceSeriesCandlestick(common, keys);
default:
Logger23.warnOnce(`unknown chart type: ${chartType}; expected one of: ${chartTypes.join(", ")}`);
return createPriceSeriesCandlestick(common, keys);
}
}
function createPriceSeriesOHLC(common, keys) {
return [
{
type: "ohlc",
// @ts-expect-error undocumented option
focusPriority: 0,
...common,
...keys
}
];
}
function createPriceSeriesLine(common, singleKeys) {
return [
{
type: "line",
// @ts-expect-error undocumented option
focusPriority: 0,
...common,
...singleKeys
}
];
}
function createPriceSeriesHLC(common, singleKeys, { xKey, highKey, closeKey, lowKey }) {
return [
{
type: RANGE_AREA_TYPE,
// @ts-expect-error undocumented option
focusPriority: 0,
...common,
xKey,
yHighKey: highKey,
yLowKey: closeKey
},
{
type: RANGE_AREA_TYPE,
// @ts-expect-error undocumented option
focusPriority: 0,
...common,
xKey,
yHighKey: closeKey,
yLowKey: lowKey
},
{
type: "line",
...common,
...singleKeys
}
];
}
function createPriceSeriesHighLow(common, { xKey, highKey, lowKey }) {
return [
{
type: "range-bar",
...common,
xKey,
yHighKey: highKey,
yLowKey: lowKey,
tooltip: { range: "nearest" },
// @ts-expect-error undocumented option
focusPriority: 0
}
];
}
function createPriceSeriesCandlestick(common, keys) {
return [
{
type: "candlestick",
// @ts-expect-error undocumented option
focusPriority: 0,
...common,
...keys
}
];
}
function inlineSwitch(caseName, switchCases) {
return switchCases[caseName] ?? switchCases.default;
}
// packages/ag-charts-enterprise/src/preset/priceVolumePresetModules.ts
var priceVolumeOptionsDef = {
chartType: union5("candlestick", "hollow-candlestick", "ohlc", "line", "step-line", "hlc", "high-low"),
dateKey: string25,
openKey: string25,
highKey: string25,
lowKey: string25,
closeKey: string25,
volumeKey: string25,
navigator: boolean20,
volume: boolean20,
rangeButtons: boolean20,
statusBar: boolean20,
toolbar: boolean20,
zoom: boolean20,
sync: boolean20,
// Valid pass-through options
theme: defined2,
container: defined2,
width: defined2,
height: defined2,
minWidth: defined2,
minHeight: defined2,
listeners: defined2,
initialState: defined2,
title: defined2,
data: array3,
formatter: defined2
};
var commonGaugeOptions2 = {
// Valid pass-through options
theme: defined2,
container: defined2,
animation: defined2,
background: defined2,
contextMenu: defined2,
context: () => true,
listeners: defined2,
locale: defined2,
width: defined2,
height: defined2,
minWidth: defined2,
minHeight: defined2,
title: defined2,
subtitle: defined2,
footnote: defined2,
padding: defined2,
tooltip: {
...tooltipOptionsDefs2,
...commonChartOptionsDefs2.tooltip
}
};
commonGaugeOptions2.overrideDevicePixelRatio = undocumented19(positiveNumber10);
var PriceVolumePresetModule = {
type: "preset",
name: "price-volume",
enterprise: true,
dependencies: [ChartToolbarModule, StatusBarModule],
version: VERSION51,
options: priceVolumeOptionsDef,
create: priceVolume
};
// packages/ag-charts-enterprise/src/module-bundles/financial.ts
var FinancialChartModule = [
PriceVolumePresetModule,
BarSeriesModule2,
LineSeriesModule2,
CandlestickSeriesModule,
OhlcSeriesModule,
RangeBarSeriesModule,
RangeAreaSeriesModule,
AnimationModule,
AnnotationsModule,
BandHighlightModule,
ChartToolbarModule,
ContextMenuModule,
CrosshairModule,
DataSourceModule,
ErrorBarsModule,
GradientLegendModule,
NavigatorModule,
RangesModule,
SyncModule,
ZoomModule,
OrdinalTimeAxisModule,
TimeAxisModule,
NumberAxisModule
];
// packages/ag-charts-enterprise/src/module-bundles/gauge.ts
var AllGaugeModule = [LinearGaugeModule, RadialGaugeModule];
// packages/ag-charts-enterprise/src/module-bundles/polar.ts
import { AllPolarModule as AllCommunityPolarModule } from "ag-charts-community";
var AllPolarModule = [
AllCommunityPolarModule,
AngleNumberAxisModule,
AngleCategoryAxisModule,
RadiusNumberAxisModule,
RadiusCategoryAxisModule,
NightingaleSeriesModule,
RadarAreaSeriesModule,
RadarLineSeriesModule,
RadialBarSeriesModule,
RadialColumnSeriesModule,
AnimationModule,
ContextMenuModule,
DataSourceModule,
GradientLegendModule
].flat();
// packages/ag-charts-enterprise/src/module-bundles/topology.ts
var AllMapSeriesModule = [
MapLineSeriesModule,
MapLineBackgroundSeriesModule,
MapMarkerSeriesModule,
MapShapeSeriesModule,
MapShapeBackgroundSeriesModule
];
// packages/ag-charts-enterprise/src/module-bundles/all.ts
var AllEnterpriseModule = [
AllCommunityModule,
AllCartesianModule,
AllPolarModule,
AllMapSeriesModule,
AllGaugeModule,
FinancialChartModule,
ChordSeriesModule,
PyramidSeriesModule,
SankeySeriesModule,
SunburstSeriesModule,
TreemapSeriesModule
].flat();
// packages/ag-charts-enterprise/src/module-bundles/integrated.ts
import { AgCharts, ModuleRegistry as ModuleRegistry2, VERSION as VERSION52, _Scene, _Theme as _Theme2, _Util } from "ag-charts-community";
// packages/ag-charts-enterprise/src/setup.ts
import "ag-charts-community";
import { ModuleRegistry, enterpriseRegistry } from "ag-charts-core";
function setupEnterpriseModules() {
ModuleRegistry.registerModules(AllEnterpriseModule);
enterpriseRegistry.styles = styles_default;
enterpriseRegistry.licenseManager = (options) => new LicenseManager(
options.container?.ownerDocument ?? (typeof document === "undefined" ? void 0 : document)
);
enterpriseRegistry.injectWatermark = injectWatermark;
enterpriseRegistry.createBackground = (ctx) => new Background(ctx);
enterpriseRegistry.createForeground = (ctx) => new Foreground(ctx);
}
// packages/ag-charts-enterprise/src/module-bundles/integrated.ts
var LicenseManager2 = {
setLicenseKey(key) {
LicenseManager.setLicenseKey(key);
}
};
var AgChartsEnterpriseModule = {
VERSION: VERSION52,
_Scene,
_Theme: _Theme2,
_Util,
create: AgCharts.create.bind(AgCharts),
createSparkline: AgCharts.__createSparkline.bind(AgCharts),
setup: () => {
ModuleRegistry2.setRegistryMode(ModuleRegistry2.RegistryMode.Integrated);
setupEnterpriseModules();
},
setGridContext: LicenseManager.setGridContext.bind(LicenseManager),
setLicenseKey: LicenseManager.setLicenseKey.bind(LicenseManager),
isEnterprise: true
};
// packages/ag-charts-enterprise/src/main.ts
ModuleRegistry3.setRegistryMode(ModuleRegistry3.RegistryMode.Enterprise);
enterpriseRegistry2.styles = styles_default;
enterpriseRegistry2.licenseManager = (options) => new LicenseManager(options.container?.ownerDocument ?? (typeof document === "undefined" ? void 0 : document));
enterpriseRegistry2.injectWatermark = injectWatermark;
enterpriseRegistry2.createBackground = (ctx) => new Background(ctx);
enterpriseRegistry2.createForeground = (ctx) => new Foreground(ctx);
export {
AgChartsEnterpriseModule,
AgTooltipAnchorToType,
AgTooltipPlacementType,
AllCartesianAxesModule,
AllCartesianModule,
AllCartesianSeriesModule,
AllEnterpriseModule,
AllGaugeModule,
AllMapSeriesModule,
AllPolarModule,
AngleCategoryAxisModule,
AngleNumberAxisModule,
AnimationModule,
AnnotationsModule,
BandHighlightModule,
BoxPlotSeriesModule,
CandlestickSeriesModule,
ChartToolbarModule,
ChordSeriesModule,
ConeFunnelSeriesModule,
ContextMenuModule,
CrosshairModule,
DataSourceModule,
ErrorBarsModule,
FinancialChartModule,
FlashOnUpdateModule,
FunnelSeriesModule,
GradientLegendModule,
HeatmapSeriesModule,
LicenseManager2 as LicenseManager,
LinearGaugeModule,
MapLineBackgroundSeriesModule,
MapLineSeriesModule,
MapMarkerSeriesModule,
MapShapeBackgroundSeriesModule,
MapShapeSeriesModule,
NavigatorModule,
NightingaleSeriesModule,
OhlcSeriesModule,
OrdinalTimeAxisModule,
PyramidSeriesModule,
RadarAreaSeriesModule,
RadarLineSeriesModule,
RadialBarSeriesModule,
RadialColumnSeriesModule,
RadialGaugeModule,
RadiusCategoryAxisModule,
RadiusNumberAxisModule,
RangeAreaSeriesModule,
RangeBarSeriesModule,
RangesModule,
SankeySeriesModule,
ScrollbarModule,
StatusBarModule,
SunburstSeriesModule,
SyncModule,
TreemapSeriesModule,
WaterfallSeriesModule,
ZoomModule
};