apexcharts
Version:
A JavaScript Chart Library
1,420 lines • 108 kB
JavaScript
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
/*!
* ApexCharts v6.6.1
* (c) 2018-2026 ApexCharts
*/
import * as _core from "apexcharts/core";
import _core__default from "apexcharts/core";
import { default as default2 } from "apexcharts/core";
const CoreUtils = _core.__apex_CoreUtils;
const Graphics = _core.__apex_Graphics;
const DataLabels = _core.__apex_DataLabels;
const BrowserAPIs = _core.__apex_BrowserAPIs_BrowserAPIs;
const Environment = _core.__apex_Environment_Environment;
function lengthTransitionEnabled(w) {
var _a;
const anim = w.config.chart.animations;
if (!anim || anim.enabled === false) return false;
if (!anim.dynamicAnimation || anim.dynamicAnimation.enabled === false) {
return false;
}
const largeThreshold = (_a = anim.largeDatasetThreshold) != null ? _a : 0;
if (largeThreshold > 0 && w.globals.dataPoints > largeThreshold) return false;
return !!(Environment.isBrowser() && w.globals.dataChanged && w.globals.shouldAnimate);
}
function datumKey(w, realIndex, j) {
var _a, _b, _c, _d;
if ((_a = w.axisFlags) == null ? void 0 : _a.isXNumeric) {
const sx = (_c = (_b = w.seriesData) == null ? void 0 : _b.seriesX) == null ? void 0 : _c[realIndex];
if (sx && sx.length && sx[j] != null) return "x:" + sx[j];
}
const lbl = (_d = w.globals.labels) == null ? void 0 : _d[j];
if (lbl != null && String(lbl) !== "") {
return "c:" + (Array.isArray(lbl) ? lbl.join(" ") : String(lbl));
}
return "j:" + j;
}
function frameDatumKey(frame, realIndex, j) {
var _a, _b;
if (frame.isXNumeric) {
const sx = (_a = frame.seriesX) == null ? void 0 : _a[realIndex];
if (sx && sx.length && sx[j] != null) return "x:" + sx[j];
}
const lbl = (_b = frame.labels) == null ? void 0 : _b[j];
if (lbl != null && String(lbl) !== "") {
return "c:" + (Array.isArray(lbl) ? lbl.join(" ") : String(lbl));
}
return "j:" + j;
}
function joinKeys(oldKeys, newKeys) {
const oldIndex = /* @__PURE__ */ new Map();
oldKeys.forEach((k, i) => {
if (!oldIndex.has(k)) oldIndex.set(k, i);
});
const toOld = new Array(newKeys.length);
const usedOld = /* @__PURE__ */ new Set();
let prev = -1;
let ordered = true;
let identity = oldKeys.length === newKeys.length;
newKeys.forEach((k, i) => {
const oi = oldIndex.has(k) && !usedOld.has(oldIndex.get(k)) ? oldIndex.get(k) : -1;
toOld[i] = oi;
if (oi !== -1) {
usedOld.add(oi);
if (oi < prev) ordered = false;
prev = oi;
}
if (oi !== i) identity = false;
});
const exits = [];
for (let i = 0; i < oldKeys.length; i++) {
if (!usedOld.has(i)) exits.push(i);
}
return { toOld, exits, ordered, changed: !identity };
}
function uniquifyKeys(keys) {
const seen = /* @__PURE__ */ new Map();
return keys.map((k) => {
const count = seen.get(k) || 0;
seen.set(k, count + 1);
return count === 0 ? k : `${k}#${count}`;
});
}
function seriesJoin(w, realIndex, includeIdentity = false, allowReorder = false) {
var _a, _b;
if (!lengthTransitionEnabled(w)) return null;
const frame = w.globals.prevStreamFrame;
if (!frame) return null;
const oldY = (_a = frame.seriesY) == null ? void 0 : _a[realIndex];
const newY = (_b = w.seriesData.series) == null ? void 0 : _b[realIndex];
if (!Array.isArray(oldY) || !Array.isArray(newY)) return null;
if (!oldY.length || !newY.length) return null;
const oldKeys = uniquifyKeys(
oldY.map((_, j) => frameDatumKey(frame, realIndex, j))
);
const newKeys = uniquifyKeys(newY.map((_, j) => datumKey(w, realIndex, j)));
const join = joinKeys(oldKeys, newKeys);
if (!join.ordered && !allowReorder) return null;
if (!join.changed && !includeIdentity) return null;
return { join, oldKeys, newKeys };
}
function firstMove(d) {
const m = /^M\s*([+-]?[\d.eE]+)[\s,]+([+-]?[\d.eE]+)/.exec(d || "");
if (!m) return null;
const x = parseFloat(m[1]);
const y = parseFloat(m[2]);
return isFinite(x) && isFinite(y) ? { x, y } : null;
}
function renderBarExitGhosts({
w,
elSeries,
record,
newKeys,
isHorizontal,
speed
}) {
var _a;
if (!lengthTransitionEnabled(w)) return;
if (!record || !Array.isArray(record.paths) || !(elSeries == null ? void 0 : elSeries.node)) return;
const newKeySet = new Set(newKeys);
const exits = record.paths.filter(
(p) => p && p.d && p.key != null && !newKeySet.has(p.key)
);
if (!exits.length) return;
const graphics = new Graphics(w);
const fallbackFill = (_a = w.globals.colors) == null ? void 0 : _a[parseInt(String(record.realIndex), 10)];
exits.forEach((p) => {
let fill = p.fill || fallbackFill || "#c8c8c8";
if (String(fill).indexOf("url(") === 0) fill = fallbackFill || "#c8c8c8";
const ghost = graphics.drawPath({
d: p.d,
stroke: "none",
strokeWidth: 0,
fill,
fillOpacity: 1,
classes: "apexcharts-bar-ghost"
});
const node = ghost.node;
node.setAttribute("pointer-events", "none");
ghost.attr(
"clip-path",
`url(#gridRectBarMask${w.globals.cuid})`
);
elSeries.node.insertBefore(node, elSeries.node.firstChild);
const start = firstMove(p.d);
let origin = isHorizontal ? "left center" : "center bottom";
try {
const bb = node.getBBox();
if (start && bb) {
if (isHorizontal) {
origin = Math.abs(start.x - bb.x) <= Math.abs(start.x - (bb.x + bb.width)) ? "left center" : "right center";
} else {
origin = Math.abs(start.y - (bb.y + bb.height)) <= Math.abs(start.y - bb.y) ? "center bottom" : "center top";
}
}
} catch (_) {
}
const style = node.style;
style.transformBox = "fill-box";
style.transformOrigin = origin;
const duration = Math.max(1, speed || 1);
const startAt = performance.now();
const step = (now) => {
if (w.globals.isDestroyed || !node.parentNode) return;
const t = Math.max(0, Math.min(1, (now - startAt) / duration));
const eased = 1 - Math.pow(1 - t, 3);
const scale = 1 - eased;
style.transform = isHorizontal ? `scaleX(${scale})` : `scaleY(${scale})`;
style.opacity = String(1 - eased);
if (t < 1) {
BrowserAPIs.requestAnimationFrame(step);
} else {
node.parentNode.removeChild(node);
}
};
BrowserAPIs.requestAnimationFrame(step);
});
}
class BarDataLabels {
/**
* @param {import('../../../charts/Bar').default} barCtx
*/
constructor(barCtx) {
this.w = barCtx.w;
this.barCtx = barCtx;
this.totalFormatter = this.w.config.plotOptions.bar.dataLabels.total.formatter;
if (!this.totalFormatter) {
this.totalFormatter = this.w.config.dataLabels.formatter;
}
}
/** handleBarDataLabels is used to calculate the positions for the data-labels
* It also sets the element's data attr for bars and calls drawCalculatedBarDataLabels()
* After calculating, it also calls the function to draw data labels
* @memberof Bar
* @param {Record<string, any>} opts - bar properties used throughout the bar drawing function
* @return {object} dataLabels node-element which you can append later
**/
handleBarDataLabels(opts) {
const {
x,
y,
y1,
y2,
i,
j,
realIndex,
columnGroupIndex,
series,
barHeight,
barWidth,
barXPosition,
barYPosition,
visibleSeries
} = opts;
const w = this.w;
const graphics = new Graphics(this.barCtx.w);
const strokeWidth = Array.isArray(this.barCtx.strokeWidth) ? this.barCtx.strokeWidth[realIndex] : this.barCtx.strokeWidth;
let bcx;
let bcy;
if (w.axisFlags.isXNumeric && !w.globals.isBarHorizontal) {
bcx = x + barWidth * (visibleSeries + 1);
bcy = y + barHeight * (visibleSeries + 1) - strokeWidth;
} else {
bcx = x + barWidth * visibleSeries;
bcy = y + barHeight * visibleSeries;
}
let dataLabels = null;
let totalDataLabels = null;
let dataLabelsX = x;
let dataLabelsY = y;
let dataLabelsPos = (
/** @type {any} */
{}
);
const dataLabelsConfig = w.config.dataLabels;
const barDataLabelsConfig = this.barCtx.barOptions.dataLabels;
const barTotalDataLabelsConfig = this.barCtx.barOptions.dataLabels.total;
if (typeof barYPosition !== "undefined" && (this.barCtx.isRangeBar || this.barCtx.isPyramid)) {
bcy = barYPosition;
dataLabelsY = barYPosition;
}
if (typeof barXPosition !== "undefined" && this.barCtx.isVerticalGroupedRangeBar) {
bcx = barXPosition;
dataLabelsX = barXPosition;
}
const offX = dataLabelsConfig.offsetX;
const offY = dataLabelsConfig.offsetY;
let textRects = {
width: 0,
height: 0
};
if (w.config.dataLabels.enabled) {
const yLabel = w.seriesData.series[i][j];
textRects = graphics.getTextRects(
w.config.dataLabels.formatter ? w.config.dataLabels.formatter(yLabel, __spreadProps(__spreadValues({}, w), {
seriesIndex: i,
dataPointIndex: j,
w
})) : w.formatters.yLabelFormatters[0](yLabel),
parseFloat(dataLabelsConfig.style.fontSize).toString()
);
}
const params = {
x,
y,
i,
j,
realIndex,
columnGroupIndex,
bcx,
bcy,
barHeight,
barWidth,
textRects,
strokeWidth,
dataLabelsX,
dataLabelsY,
dataLabelsConfig,
barDataLabelsConfig,
barTotalDataLabelsConfig,
offX,
offY
};
if (this.barCtx.isHorizontal) {
dataLabelsPos = this.calculateBarsDataLabelsPosition(params);
} else {
dataLabelsPos = this.calculateColumnsDataLabelsPosition(params);
}
dataLabels = this.drawCalculatedDataLabels({
x: dataLabelsPos.dataLabelsX,
y: dataLabelsPos.dataLabelsY,
val: this.barCtx.isRangeBar ? [y1, y2] : w.config.chart.stackType === "100%" ? series[realIndex][j] : w.seriesData.series[realIndex][j],
i: realIndex,
j,
barWidth,
barHeight,
textRects,
dataLabelsConfig
});
if (w.config.chart.stacked && barTotalDataLabelsConfig.enabled) {
totalDataLabels = this.drawTotalDataLabels({
x: dataLabelsPos.totalDataLabelsX,
y: dataLabelsPos.totalDataLabelsY,
barWidth,
barHeight,
realIndex,
textAnchor: dataLabelsPos.totalDataLabelsAnchor,
val: this.getStackedTotalDataLabel({ realIndex, j }),
dataLabelsConfig,
barTotalDataLabelsConfig
});
}
return {
dataLabelsPos,
dataLabels,
totalDataLabels
};
}
/** @param {{realIndex: any, j: any}} opts */
getStackedTotalDataLabel({ realIndex, j }) {
const w = this.w;
let val = this.barCtx.stackedSeriesTotals[j];
if (this.totalFormatter) {
val = this.totalFormatter(val, __spreadProps(__spreadValues({}, w), {
seriesIndex: realIndex,
dataPointIndex: j,
w
}));
}
return val;
}
/**
* @param {Record<string, any>} opts
*/
calculateColumnsDataLabelsPosition(opts) {
const w = this.w;
let {
i,
j,
realIndex,
y,
bcx,
barWidth,
barHeight,
textRects,
dataLabelsX,
dataLabelsY,
dataLabelsConfig,
barDataLabelsConfig,
barTotalDataLabelsConfig,
strokeWidth,
offX,
offY
} = opts;
let totalDataLabelsY;
let totalDataLabelsX;
const totalDataLabelsAnchor = "middle";
const totalDataLabelsBcx = bcx;
barHeight = Math.abs(barHeight);
const vertical = w.config.plotOptions.bar.dataLabels.orientation === "vertical";
const { zeroEncounters } = this.barCtx.barHelpers.getZeroValueEncounters({
i,
j
});
bcx = bcx - strokeWidth / 2;
const dataPointsDividedWidth = w.layout.gridWidth / w.globals.dataPoints;
if (this.barCtx.isVerticalGroupedRangeBar) {
dataLabelsX += barWidth / 2;
} else {
if (w.axisFlags.isXNumeric) {
dataLabelsX = bcx - barWidth / 2 + offX;
} else {
dataLabelsX = bcx - dataPointsDividedWidth + barWidth / 2 + offX;
}
if (!w.config.chart.stacked && zeroEncounters > 0 && w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
dataLabelsX -= barWidth * zeroEncounters;
}
}
if (vertical) {
const offsetDLX = 2;
dataLabelsX = dataLabelsX + textRects.height / 2 - strokeWidth / 2 - offsetDLX;
}
const valIsNegative = w.seriesData.series[i][j] < 0;
let newY = y;
if (this.barCtx.isReversed) {
newY = y + (valIsNegative ? barHeight : -barHeight);
}
switch (barDataLabelsConfig.position) {
case "center":
if (vertical) {
if (valIsNegative) {
dataLabelsY = newY - barHeight / 2 + offY;
} else {
dataLabelsY = newY + barHeight / 2 - offY;
}
} else {
if (valIsNegative) {
dataLabelsY = newY - barHeight / 2 + textRects.height / 2 + offY;
} else {
dataLabelsY = newY + barHeight / 2 + textRects.height / 2 - offY;
}
}
break;
case "bottom":
if (vertical) {
if (valIsNegative) {
dataLabelsY = newY - barHeight + offY;
} else {
dataLabelsY = newY + barHeight - offY;
}
} else {
if (valIsNegative) {
dataLabelsY = newY - barHeight + textRects.height + strokeWidth + offY;
} else {
dataLabelsY = newY + barHeight - textRects.height / 2 + strokeWidth - offY;
}
}
break;
case "top":
if (vertical) {
if (valIsNegative) {
dataLabelsY = newY + offY;
} else {
dataLabelsY = newY - offY;
}
} else {
if (valIsNegative) {
dataLabelsY = newY - textRects.height / 2 - offY;
} else {
dataLabelsY = newY + textRects.height + offY;
}
}
break;
}
let lowestPrevY = newY;
w.labelData.seriesGroups.forEach((sg) => {
var _a;
(_a = this.barCtx[sg.join(",")]) == null ? void 0 : _a.prevY.forEach(
(arr) => {
if (valIsNegative) {
lowestPrevY = Math.max(arr[j], lowestPrevY);
} else {
lowestPrevY = Math.min(arr[j], lowestPrevY);
}
}
);
});
if (this.barCtx.lastActiveBarSerieIndex === realIndex && barTotalDataLabelsConfig.enabled) {
const ADDITIONAL_OFFY = 18;
const graphics = new Graphics(this.barCtx.w);
const totalLabeltextRects = graphics.getTextRects(
this.getStackedTotalDataLabel({ realIndex, j }),
dataLabelsConfig.fontSize
);
if (valIsNegative) {
totalDataLabelsY = lowestPrevY - totalLabeltextRects.height / 2 - offY - barTotalDataLabelsConfig.offsetY + ADDITIONAL_OFFY;
} else {
totalDataLabelsY = lowestPrevY + totalLabeltextRects.height + offY + barTotalDataLabelsConfig.offsetY - ADDITIONAL_OFFY;
}
const xDivision = dataPointsDividedWidth;
totalDataLabelsX = totalDataLabelsBcx + (w.axisFlags.isXNumeric ? -barWidth * w.globals.barGroups.length / 2 : w.globals.barGroups.length * barWidth / 2 - (w.globals.barGroups.length - 1) * barWidth - xDivision) + barTotalDataLabelsConfig.offsetX;
}
if (!w.config.chart.stacked) {
if (dataLabelsY < 0) {
dataLabelsY = 0 + strokeWidth;
} else if (dataLabelsY + textRects.height / 3 > w.layout.gridHeight) {
dataLabelsY = w.layout.gridHeight - strokeWidth;
}
}
return {
bcx,
bcy: y,
dataLabelsX,
dataLabelsY,
totalDataLabelsX,
totalDataLabelsY,
totalDataLabelsAnchor
};
}
/**
* @param {Record<string, any>} opts
*/
calculateBarsDataLabelsPosition(opts) {
var _a;
const w = this.w;
let {
x,
i,
j,
realIndex,
bcy,
barHeight,
barWidth,
textRects,
dataLabelsX,
strokeWidth,
dataLabelsConfig,
barDataLabelsConfig,
barTotalDataLabelsConfig,
offX,
offY
} = opts;
const dataPointsDividedHeight = w.layout.gridHeight / w.globals.dataPoints;
const { zeroEncounters } = this.barCtx.barHelpers.getZeroValueEncounters({
i,
j
});
barWidth = Math.abs(barWidth);
let dataLabelsY;
if (this.barCtx.isPyramid) {
const centerOffset = (_a = textRects.centerOffset) != null ? _a : 0;
dataLabelsY = bcy + barHeight / 2 + offY - centerOffset;
} else {
dataLabelsY = bcy - (this.barCtx.isRangeBar ? 0 : dataPointsDividedHeight) + barHeight / 2 + textRects.height / 2 + offY - 3;
}
if (!w.config.chart.stacked && zeroEncounters > 0 && w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
dataLabelsY -= barHeight * zeroEncounters;
}
let totalDataLabelsX;
let totalDataLabelsY;
let totalDataLabelsAnchor = "start";
const valIsNegative = w.seriesData.series[i][j] < 0;
let newX = x;
if (this.barCtx.isReversed) {
newX = x + (valIsNegative ? -barWidth : barWidth);
totalDataLabelsAnchor = valIsNegative ? "start" : "end";
}
if (this.barCtx.isPyramid) {
dataLabelsX = w.layout.gridWidth / 2 + offX;
} else {
switch (barDataLabelsConfig.position) {
case "center":
if (valIsNegative) {
dataLabelsX = newX + barWidth / 2 - offX;
} else {
dataLabelsX = Math.max(textRects.width / 2, newX - barWidth / 2) + offX;
}
break;
case "bottom":
if (valIsNegative) {
dataLabelsX = newX + barWidth - strokeWidth - offX;
} else {
dataLabelsX = newX - barWidth + strokeWidth + offX;
}
break;
case "top":
if (valIsNegative) {
dataLabelsX = newX - strokeWidth - offX;
} else {
dataLabelsX = newX - strokeWidth + offX;
}
break;
}
}
let lowestPrevX = newX;
w.labelData.seriesGroups.forEach((sg) => {
var _a2;
(_a2 = this.barCtx[sg.join(",")]) == null ? void 0 : _a2.prevX.forEach(
(arr) => {
if (valIsNegative) {
lowestPrevX = Math.min(arr[j], lowestPrevX);
} else {
lowestPrevX = Math.max(arr[j], lowestPrevX);
}
}
);
});
if (this.barCtx.lastActiveBarSerieIndex === realIndex && barTotalDataLabelsConfig.enabled) {
const graphics = new Graphics(this.barCtx.w);
const totalLabeltextRects = graphics.getTextRects(
this.getStackedTotalDataLabel({ realIndex, j }),
dataLabelsConfig.fontSize
);
if (valIsNegative) {
totalDataLabelsX = lowestPrevX - strokeWidth - offX - barTotalDataLabelsConfig.offsetX;
totalDataLabelsAnchor = "end";
} else {
totalDataLabelsX = lowestPrevX + offX + barTotalDataLabelsConfig.offsetX + (this.barCtx.isReversed ? -(barWidth + strokeWidth) : strokeWidth);
}
totalDataLabelsY = dataLabelsY - textRects.height / 2 + totalLabeltextRects.height / 2 + barTotalDataLabelsConfig.offsetY + strokeWidth;
if (w.globals.barGroups.length > 1) {
totalDataLabelsY = totalDataLabelsY - w.globals.barGroups.length / 2 * (barHeight / 2);
}
}
if (!w.config.chart.stacked) {
if (dataLabelsConfig.textAnchor === "start") {
if (dataLabelsX - textRects.width < 0) {
dataLabelsX = valIsNegative ? textRects.width + strokeWidth - offX : strokeWidth + offX;
} else if (dataLabelsX + textRects.width > w.layout.gridWidth) {
dataLabelsX = valIsNegative ? w.layout.gridWidth - strokeWidth : w.layout.gridWidth - textRects.width - strokeWidth;
}
} else if (dataLabelsConfig.textAnchor === "middle") {
if (dataLabelsX - textRects.width / 2 < 0) {
dataLabelsX = textRects.width / 2 + strokeWidth;
} else if (dataLabelsX + textRects.width / 2 > w.layout.gridWidth) {
dataLabelsX = w.layout.gridWidth - textRects.width / 2 - strokeWidth;
}
} else if (dataLabelsConfig.textAnchor === "end") {
if (dataLabelsX < 1) {
dataLabelsX = textRects.width + strokeWidth;
} else if (dataLabelsX + 1 > w.layout.gridWidth) {
dataLabelsX = w.layout.gridWidth - textRects.width - strokeWidth;
}
}
}
return {
bcx: x,
bcy,
dataLabelsX,
dataLabelsY,
totalDataLabelsX,
totalDataLabelsY,
totalDataLabelsAnchor
};
}
/** @param {{x: any, y: any, val: any, i: any, j: any, textRects: any, barHeight: any, barWidth: any, dataLabelsConfig: any}} opts */
drawCalculatedDataLabels({
x,
y,
val,
i,
// = realIndex
j,
textRects,
barHeight,
barWidth,
dataLabelsConfig
}) {
var _a, _b;
const w = this.w;
let rotate = "rotate(0)";
if (w.config.plotOptions.bar.dataLabels.orientation === "vertical")
rotate = `rotate(-90, ${x}, ${y})`;
const dataLabels = new DataLabels(this.barCtx.w, this.barCtx.ctx);
const graphics = new Graphics(this.barCtx.w);
const formatter = dataLabelsConfig.formatter;
let elDataLabelsWrap = null;
const isSeriesNotCollapsed = w.globals.collapsedSeriesIndices.indexOf(i) > -1;
if (dataLabelsConfig.enabled && !isSeriesNotCollapsed) {
elDataLabelsWrap = graphics.group({
class: "apexcharts-data-labels",
transform: rotate
});
const dlCfg = w.config.dataLabels;
if (((_a = dlCfg.animate) == null ? void 0 : _a.enabled) || ((_b = dlCfg.countUp) == null ? void 0 : _b.enabled)) {
elDataLabelsWrap.node.setAttribute(
"data:dlKey",
`${i}::${datumKey(w, i, j)}`
);
elDataLabelsWrap.node.setAttribute("data:dlJ", String(j));
if (typeof val === "number" && isFinite(val)) {
elDataLabelsWrap.node.setAttribute("data:dlVal", String(val));
}
}
let text = "";
if (typeof val !== "undefined") {
text = formatter(val, __spreadProps(__spreadValues({}, w), {
seriesIndex: i,
dataPointIndex: j,
w
}));
}
if (!val && w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
text = "";
}
const valIsNegative = w.seriesData.series[i][j] < 0;
const position = w.config.plotOptions.bar.dataLabels.position;
if (w.config.plotOptions.bar.dataLabels.orientation === "vertical") {
if (position === "top") {
if (valIsNegative) dataLabelsConfig.textAnchor = "end";
else dataLabelsConfig.textAnchor = "start";
}
if (position === "center") {
dataLabelsConfig.textAnchor = "middle";
}
if (position === "bottom") {
if (valIsNegative) dataLabelsConfig.textAnchor = "end";
else dataLabelsConfig.textAnchor = "start";
}
}
if (this.barCtx.isRangeBar && this.barCtx.barOptions.dataLabels.hideOverflowingLabels) {
const txRect = graphics.getTextRects(
text,
parseFloat(dataLabelsConfig.style.fontSize).toString()
);
if (barWidth < txRect.width) {
text = "";
}
}
if (w.config.chart.stacked && this.barCtx.barOptions.dataLabels.hideOverflowingLabels) {
if (this.barCtx.isHorizontal) {
if (textRects.width / 1.6 > Math.abs(barWidth)) {
text = "";
}
} else {
if (textRects.height / 1.6 > Math.abs(barHeight)) {
text = "";
}
}
}
const modifiedDataLabelsConfig = __spreadValues({}, dataLabelsConfig);
if (this.barCtx.isHorizontal) {
if (val < 0) {
if (dataLabelsConfig.textAnchor === "start") {
modifiedDataLabelsConfig.textAnchor = "end";
} else if (dataLabelsConfig.textAnchor === "end") {
modifiedDataLabelsConfig.textAnchor = "start";
}
}
}
dataLabels.plotDataLabelsText({
x,
y,
text,
i,
j,
parent: elDataLabelsWrap,
dataLabelsConfig: modifiedDataLabelsConfig,
alwaysDrawDataLabel: true,
offsetCorrection: true
});
}
return elDataLabelsWrap;
}
/** @param {{ x?: any, y?: any, val?: any, realIndex?: any, textAnchor?: any, barWidth?: any, barHeight?: any, dataLabelsConfig?: any, barTotalDataLabelsConfig?: any }} opts */
drawTotalDataLabels({
x,
y,
val,
realIndex,
textAnchor,
barTotalDataLabelsConfig
}) {
const graphics = new Graphics(this.barCtx.w);
let totalDataLabelText;
if (barTotalDataLabelsConfig.enabled && typeof x !== "undefined" && typeof y !== "undefined" && this.barCtx.lastActiveBarSerieIndex === realIndex) {
totalDataLabelText = graphics.drawText({
x,
y,
foreColor: barTotalDataLabelsConfig.style.color,
text: val,
textAnchor,
fontFamily: barTotalDataLabelsConfig.style.fontFamily,
fontSize: barTotalDataLabelsConfig.style.fontSize,
fontWeight: barTotalDataLabelsConfig.style.fontWeight
});
}
return totalDataLabelText;
}
}
const Series = _core.__apex_Series;
const Fill = _core.__apex_Fill;
const Utils = _core.__apex_Utils;
class Helpers {
/**
* @param {Record<string, any>} barCtx
*/
constructor(barCtx) {
this.w = barCtx.w;
this.barCtx = barCtx;
}
/**
* @param {any[]} series
*/
initVariables(series) {
const w = this.w;
this.barCtx.series = series;
this.barCtx.totalItems = 0;
this.barCtx.seriesLen = 0;
this.barCtx.visibleI = -1;
this.barCtx.visibleItems = 1;
for (let sl = 0; sl < series.length; sl++) {
if (series[sl].length > 0) {
this.barCtx.seriesLen = this.barCtx.seriesLen + 1;
this.barCtx.totalItems += series[sl].length;
}
if (w.axisFlags.isXNumeric) {
for (let j = 0; j < series[sl].length; j++) {
if (w.seriesData.seriesX[sl][j] > w.globals.minX && w.seriesData.seriesX[sl][j] < w.globals.maxX) {
this.barCtx.visibleItems++;
}
}
} else {
this.barCtx.visibleItems = w.globals.dataPoints;
}
}
this.arrBorderRadius = this.createBorderRadiusArr(w.seriesData.series);
if (Utils.isSafari()) {
this.arrBorderRadius = this.arrBorderRadius.map(
(brArr) => (
/**
* @param {any} _
*/
brArr.map((_) => "none")
)
);
}
if (this.barCtx.seriesLen === 0) {
this.barCtx.seriesLen = 1;
}
this.barCtx.zeroSerieses = [];
if (!w.globals.comboCharts) {
this.checkZeroSeries({ series });
}
}
/**
* @param {number} realIndex
*/
initialPositions(realIndex) {
const w = this.w;
let x, y, yDivision, xDivision, barHeight, barWidth, zeroH, zeroW;
let dataPoints = w.globals.dataPoints;
if (this.barCtx.isRangeBar) {
dataPoints = w.labelData.labels.length;
}
let seriesLen = this.barCtx.seriesLen;
if (w.config.plotOptions.bar.rangeBarGroupRows) {
seriesLen = 1;
}
if (this.barCtx.isHorizontal) {
yDivision = w.layout.gridHeight / dataPoints;
barHeight = yDivision / seriesLen;
if (w.axisFlags.isXNumeric) {
yDivision = w.layout.gridHeight / this.barCtx.totalItems;
barHeight = yDivision / this.barCtx.seriesLen;
}
barHeight = barHeight * parseInt(this.barCtx.barOptions.barHeight, 10) / 100;
if (String(this.barCtx.barOptions.barHeight).indexOf("%") === -1) {
barHeight = parseInt(this.barCtx.barOptions.barHeight, 10);
}
zeroW = this.barCtx.baseLineInvertedY + w.globals.padHorizontal + (this.barCtx.isReversed ? w.layout.gridWidth : 0) - (this.barCtx.isReversed ? this.barCtx.baseLineInvertedY * 2 : 0);
if (this.barCtx.isFunnel) {
zeroW = w.layout.gridWidth / 2;
}
y = (yDivision - barHeight * this.barCtx.seriesLen) / 2;
} else {
xDivision = w.layout.gridWidth / this.barCtx.visibleItems;
if (w.config.xaxis.convertedCatToNumeric) {
xDivision = w.layout.gridWidth / w.globals.dataPoints;
}
barWidth = xDivision / seriesLen * parseInt(this.barCtx.barOptions.columnWidth, 10) / 100;
if (w.axisFlags.isXNumeric) {
const xRatio = this.barCtx.xRatio;
if (w.globals.minXDiff && w.globals.minXDiff !== 0.5 && w.globals.minXDiff / xRatio > 0) {
xDivision = w.globals.minXDiff / xRatio;
}
barWidth = xDivision / seriesLen * parseInt(this.barCtx.barOptions.columnWidth, 10) / 100;
if (barWidth < 1) {
barWidth = 1;
}
}
if (String(this.barCtx.barOptions.columnWidth).indexOf("%") === -1) {
barWidth = parseInt(this.barCtx.barOptions.columnWidth, 10);
}
zeroH = w.layout.gridHeight - this.barCtx.baseLineY[this.barCtx.translationsIndex] - (this.barCtx.isReversed ? w.layout.gridHeight : 0) + (this.barCtx.isReversed ? this.barCtx.baseLineY[this.barCtx.translationsIndex] * 2 : 0);
if (w.axisFlags.isXNumeric) {
const xForNumericX = this.barCtx.getBarXForNumericXAxis({
x,
j: 0,
realIndex,
barWidth
});
x = xForNumericX.x;
} else {
x = w.globals.padHorizontal + Utils.noExponents(xDivision - barWidth * this.barCtx.seriesLen) / 2;
}
}
w.globals.barHeight = barHeight;
w.globals.barWidth = barWidth;
return {
x,
y,
yDivision,
xDivision,
barHeight,
barWidth,
zeroH,
zeroW
};
}
/**
* @param {Record<string, any>} ctx
*/
initializeStackedPrevVars(ctx) {
const w = ctx.w;
w.labelData.seriesGroups.forEach((group) => {
if (!ctx[group]) ctx[group] = {};
ctx[group].prevY = [];
ctx[group].prevX = [];
ctx[group].prevYF = [];
ctx[group].prevXF = [];
ctx[group].prevYVal = [];
ctx[group].prevXVal = [];
});
}
/**
* @param {Record<string, any>} ctx
*/
initializeStackedXYVars(ctx) {
const w = ctx.w;
w.labelData.seriesGroups.forEach((group) => {
if (!ctx[group]) ctx[group] = {};
ctx[group].xArrj = [];
ctx[group].xArrjF = [];
ctx[group].xArrjVal = [];
ctx[group].yArrj = [];
ctx[group].yArrjF = [];
ctx[group].yArrjVal = [];
});
}
/**
* @param {any[]} series
* @param {number} i
* @param {number} j
* @param {number} realIndex
*/
getPathFillColor(series, i, j, realIndex) {
var _a, _b, _c, _d;
const w = this.w;
const fill = new Fill(this.barCtx.w);
let fillColor = null;
const seriesNumber = this.barCtx.barOptions.distributed ? j : i;
let useRangeColor = false;
if (this.barCtx.barOptions.colors.ranges.length > 0) {
const colorRange = this.barCtx.barOptions.colors.ranges;
colorRange.map((range) => {
if (series[i][j] >= range.from && series[i][j] <= range.to) {
fillColor = range.color;
useRangeColor = true;
}
});
}
const pathFill = fill.fillPath({
seriesNumber: this.barCtx.barOptions.distributed ? seriesNumber : realIndex,
dataPointIndex: j,
color: fillColor,
value: series[i][j],
fillConfig: (_a = w.config.series[i].data[j]) == null ? void 0 : _a.fill,
fillType: ((_c = (_b = w.config.series[i].data[j]) == null ? void 0 : _b.fill) == null ? void 0 : _c.type) ? (_d = w.config.series[i].data[j]) == null ? void 0 : _d.fill.type : Array.isArray(w.config.fill.type) ? w.config.fill.type[realIndex] : w.config.fill.type
});
return {
color: pathFill,
useRangeColor
};
}
/**
* @param {number} i
* @param {number} j
* @param {number} realIndex
*/
getStrokeWidth(i, j, realIndex) {
let strokeWidth = 0;
const w = this.w;
if (typeof this.barCtx.series[i][j] === "undefined" || this.barCtx.series[i][j] === null || w.config.chart.type === "bar" && !this.barCtx.series[i][j]) {
this.barCtx.isNullValue = true;
} else {
this.barCtx.isNullValue = false;
}
if (w.config.stroke.show) {
if (!this.barCtx.isNullValue) {
strokeWidth = Array.isArray(this.barCtx.strokeWidth) ? this.barCtx.strokeWidth[realIndex] : this.barCtx.strokeWidth;
}
}
return strokeWidth;
}
/**
* @param {any[]} series
*/
createBorderRadiusArr(series) {
var _a;
const w = this.w;
const alwaysApplyRadius = !this.w.config.chart.stacked || w.config.plotOptions.bar.borderRadius <= 0;
const numSeries = series.length;
const numColumns = ((_a = series[0]) == null ? void 0 : _a.length) | 0;
const output = Array.from(
{ length: numSeries },
() => Array(numColumns).fill(alwaysApplyRadius ? "top" : "none")
);
if (alwaysApplyRadius) return output;
const chartType = this.w.config.chart.type;
for (let j = 0; j < numColumns; j++) {
const positiveIndices = [];
const negativeIndices = [];
let nonZeroCount = 0;
for (let i = 0; i < numSeries; i++) {
const value = series[i][j];
if (value > 0) {
positiveIndices.push(i);
nonZeroCount++;
} else if (value < 0) {
negativeIndices.push(i);
nonZeroCount++;
}
}
if (positiveIndices.length > 0 && negativeIndices.length === 0) {
if (positiveIndices.length === 1) {
output[positiveIndices[0]][j] = chartType === "bar" && numColumns === 1 ? "top" : "both";
} else {
const firstPositiveIndex = positiveIndices[0];
const lastPositiveIndex = positiveIndices[positiveIndices.length - 1];
for (const i of positiveIndices) {
if (i === firstPositiveIndex) {
output[i][j] = chartType === "bar" && numColumns === 1 ? "top" : "bottom";
} else if (i === lastPositiveIndex) {
output[i][j] = "top";
} else {
output[i][j] = "none";
}
}
}
} else if (negativeIndices.length > 0 && positiveIndices.length === 0) {
if (negativeIndices.length === 1) {
output[negativeIndices[0]][j] = "both";
} else {
const highestNegativeIndex = Math.max(...negativeIndices);
const lowestNegativeIndex = Math.min(...negativeIndices);
for (const i of negativeIndices) {
if (i === highestNegativeIndex) {
output[i][j] = "bottom";
} else if (i === lowestNegativeIndex) {
output[i][j] = "top";
} else {
output[i][j] = "none";
}
}
}
} else if (positiveIndices.length > 0 && negativeIndices.length > 0) {
const lastPositiveIndex = positiveIndices[positiveIndices.length - 1];
for (const i of positiveIndices) {
if (i === lastPositiveIndex) {
output[i][j] = "top";
} else {
output[i][j] = "none";
}
}
const highestNegativeIndex = Math.max(...negativeIndices);
for (const i of negativeIndices) {
if (i === highestNegativeIndex) {
output[i][j] = "bottom";
} else {
output[i][j] = "none";
}
}
} else if (nonZeroCount === 1) {
const index = positiveIndices[0] || negativeIndices[0];
output[index][j] = "both";
}
}
return output;
}
/** @param {{ j?: any, i?: any, x1?: any, x2?: any, y1?: any, y2?: any, bc?: any, elSeries?: any }} opts */
barBackground({ j, i, x1, x2, y1, y2, elSeries }) {
const w = this.w;
const graphics = new Graphics(this.barCtx.w);
const sr = new Series(this.barCtx.w);
const activeSeriesIndex = sr.getActiveConfigSeriesIndex();
if (this.barCtx.barOptions.colors.backgroundBarColors.length > 0 && activeSeriesIndex === i) {
if (j >= this.barCtx.barOptions.colors.backgroundBarColors.length) {
j %= this.barCtx.barOptions.colors.backgroundBarColors.length;
}
const bcolor = this.barCtx.barOptions.colors.backgroundBarColors[j];
const rect = graphics.drawRect(
typeof x1 !== "undefined" ? x1 : 0,
typeof y1 !== "undefined" ? y1 : 0,
typeof x2 !== "undefined" ? x2 : w.layout.gridWidth,
typeof y2 !== "undefined" ? y2 : w.layout.gridHeight,
this.barCtx.barOptions.colors.backgroundBarRadius,
bcolor,
this.barCtx.barOptions.colors.backgroundBarOpacity
);
elSeries.add(rect);
rect.node.classList.add("apexcharts-backgroundBar");
}
}
/** @param {{ barWidth?: any, barXPosition?: any, y1?: any, y2?: any, yRatio?: any, strokeWidth?: any, isReversed?: any, series?: any, seriesGroup?: any, realIndex?: any, i?: any, j?: any, w?: any }} opts */
getColumnPaths({
barWidth,
barXPosition,
y1,
y2,
strokeWidth,
isReversed,
series,
seriesGroup,
realIndex,
i,
j,
w
}) {
var _a, _b, _c;
const graphics = new Graphics(this.barCtx.w);
strokeWidth = Array.isArray(strokeWidth) ? strokeWidth[realIndex] : strokeWidth;
if (!strokeWidth) strokeWidth = 0;
let bW = barWidth;
let bXP = barXPosition;
if ((_a = w.config.series[realIndex].data[j]) == null ? void 0 : _a.columnWidthOffset) {
bXP = barXPosition - w.config.series[realIndex].data[j].columnWidthOffset / 2;
bW = barWidth + w.config.series[realIndex].data[j].columnWidthOffset;
}
const strokeCenter = strokeWidth / 2;
const x1 = bXP + strokeCenter;
const x2 = bXP + bW - strokeCenter;
const direction = (series[i][j] >= 0 ? 1 : -1) * (isReversed ? -1 : 1);
y1 += 1e-3 - strokeCenter * direction;
y2 += 1e-3 + strokeCenter * direction;
const sl = graphics.line(x2, y1);
const closing = w.config.plotOptions.bar.borderRadiusApplication === "around" || this.arrBorderRadius[realIndex][j] === "both" ? " Z" : " z";
let pathTo = graphics.move(x1, y1) + graphics.line(x1, y2) + graphics.line(x2, y2) + sl + closing;
if (this.arrBorderRadius[realIndex][j] !== "none") {
pathTo = graphics.roundPathCorners(
pathTo,
w.config.plotOptions.bar.borderRadius
);
}
let pathFrom = null;
const morphFrom = (_c = (_b = this.barCtx.ctx) == null ? void 0 : _b.morphTypeChange) == null ? void 0 : _c.getInitialPathFor(
realIndex,
j
);
if (morphFrom) {
pathFrom = morphFrom;
} else if (w.globals.previousPaths.length > 0) {
pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo);
}
if (pathFrom == null) {
pathFrom = graphics.move(x1, y1) + graphics.line(x1, y1) + sl + sl + sl + sl + sl + graphics.line(x1, y1) + closing;
}
if (w.config.chart.stacked) {
let _ctx = this.barCtx;
_ctx = this.barCtx[seriesGroup];
_ctx.yArrj.push(y2 - strokeCenter * direction);
_ctx.yArrjF.push(Math.abs(y1 - y2 + strokeWidth * direction));
_ctx.yArrjVal.push(this.barCtx.series[i][j]);
}
return {
pathTo,
pathFrom
};
}
/**
* Build a trapezoidal funnel-stage path. Used when
* `plotOptions.funnel.shape === 'trapezoid'` is active alongside `isFunnel`.
*
* Each stage is a 4-corner polygon whose top width matches the current
* stage's value and bottom width matches the next stage's value, producing
* continuous sloped sides between consecutive stages.
*
* For the last stage, the bottom width is configurable:
* - `lastShape: 'flat'` → bottom width = top width (parallel sides)
* - `lastShape: 'taper'` → bottom width = 0 (taper to a point)
*
* @param {{ barYPosition: number, barHeight: number, series: any[][], i: number, j: number, realIndex: number, strokeWidth: number, w: any }} opts
*/
getFunnelTrapezoidPaths({
barYPosition,
barHeight,
series,
i,
j,
realIndex,
strokeWidth,
w
}) {
var _a, _b;
const graphics = new Graphics(this.barCtx.w);
const center = w.layout.gridWidth / 2;
const halfWidthFor = (v) => Math.abs(v / this.barCtx.invertedYRatio) / 2;
const topHalf = halfWidthFor(series[i][j]);
const lastIdx = series[i].length - 1;
const isLast = j === lastIdx;
const lastShape = w.config.plotOptions.funnel.lastShape === "taper" ? "taper" : "flat";
let bottomHalf;
if (isLast) {
bottomHalf = lastShape === "taper" ? 0 : topHalf;
} else {
bottomHalf = halfWidthFor(series[i][j + 1]);
}
const strokeCenter = strokeWidth / 2;
const y1 = barYPosition + strokeCenter;
const y2 = barYPosition + barHeight - strokeCenter;
const topLeftX = center - topHalf;
const topRightX = center + topHalf;
const bottomLeftX = center - bottomHalf;
const bottomRightX = center + bottomHalf;
const pathTo = graphics.move(topLeftX, y1) + graphics.line(topRightX, y1) + graphics.line(bottomRightX, y2) + graphics.line(bottomLeftX, y2) + " Z";
let pathFrom = null;
const morphFrom = (_b = (_a = this.barCtx.ctx) == null ? void 0 : _a.morphTypeChange) == null ? void 0 : _b.getInitialPathFor(
realIndex,
j
);
if (morphFrom) {
pathFrom = morphFrom;
} else if (w.globals.previousPaths.length > 0) {
pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo);
}
if (pathFrom == null) {
pathFrom = graphics.move(center, y1) + graphics.line(center, y1) + graphics.line(center, y2) + graphics.line(center, y2) + " Z";
}
return {
pathTo,
pathFrom,
// x is the right edge of the wider (top) side — used by dataLabel
// positioning helpers that expect a "right" reference.
x: topRightX,
x1: topLeftX,
barXPosition: center
};
}
/**
* Pre-compute the per-segment layout for a value-proportional pyramid.
*
* Each segment is a horizontal slice of a triangle whose apex sits at the
* top of the plot area (width = 0) and whose base spans `gridWidth` at the
* bottom. The vertical extent of each slice is its share of the total
* series value, so areas track value contribution and segments share
* edges (no gaps). The first data point is the apex, the last is the base.
*
* @param {any[]} seriesData - 1D array of values for a single series row
* @returns {{ y: number, height: number, topHalf: number, bottomHalf: number }[]}
*/
computePyramidLayout(seriesData) {
const w = this.w;
const gridHeight = w.layout.gridHeight;
const gridWidth = w.layout.gridWidth;
const values = seriesData.map(
/** @param {any} v */
(v) => Math.abs(Number(v) || 0)
);
const total = values.reduce(
/** @param {number} a @param {number} b */
(a, b) => a + b,
0
);
if (total === 0 || gridHeight <= 0) {
return values.map(() => ({ y: 0, height: 0, topHalf: 0, bottomHalf: 0 }));
}
const halfWidth = gridWidth / 2;
let cumulative = 0;
const layout = [];
for (let j = 0; j < values.length; j++) {
const topRatio = cumulative / total;
cumulative += values[j];
const bottomRatio = cumulative / total;
const topY = topRatio * gridHeight;
const bottomY = bottomRatio * gridHeight;
layout.push({
y: topY,
height: bottomY - topY,
topHalf: topRatio * halfWidth,
bottomHalf: bottomRatio * halfWidth
});
}
return layout;
}
/**
* Build a single pyramid stage path. Geometry is precomputed by
* `computePyramidLayout`; this method only renders that geometry into an
* SVG path string plus a `pathFrom` for entry/morph animations.
*
* @param {{ barYPosition: number, barHeight: number, topHalf: number, bottomHalf: number, realIndex: number, j: number, strokeWidth: number, w: any }} opts
*/
getPyramidPaths({
barYPosition,
barHeight,
topHalf,
bottomHalf,
realIndex,
j,
strokeWidth,
w
}) {
var _a, _b;
const graphics = new Graphics(this.barCtx.w);
const center = w.layout.gridWidth / 2;
const strokeCenter = strokeWidth / 2;
const y1 = barYPosition + strokeCenter;
const y2 = barYPosition + barHeight - strokeCenter;
const topLeftX = center - topHalf;
const topRightX = center + topHalf;
const bottomLeftX = center - bottomHalf;
const bottomRightX = center + bottomHalf;
const pathTo = graphics.move(topLeftX, y1) + graphics.line(topRightX, y1) + graphics.line(bottomRightX, y2) + graphics.line(bottomLeftX, y2) + " Z";
let pathFrom = null;
const morphFrom = (_b = (_a = this.barCtx.ctx) == null ? void 0 : _a.morphTypeChange) == null ? void 0 : _b.getInitialPathFor(
realIndex,
j
);
if (morphFrom) {
pathFrom = morphFrom;
} else if (w.globals.previousPaths.length > 0) {
pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo);
}
if (pathFrom == null) {
pathFrom = graphics.move(center, y1) + graphics.line(center, y1) + graphics.line(center, y2) + graphics.line(center, y2) + " Z";
}
return {
pathTo,
pathFrom,
x: topRightX,
x1: topLeftX,
barXPosition: center
};
}
/** @param {{ barYPosition?: any, barHeight?: any, x1?: any, x2?: any, strokeWidth?: any, isReversed?: any, series?: any, seriesGroup?: any, realIndex?: any, i?: any, j?: any, w?: any }} opts */
getBarpaths({
barYPosition,
barHeight,
x1,
x2,
strokeWidth,
isReversed,
series,
seriesGroup,
realIndex,
i,
j,
w
}) {
var _a, _b, _c;
const graphics = new Graphics(this.barCtx.w);
strokeWidth = Array.isArray(strokeWidth) ? strokeWidth[realIndex] : strokeWidth;
if (!strokeWidth) strokeWidth = 0;
let bYP = barYPosition;
let bH = barHeight;
if ((_a = w.config.series[realIndex].data[j]) == null ? void 0 : _a.barHeightOffset) {
bYP = barYPosition - w.config.series[realIndex].data[j].barHeightOffset / 2;
bH = barHeight + w.config.series[realIndex].data[j].barHeightOffset;
}
const strokeCenter = strokeWidth / 2;
const y1 = bYP + strokeCenter;
const y2 = bYP + bH - strokeCenter;
const direction = (series[i][j] >= 0 ? 1 : -1) * (isReversed ? -1 : 1);
x1 += 1e-3 + strokeCenter * direction;
x2 += 1e-3 - strokeCenter * direction;
const isFunnel = this.barCtx.isFunnel;
const fromX = isFunnel ? (x1 + x2) / 2 : x1;
const sl = graphics.line(x1, y2);
const closing = w.config.plotOptions.bar.borderRadiusApplication === "around" || this.arrBorderRadius[realIndex][j] === "both" ? " Z" : " z";
let pathTo = graphics.move(x1, y1) + graphics.line(x2, y1) + graphics.line(x2, y2) + sl + closing;
if (this.arrBorderRadius[realIndex][j] !== "none") {
pathTo = graphics.roundPathCorners(
pathTo,
w.config.plotOptions.bar.borderRadius
);
}
let pathFrom = null;
const morphFrom = (_c = (_b = this.barCtx.ctx) == null ? void 0 : _b.morphTypeChange) == null ? void 0 : _c.getInitialPathFor(
realIndex,
j
);
if (morphFrom) {
pathFrom = morphFrom;
} else if (w.globals.previousPaths.length > 0) {
pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo);
}
if (pathFrom == null) {
const slFrom = isFunnel ? graphics.line(fromX, y2) : sl;
pathFrom = graphics.move(fromX, y1) + graphics.line(fromX, y1) + slFrom + slFrom + slFrom + slFrom + slFrom + graphics.line(fromX, y1) + closing;
}
if (w.config.chart.stacked) {
let _ctx = this.barCtx;
_ctx = this.barCtx[seriesGroup];
_ctx.xArrj.push(x2 + strokeCenter * direction);
_ctx.xArrjF.push(Math.abs(x1 - x2 - strokeWidth * direction));
_ctx.xArrjVal.push(this.barCtx.series[i][j]);
}
return {
pathTo,
pathFrom
};
}
/** @param {{series: any}} opts */
checkZeroSeries({ series }) {
const w = this.w;
for (let zs = 0; zs < series.length; zs++) {
let total = 0;
for (let zsj = 0; zsj < series[w.globals.maxValsInArrayIndex].length; zsj++) {
total += series[zs][zsj];
}
if (total === 0) {
this.barCtx.zeroSerieses.push(zs);
}
}
}
/**
* @param {number} value
* @param {number} zeroW
*/
getXForValue(value, zeroW, zeroPositionForNull = true) {
let xForVal = zeroPositionForNull ? zeroW : null;
if (typeof value !== "undefined" && value !== null) {
xForVal = zeroW + value / this.barCtx.invertedYRatio - (this.barCtx.isReversed ? value / this.barCtx.invertedYRatio : 0) * 2;
}
return xForVal;
}
/**
* @param {number} value
* @param {number} zeroH
* @param {number} translationsIndex
*/
getYForValue(value, zeroH, translationsIndex, zeroPositionForNull = true) {
let yForVal = zeroPositionForNull ? zeroH : null;
if (typeof value !== "undefined" && value !==