UNPKG

ag-charts-enterprise

Version:

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

1,379 lines (1,359 loc) 937 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); 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-modules.ts var main_modules_exports = {}; __export(main_modules_exports, { AllCartesianEnterpriseModules: () => AllCartesianEnterpriseModules, AllEnterpriseModules: () => AllEnterpriseModules, AllFlowProportionEnterpriseModules: () => AllFlowProportionEnterpriseModules, AllGaugeEnterpriseModules: () => AllGaugeEnterpriseModules, AllHierarchyEnterpriseModules: () => AllHierarchyEnterpriseModules, AllPolarEnterpriseModules: () => AllPolarEnterpriseModules, AllStandaloneEnterpriseModules: () => AllStandaloneEnterpriseModules, AllTopologyEnterpriseModules: () => AllTopologyEnterpriseModules, AngleCategoryAxisModule: () => AngleCategoryAxisModule, AngleNumberAxisModule: () => AngleNumberAxisModule, BoxPlotSeriesModule: () => BoxPlotSeriesModule, CandlestickSeriesModule: () => CandlestickSeriesModule, ChordSeriesModule: () => ChordSeriesModule, ConeFunnelSeriesModule: () => ConeFunnelSeriesModule, FlowProportionChartModule: () => FlowProportionChartModule, FunnelSeriesModule: () => FunnelSeriesModule, GaugeChartModule: () => GaugeChartModule, HeatmapSeriesModule: () => HeatmapSeriesModule, HierarchyChartModule: () => HierarchyChartModule, LinearGaugeSeriesModule: () => LinearGaugeSeriesModule, MapLineBackgroundSeriesModule: () => MapLineBackgroundSeriesModule, MapLineSeriesModule: () => MapLineSeriesModule, MapMarkerSeriesModule: () => MapMarkerSeriesModule, MapShapeBackgroundSeriesModule: () => MapShapeBackgroundSeriesModule, MapShapeSeriesModule: () => MapShapeSeriesModule, ModuleRegistry: () => ModuleRegistry, NightingaleSeriesModule: () => NightingaleSeriesModule, OhlcSeriesModule: () => OhlcSeriesModule, OrdinalTimeAxisModule: () => OrdinalTimeAxisModule, PyramidSeriesModule: () => PyramidSeriesModule, RadarAreaSeriesModule: () => RadarAreaSeriesModule, RadarLineSeriesModule: () => RadarLineSeriesModule, RadialBarSeriesModule: () => RadialBarSeriesModule, RadialColumnSeriesModule: () => RadialColumnSeriesModule, RadialGaugeSeriesModule: () => RadialGaugeSeriesModule, RadiusCategoryAxisModule: () => RadiusCategoryAxisModule, RadiusNumberAxisModule: () => RadiusNumberAxisModule, RangeAreaSeriesModule: () => RangeAreaSeriesModule, RangeBarSeriesModule: () => RangeBarSeriesModule, SankeySeriesModule: () => SankeySeriesModule, StandaloneChartModule: () => StandaloneChartModule, SunburstSeriesModule: () => SunburstSeriesModule, TopologyChartModule: () => TopologyChartModule, TreemapSeriesModule: () => TreemapSeriesModule, WaterfallSeriesModule: () => WaterfallSeriesModule }); module.exports = __toCommonJS(main_modules_exports); var import_ag_charts_community173 = require("ag-charts-community"); // packages/ag-charts-enterprise/src/axes/axisModules.ts var import_ag_charts_community13 = require("ag-charts-community"); var import_ag_charts_core8 = require("ag-charts-core"); // packages/ag-charts-enterprise/src/axes/angle-category/angleCategoryAxis.ts var import_ag_charts_community5 = require("ag-charts-community"); var import_ag_charts_core3 = require("ag-charts-core"); // packages/ag-charts-enterprise/src/utils/polar.ts function loopSymmetrically(items, step, iterator) { const loop = (start, end, loopStep, loopIterator) => { let prev = items[0]; for (let i = start; loopStep > 0 ? i <= end : i > end; i += loopStep) { const curr = items[i]; if (loopIterator(prev, curr)) return true; prev = curr; } return false; }; const midIndex = Math.floor(items.length / 2); if (loop(step, midIndex, step, iterator)) return true; return loop(items.length - step, midIndex, -step, iterator); } // packages/ag-charts-enterprise/src/axes/angle-number/angleAxisInterval.ts var import_ag_charts_community = require("ag-charts-community"); var { OR, POSITIVE_NUMBER, NAN, AxisInterval, TempValidate } = import_ag_charts_community._ModuleSupport; var AngleAxisInterval = class extends AxisInterval { }; __decorateClass([ TempValidate(OR(POSITIVE_NUMBER, NAN)) ], AngleAxisInterval.prototype, "minSpacing", 2); // packages/ag-charts-enterprise/src/axes/angle/angleAxis.ts var import_ag_charts_community4 = require("ag-charts-community"); var import_ag_charts_core2 = require("ag-charts-core"); // packages/ag-charts-enterprise/src/axes/polar-crosslines/angleCrossLine.ts var import_ag_charts_community3 = require("ag-charts-community"); var import_ag_charts_core = require("ag-charts-core"); // packages/ag-charts-enterprise/src/axes/polar-crosslines/polarCrossLine.ts var import_ag_charts_community2 = require("ag-charts-community"); var { BaseProperties, ChartAxisDirection, ARRAY, BOOLEAN, COLOR_STRING, FONT_STYLE, FONT_WEIGHT, LINE_DASH, NUMBER, OBJECT, POSITIVE_NUMBER: POSITIVE_NUMBER2, RATIO, STRING, UNION, AND, COLOR_STRING_ARRAY, TempValidate: TempValidate2, MATCHING_CROSSLINE_TYPE, createId, Group } = import_ag_charts_community2._ModuleSupport; var PolarCrossLineLabel = class extends BaseProperties { constructor() { super(...arguments); this.fontSize = 14; this.fontFamily = "Verdana, sans-serif"; this.padding = 5; this.color = "rgba(87, 87, 87, 1)"; } }; __decorateClass([ TempValidate2(BOOLEAN, { optional: true }) ], PolarCrossLineLabel.prototype, "enabled", 2); __decorateClass([ TempValidate2(STRING, { optional: true }) ], PolarCrossLineLabel.prototype, "text", 2); __decorateClass([ TempValidate2(FONT_STYLE, { optional: true }) ], PolarCrossLineLabel.prototype, "fontStyle", 2); __decorateClass([ TempValidate2(FONT_WEIGHT, { optional: true }) ], PolarCrossLineLabel.prototype, "fontWeight", 2); __decorateClass([ TempValidate2(POSITIVE_NUMBER2) ], PolarCrossLineLabel.prototype, "fontSize", 2); __decorateClass([ TempValidate2(STRING) ], PolarCrossLineLabel.prototype, "fontFamily", 2); __decorateClass([ TempValidate2(NUMBER) ], PolarCrossLineLabel.prototype, "padding", 2); __decorateClass([ TempValidate2(COLOR_STRING, { optional: true }) ], PolarCrossLineLabel.prototype, "color", 2); __decorateClass([ TempValidate2(BOOLEAN, { optional: true }) ], PolarCrossLineLabel.prototype, "parallel", 2); var PolarCrossLine = class extends BaseProperties { 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.X; 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.fontFamily = label.fontFamily; node.fontSize = label.fontSize; node.fontStyle = label.fontStyle; node.visible = true; } }; __decorateClass([ TempValidate2(BOOLEAN, { optional: true }) ], PolarCrossLine.prototype, "enabled", 2); __decorateClass([ TempValidate2(UNION(["range", "line"], "a crossLine type")) ], PolarCrossLine.prototype, "type", 2); __decorateClass([ TempValidate2(AND(MATCHING_CROSSLINE_TYPE("range"), ARRAY.restrict({ length: 2 })), { optional: true }) ], PolarCrossLine.prototype, "range", 2); __decorateClass([ TempValidate2(MATCHING_CROSSLINE_TYPE("value"), { optional: true }) ], PolarCrossLine.prototype, "value", 2); __decorateClass([ TempValidate2(COLOR_STRING_ARRAY) ], PolarCrossLine.prototype, "defaultColorRange", 2); __decorateClass([ TempValidate2(COLOR_STRING, { optional: true }) ], PolarCrossLine.prototype, "fill", 2); __decorateClass([ TempValidate2(RATIO, { optional: true }) ], PolarCrossLine.prototype, "fillOpacity", 2); __decorateClass([ TempValidate2(COLOR_STRING, { optional: true }) ], PolarCrossLine.prototype, "stroke", 2); __decorateClass([ TempValidate2(NUMBER, { optional: true }) ], PolarCrossLine.prototype, "strokeWidth", 2); __decorateClass([ TempValidate2(RATIO, { optional: true }) ], PolarCrossLine.prototype, "strokeOpacity", 2); __decorateClass([ TempValidate2(LINE_DASH, { optional: true }) ], PolarCrossLine.prototype, "lineDash", 2); __decorateClass([ TempValidate2(UNION(["polygon", "circle"], "a shape")) ], PolarCrossLine.prototype, "shape", 2); __decorateClass([ TempValidate2(OBJECT) ], PolarCrossLine.prototype, "label", 2); // packages/ag-charts-enterprise/src/axes/polar-crosslines/angleCrossLine.ts var { ChartAxisDirection: ChartAxisDirection2, getCrossLineValue, validateCrossLineValue, normalizeAngle360, Group: Group2, Path, Sector, RotatableText, ContinuousScale } = import_ag_charts_community3._ModuleSupport; var AngleCrossLine = class extends PolarCrossLine { constructor() { super(); this.direction = ChartAxisDirection2.X; 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 ((0, import_ag_charts_core.isArray)(value)) { 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 || !this.isValid() || !validateCrossLineValue(getCrossLineValue(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 (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); angles.forEach((angle, index) => { 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 { angles.slice().reverse().forEach((angle) => { 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 padding = scale instanceof import_ag_charts_community3._ModuleSupport.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] - padding; sector.endAngle = angles[1] + padding; 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 = (0, import_ag_charts_core.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 = ((0, import_ag_charts_core.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 { ChartAxisDirection: ChartAxisDirection3, NUMBER: NUMBER2, UNION: UNION2, ProxyOnWrite, TextWrapper, TextUtils, TempValidate: TempValidate3, toRadians, normalizeAngle360: normalizeAngle3602, normalizeAngle360Inclusive, Path: Path2, RotatableText: RotatableText2, Transformable, BBox } = import_ag_charts_community4._ModuleSupport; var AngleAxisLabel = class extends import_ag_charts_community4._ModuleSupport.AxisLabel { constructor() { super(...arguments); this.orientation = "fixed"; } }; __decorateClass([ TempValidate3(UNION2(["fixed", "parallel", "perpendicular"], "a label orientation")) ], AngleAxisLabel.prototype, "orientation", 2); var AngleAxis = class extends import_ag_charts_community4._ModuleSupport.PolarAxis { constructor(moduleCtx, scale) { super(moduleCtx, scale); this.startAngle = 0; this.endAngle = void 0; this.labelData = []; this.tickData = []; this.radiusLine = this.axisGroup.appendChild(new Path2()); this.includeInvisibleDomains = true; } get direction() { return ChartAxisDirection3.X; } createLabel() { return new AngleAxisLabel(); } calculateTickLayout(domain) { const { nice, scale } = this; const ticksParams = { 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" ? (0, import_ag_charts_core2.countFractionDigits)(t) : 0, f), 0 ); return { niceDomain, primaryTickCount: void 0, tickDomain: niceDomain, ticks, fractionDigits, bbox: this.getBBox() }; } update() { super.update(); this.updateRadiusLine(); } normalizedAngles() { const startAngle = normalizeAngle3602(-Math.PI / 2 + toRadians(this.startAngle)); const sweep = this.endAngle != null ? normalizeAngle360Inclusive(toRadians(this.endAngle) - toRadians(this.startAngle)) : 2 * Math.PI; 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() { const { translation, axisGroup, gridGroup, crossLineRangeGroup, crossLineLineGroup, crossLineLabelGroup } = this; const translationX = Math.floor(translation.x); const translationY = Math.floor(translation.y); axisGroup.translationX = translationX; axisGroup.translationY = translationY; gridGroup.translationX = translationX; gridGroup.translationY = translationY; crossLineRangeGroup.translationX = translationX; crossLineRangeGroup.translationY = translationY; crossLineLineGroup.translationX = translationX; crossLineLineGroup.translationY = translationY; crossLineLabelGroup.translationX = translationX; crossLineLabelGroup.translationY = translationY; } updateRadiusLine() { const node = this.radiusLine; const { path } = node; path.clear(true); const { points, closePath } = this.getAxisLinePoints(); points.forEach(({ x, y, moveTo, arc, radius = 0, startAngle = 0, endAngle = 0 }) => { if (arc) { path.arc(x, y, radius, startAngle, endAngle); } else if (moveTo) { 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 = (0, import_ag_charts_core2.isNumberEqual)(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, interval: void 0, tickCount: void 0, minTickCount: 0, maxTickCount: Infinity })?.map((value) => scale.convert(value)); if (angles && angles.length > 2) { angles.forEach((angle, i) => { const x = radius * Math.cos(angle); const y = radius * Math.sin(angle); const moveTo = i === 0; points.push({ x, y, moveTo }); }); } } 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, 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 = stroke; 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.textAlign = labelDatum.textAlign; node.textBaseline = labelDatum.textBaseline; 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 tempText2 = new RotatableText2(); const seriesLeft = seriesRect.x - this.translation.x; const seriesRight = seriesRect.x + seriesRect.width - this.translation.x; 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] && (0, import_ag_charts_core2.isNumberEqual)(normalizeAngle3602(angle), normalizeAngle3602(scale.convert(ticks[0]))); const rotation = this.getLabelRotation(angle); let text = this.formatTick(value, index, scale.domain); tempText2.text = text; tempText2.x = x; tempText2.y = y; tempText2.setFont(label); tempText2.textAlign = textAlign; tempText2.textBaseline = textBaseline; tempText2.rotation = rotation; if (rotation) { tempText2.rotationCenterX = x; tempText2.rotationCenterY = y; } let box = rotation ? Transformable.toCanvas(tempText2) : tempText2.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); text = TextWrapper.wrapText(text, { maxWidth: availWidth, font: label, textWrap: "never" }); if (text === TextUtils.EllipsisChar) { text = ""; } tempText2.text = text; box = tempText2.getBBox(); } } return { text, x, y, textAlign, textBaseline, hidden: text === "" || 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 = (0, import_ag_charts_core2.isNumberEqual)(cos, 0); const isSin0 = (0, import_ag_charts_core2.isNumberEqual)(sin, 0); const isCos1 = (0, import_ag_charts_core2.isNumberEqual)(cos, 1); const isSinMinus1 = (0, import_ag_charts_core2.isNumberEqual)(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; this.crossLines.forEach((crossLine) => { 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([ ProxyOnWrite("rotation"), TempValidate3(NUMBER2) ], AngleAxis.prototype, "startAngle", 2); __decorateClass([ TempValidate3(NUMBER2, { optional: true }) ], AngleAxis.prototype, "endAngle", 2); // packages/ag-charts-enterprise/src/axes/angle-category/angleCategoryAxis.ts var { RATIO: RATIO2, OBJECT: OBJECT2, TempValidate: TempValidate4, CategoryScale } = import_ag_charts_community5._ModuleSupport; var AngleCategoryAxis = class extends AngleAxis { constructor(moduleCtx) { super(moduleCtx, new CategoryScale()); this.groupPaddingInner = 0; this.paddingInner = 0; this.interval = new AngleAxisInterval(); } generateAngleTicks() { const { scale, gridLength: radius } = this; const { values, minSpacing } = this.interval; const ticks = values ?? scale.ticks({ nice: this.nice, interval: void 0, tickCount: void 0, minTickCount: 0, maxTickCount: Infinity }) ?? []; 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.sqrt((nextX - startX) ** 2 + (nextY - startY) ** 2); if (spacing > minSpacing) { const visibleTicks = /* @__PURE__ */ new Set([startTick]); loopSymmetrically(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 = (0, import_ag_charts_core3.isNumberEqual)(firstLabel.x, lastLabel.x) && (0, import_ag_charts_core3.isNumberEqual)(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 = loopSymmetrically(labels, step, labelsCollide); if (!collisionDetected) { loopSymmetrically(labels, step, (_, next) => { visibleLabels.add(next); }); break; } } labelData.forEach((datum) => { if (!visibleLabels.has(datum)) { datum.hidden = true; datum.box = void 0; } }); } }; AngleCategoryAxis.className = "AngleCategoryAxis"; AngleCategoryAxis.type = "angle-category"; __decorateClass([ TempValidate4(RATIO2) ], AngleCategoryAxis.prototype, "groupPaddingInner", 2); __decorateClass([ TempValidate4(RATIO2) ], AngleCategoryAxis.prototype, "paddingInner", 2); __decorateClass([ TempValidate4(OBJECT2) ], AngleCategoryAxis.prototype, "interval", 2); // packages/ag-charts-enterprise/src/axes/angle-number/angleNumberAxis.ts var import_ag_charts_community7 = require("ag-charts-community"); var import_ag_charts_core5 = require("ag-charts-core"); // packages/ag-charts-enterprise/src/axes/angle-number/linearAngleScale.ts var import_ag_charts_community6 = require("ag-charts-community"); var import_ag_charts_core4 = require("ag-charts-core"); var { range, isDenseInterval, LinearScale } = import_ag_charts_community6._ModuleSupport; 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 = 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) => !isFinite(d)) || arcLength <= 0) { return []; } 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)) { return range(d0, d1, step2); } } 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); } return range(d0, d1, step); } hasNiceRange() { const sortedRange = this.range.slice().sort((a, b) => a - b); const niceRanges = [Math.PI, 2 * Math.PI]; return niceRanges.some((r) => (0, import_ag_charts_core4.isNumberEqual)(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 { AND: AND2, GREATER_THAN, LESS_THAN, NUMBER_OR_NAN, OBJECT: OBJECT3, TempValidate: TempValidate5, angleBetween, normalisedExtentWithMetadata, findMinMax } = import_ag_charts_community7._ModuleSupport; var AngleNumberAxis = class extends AngleAxis { constructor(moduleCtx) { super(moduleCtx, new LinearAngleScale()); this.shape = "circle"; this.interval = new AngleAxisInterval(); } normaliseDataDomain(d) { const { min, max } = this; const { extent: extent3, clipped } = normalisedExtentWithMetadata(d, min, max); return { domain: extent3, clipped }; } 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, interval: step, tickCount, minTickCount, maxTickCount }; rawTicks = scale.ticks(tickParams, domain); } 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 && (0, import_ag_charts_core5.isNumberEqual)(firstLabel.x, lastLabel.x) && (0, import_ag_charts_core5.isNumberEqual)(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) { labelData.forEach((datum, i) => { if (i % step > 0) { datum.hidden = true; datum.box = void 0; } }); return; } } labelData.forEach((datum, i) => { if (i > 0) { datum.hidden = true; datum.box = void 0; } }); } }; AngleNumberAxis.className = "AngleNumberAxis"; AngleNumberAxis.type = "angle-number"; __decorateClass([ TempValidate5(AND2(NUMBER_OR_NAN, LESS_THAN("max")), { optional: true }) ], AngleNumberAxis.prototype, "min", 2); __decorateClass([ TempValidate5(AND2(NUMBER_OR_NAN, GREATER_THAN("min")), { optional: true }) ], AngleNumberAxis.prototype, "max", 2); __decorateClass([ TempValidate5(OBJECT3) ], AngleNumberAxis.prototype, "interval", 2); // packages/ag-charts-enterprise/src/axes/ordinal/ordinalTimeAxis.ts var import_ag_charts_community8 = require("ag-charts-community"); var { OrdinalTimeScale } = import_ag_charts_community8._ModuleSupport; var OrdinalTimeAxis = class extends import_ag_charts_community8._ModuleSupport.CategoryAxis { constructor(moduleCtx) { super(moduleCtx, new OrdinalTimeScale()); } }; OrdinalTimeAxis.className = "OrdinalTimeAxis"; OrdinalTimeAxis.type = "ordinal-time"; // packages/ag-charts-enterprise/src/axes/radius-category/radiusCategoryAxis.ts var import_ag_charts_community11 = require("ag-charts-community"); // packages/ag-charts-enterprise/src/axes/radius/radiusAxis.ts var import_ag_charts_community10 = require("ag-charts-community"); var import_ag_charts_core7 = require("ag-charts-core"); // packages/ag-charts-enterprise/src/axes/polar-crosslines/radiusCrossLine.ts var import_ag_charts_community9 = require("ag-charts-community"); var import_ag_charts_core6 = require("ag-charts-core"); var { ChartAxisDirection: ChartAxisDirection4, TempValidate: TempValidate6, NUMBER: NUMBER3, getCrossLineValue: getCrossLineValue2, validateCrossLineValue: validateCrossLineValue2, normalizeAngle360: normalizeAngle3603, toRadians: toRadians2, Group: Group3, Path: Path3, Sector: Sector2, RotatableText: RotatableText3 } = import_ag_charts_community9._ModuleSupport; var RadiusCrossLineLabel = class extends PolarCrossLineLabel { constructor() { super(...arguments); this.positionAngle = void 0; } }; __decorateClass([ TempValidate6(NUMBER3, { optional: true }) ], RadiusCrossLineLabel.prototype, "positionAngle", 2); var RadiusCrossLine = class extends PolarCrossLine { constructor() { super(); this.direction = ChartAxisDirection4.Y; 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 || !this.isValid() || !validateCrossLineValue2(getCrossLineValue2(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) { angles.forEach((angle, index) => { 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 padding = this.getPadding(); polygon.path.clear(true); this.drawPolygon(outerRadius - padding, gridAngles, polygon); const reversedAngles = gridAngles.slice().reverse(); const innerPolygonRadius = type === "line" ? outerRadius - padding : innerRadius + padding; 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 padding = this.getPadding(); const r0 = (0, import_ag_charts_core6.clamp)(axisInnerRadius, innerRadius + padding, axisOuterRadius); const r1 = (0, import_ag_charts_core6.clamp)(axisInnerRadius, outerRadius - padding, 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 = normalizeAngle3603(toRadians2((label.positionAngle ?? 0) - 90)); const isBottomSide = ((0, import_ag_charts_core6.isNumberEqual)(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 import_ag_charts_community9._ModuleSupport.BandScale ? (step - bandwidth) / 2 : 0; } }; RadiusCrossLine.className = "RadiusCrossLine"; // packages/ag-charts-enterprise/src/axes/radius/radiusAxis.ts var { ChartAxisDirection: ChartAxisDirection5, ZIndexMap, NUMBER: NUMBER4, BOOLEAN: BOOLEAN2, TempValidate: TempValidate7, normalizeAngle360: normalizeAngle3604, toRadians: toRadians3, Caption, Group: Group4, Path: Path4, Line, Selection, AxisTickGenerator, AxisGroupZIndexMap } = import_ag_charts_community10._ModuleSupport; var RadiusAxisLabel = class extends import_ag_charts_community10._ModuleSupport.AxisLabel { constructor() { super(...arguments); this.autoRotateAngle = 335; } }; __decorateClass([ TempValidate7(BOOLEAN2, { optional: true }) ], RadiusAxisLabel.prototype, "autoRotate", 2); __decorateClass([ TempValidate7(NUMBER4) ], RadiusAxisLabel.prototype, "autoRotateAngle", 2); var RadiusAxis = class extends import_ag_charts_community10._ModuleSupport.PolarAxis { constructor(moduleCtx, scale) { super(moduleCtx, scale); this.positionAngle = 0; this.tickGenerator = new AxisTickGenerator(this); this.generatedTicks = void 0; this.lineNode = this.axisGroup.appendChild( new Line({ name: `${this.id}-Axis-line`, zIndex: AxisGroupZIndexMap.AxisLine }) ); this.gridPathGroup = this.gridGroup.appendChild( new Group4({ name: `${this.id}-gridPaths`, zIndex: ZIndexMap.AXIS_GRID }) ); this.gridPathSelection = Selection.select(this.gridPathGroup, Path4); this.axisGroup.appendChild(this.title.caption.node); this.destroyFns.push(this.title.caption.registerInteraction(this.moduleCtx, "afterend")); } get direction() {