apexcharts 8.2.0 → 8.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/README.md +7 -7
  2. package/dist/apexcharts.common.js +2 -2
  3. package/dist/apexcharts.core.js +271 -173
  4. package/dist/apexcharts.core.min.js +2 -2
  5. package/dist/apexcharts.css +35 -0
  6. package/dist/apexcharts.esm.js +1722 -1527
  7. package/dist/apexcharts.full.js +1459 -1075
  8. package/dist/apexcharts.full.min.js +2 -2
  9. package/dist/apexcharts.js +994 -715
  10. package/dist/apexcharts.min.js +2 -2
  11. package/dist/apexcharts.ssr.common.js +2 -2
  12. package/dist/apexcharts.ssr.esm.js +994 -715
  13. package/dist/area.common.js +2 -2
  14. package/dist/area.esm.js +91 -40
  15. package/dist/bar.common.js +2 -2
  16. package/dist/bar.esm.js +433 -394
  17. package/dist/bar.js +2 -2
  18. package/dist/boxPlot.common.js +2 -2
  19. package/dist/boxPlot.esm.js +364 -322
  20. package/dist/bubble.common.js +2 -2
  21. package/dist/bubble.esm.js +91 -40
  22. package/dist/candlestick.common.js +2 -2
  23. package/dist/candlestick.esm.js +364 -322
  24. package/dist/candlestick.js +2 -2
  25. package/dist/column.common.js +2 -2
  26. package/dist/column.esm.js +433 -394
  27. package/dist/core.common.js +2 -2
  28. package/dist/core.esm.js +271 -173
  29. package/dist/donut.common.js +1 -1
  30. package/dist/donut.esm.js +1 -1
  31. package/dist/dumbbell.common.js +2 -2
  32. package/dist/dumbbell.esm.js +433 -394
  33. package/dist/features/all.common.js +2 -2
  34. package/dist/features/all.esm.js +250 -187
  35. package/dist/features/annotations.common.js +1 -1
  36. package/dist/features/annotations.esm.js +1 -1
  37. package/dist/features/annotations.js +1 -1
  38. package/dist/features/context-menu.common.js +1 -1
  39. package/dist/features/context-menu.esm.js +1 -1
  40. package/dist/features/context-menu.js +1 -1
  41. package/dist/features/drilldown.common.js +2 -2
  42. package/dist/features/drilldown.esm.js +4 -2
  43. package/dist/features/drilldown.js +2 -2
  44. package/dist/features/dumbbell.common.js +1 -1
  45. package/dist/features/dumbbell.esm.js +1 -1
  46. package/dist/features/dumbbell.js +1 -1
  47. package/dist/features/exports.common.js +1 -1
  48. package/dist/features/exports.esm.js +1 -1
  49. package/dist/features/exports.js +1 -1
  50. package/dist/features/facet.common.js +1 -1
  51. package/dist/features/facet.esm.js +1 -1
  52. package/dist/features/facet.js +1 -1
  53. package/dist/features/highlight-filter.common.js +2 -2
  54. package/dist/features/highlight-filter.esm.js +14 -9
  55. package/dist/features/highlight-filter.js +2 -2
  56. package/dist/features/history.common.js +1 -1
  57. package/dist/features/history.esm.js +1 -1
  58. package/dist/features/history.js +1 -1
  59. package/dist/features/ink.common.js +1 -1
  60. package/dist/features/ink.esm.js +1 -1
  61. package/dist/features/ink.js +1 -1
  62. package/dist/features/keyboard.common.js +2 -2
  63. package/dist/features/keyboard.esm.js +97 -145
  64. package/dist/features/keyboard.js +2 -2
  65. package/dist/features/legend.common.js +2 -2
  66. package/dist/features/legend.esm.js +63 -43
  67. package/dist/features/legend.js +2 -2
  68. package/dist/features/link.common.js +1 -1
  69. package/dist/features/link.esm.js +1 -1
  70. package/dist/features/link.js +1 -1
  71. package/dist/features/marks.common.js +1 -1
  72. package/dist/features/marks.esm.js +1 -1
  73. package/dist/features/marks.js +1 -1
  74. package/dist/features/measure.common.js +1 -1
  75. package/dist/features/measure.esm.js +1 -1
  76. package/dist/features/measure.js +1 -1
  77. package/dist/features/morph.common.js +1 -1
  78. package/dist/features/morph.esm.js +1 -1
  79. package/dist/features/morph.js +1 -1
  80. package/dist/features/perspectives.common.js +1 -1
  81. package/dist/features/perspectives.esm.js +1 -1
  82. package/dist/features/perspectives.js +1 -1
  83. package/dist/features/raincloud.common.js +1 -1
  84. package/dist/features/raincloud.esm.js +1 -1
  85. package/dist/features/raincloud.js +1 -1
  86. package/dist/features/renderer-canvas.common.js +2 -2
  87. package/dist/features/renderer-canvas.esm.js +2 -1
  88. package/dist/features/renderer-canvas.js +2 -2
  89. package/dist/features/stats.common.js +1 -1
  90. package/dist/features/stats.esm.js +1 -1
  91. package/dist/features/stats.js +1 -1
  92. package/dist/features/storyboard.common.js +1 -1
  93. package/dist/features/storyboard.esm.js +1 -1
  94. package/dist/features/storyboard.js +1 -1
  95. package/dist/features/streamgraph.common.js +2 -2
  96. package/dist/features/streamgraph.esm.js +3 -2
  97. package/dist/features/streamgraph.js +2 -2
  98. package/dist/features/toolbar.common.js +2 -2
  99. package/dist/features/toolbar.esm.js +92 -2
  100. package/dist/features/toolbar.js +2 -2
  101. package/dist/features/trellis.common.js +2 -2
  102. package/dist/features/trellis.esm.js +83 -47
  103. package/dist/features/trellis.js +2 -2
  104. package/dist/features/waterfall.common.js +1 -1
  105. package/dist/features/waterfall.esm.js +1 -1
  106. package/dist/features/waterfall.js +1 -1
  107. package/dist/features/weave.common.js +1 -1
  108. package/dist/features/weave.esm.js +1 -1
  109. package/dist/features/weave.js +1 -1
  110. package/dist/full.common.js +2 -2
  111. package/dist/full.esm.js +950 -795
  112. package/dist/heatmap.common.js +2 -2
  113. package/dist/heatmap.esm.js +3 -17
  114. package/dist/heatmap.js +2 -2
  115. package/dist/histogram.common.js +2 -2
  116. package/dist/histogram.esm.js +433 -394
  117. package/dist/icicle.common.js +2 -2
  118. package/dist/icicle.esm.js +54 -38
  119. package/dist/icicle.js +2 -2
  120. package/dist/line.common.js +2 -2
  121. package/dist/line.esm.js +91 -40
  122. package/dist/line.js +2 -2
  123. package/dist/locales/en.json +2 -1
  124. package/dist/locales/ro.json +3 -2
  125. package/dist/pictograms.common.js +1 -1
  126. package/dist/pictograms.esm.js +1 -1
  127. package/dist/pictograms.js +1 -1
  128. package/dist/pie.common.js +1 -1
  129. package/dist/pie.esm.js +1 -1
  130. package/dist/pie.js +1 -1
  131. package/dist/polarArea.common.js +1 -1
  132. package/dist/polarArea.esm.js +1 -1
  133. package/dist/radar.common.js +2 -2
  134. package/dist/radar.esm.js +5 -4
  135. package/dist/radar.js +2 -2
  136. package/dist/radialBar.common.js +1 -1
  137. package/dist/radialBar.esm.js +1 -1
  138. package/dist/radialBar.js +1 -1
  139. package/dist/raincloud.common.js +2 -2
  140. package/dist/raincloud.esm.js +72 -26
  141. package/dist/rangeArea.common.js +2 -2
  142. package/dist/rangeArea.esm.js +91 -40
  143. package/dist/rangeBar.common.js +2 -2
  144. package/dist/rangeBar.esm.js +433 -394
  145. package/dist/scatter.common.js +2 -2
  146. package/dist/scatter.esm.js +91 -40
  147. package/dist/streamgraph.common.js +2 -2
  148. package/dist/streamgraph.esm.js +93 -41
  149. package/dist/sunburst.common.js +2 -2
  150. package/dist/sunburst.esm.js +103 -93
  151. package/dist/sunburst.js +2 -2
  152. package/dist/treemap.common.js +2 -2
  153. package/dist/treemap.esm.js +105 -86
  154. package/dist/treemap.js +2 -2
  155. package/dist/unit-shapes.common.js +1 -1
  156. package/dist/unit-shapes.esm.js +1 -1
  157. package/dist/unit-shapes.js +1 -1
  158. package/dist/unit.common.js +2 -2
  159. package/dist/unit.esm.js +280 -202
  160. package/dist/unit.js +2 -2
  161. package/dist/violin.common.js +2 -2
  162. package/dist/violin.esm.js +72 -26
  163. package/dist/violin.js +2 -2
  164. package/dist/waterfall.common.js +2 -2
  165. package/dist/waterfall.esm.js +432 -393
  166. package/package.json +1 -1
  167. package/src/apexcharts.js +13 -6
  168. package/src/assets/apexcharts.css +35 -0
  169. package/src/charts/Bar.js +62 -55
  170. package/src/charts/BarStacked.js +80 -88
  171. package/src/charts/BoxCandleStick.js +28 -31
  172. package/src/charts/Icicle.js +37 -37
  173. package/src/charts/Line.js +118 -42
  174. package/src/charts/Radar.js +5 -7
  175. package/src/charts/RangeBar.js +47 -43
  176. package/src/charts/Sunburst.js +101 -98
  177. package/src/charts/Treemap.js +108 -66
  178. package/src/charts/Unit.js +368 -250
  179. package/src/charts/Violin.js +48 -30
  180. package/src/charts/common/Breadcrumb.js +2 -2
  181. package/src/charts/common/Hierarchy.js +32 -11
  182. package/src/charts/common/Jitter.js +32 -7
  183. package/src/charts/common/bar/DataLabels.js +76 -81
  184. package/src/charts/common/bar/Helpers.js +43 -7
  185. package/src/charts/common/line/Helpers.js +12 -15
  186. package/src/charts/common/partition/NodeTooltip.js +8 -1
  187. package/src/charts/common/partition/Partition.js +33 -1
  188. package/src/charts/common/treemap/Helpers.js +3 -11
  189. package/src/locales/en.json +2 -1
  190. package/src/locales/ro.json +3 -2
  191. package/src/modules/Core.js +4 -0
  192. package/src/modules/CoreUtils.js +18 -42
  193. package/src/modules/Data.js +23 -24
  194. package/src/modules/DataLabels.js +6 -6
  195. package/src/modules/Graphics.js +62 -49
  196. package/src/modules/Markers.js +3 -1
  197. package/src/modules/Range.js +44 -29
  198. package/src/modules/RendererController.js +17 -3
  199. package/src/modules/Scales.js +32 -9
  200. package/src/modules/Series.js +39 -18
  201. package/src/modules/Theme.js +1 -1
  202. package/src/modules/ZoomPanSelection.js +119 -2
  203. package/src/modules/accessibility/KeyboardNavigation.js +114 -186
  204. package/src/modules/animations/LengthTransition.js +22 -2
  205. package/src/modules/drilldown/Breadcrumb.js +5 -2
  206. package/src/modules/helpers/Destroy.js +1 -1
  207. package/src/modules/highlightFilter/HighlightFilter.js +8 -9
  208. package/src/modules/highlightFilter/TreemapPart.js +2 -2
  209. package/src/modules/legend/HeatmapGradientLegend.js +76 -45
  210. package/src/modules/legend/Helpers.js +2 -0
  211. package/src/modules/legend/Legend.js +11 -12
  212. package/src/modules/settings/Options.js +7 -0
  213. package/src/modules/streamgraph/StreamLabels.js +1 -0
  214. package/src/modules/tooltip/Tooltip.js +20 -4
  215. package/src/modules/tooltip/Utils.js +8 -0
  216. package/src/modules/trellis/Trellis.js +6 -0
  217. package/src/modules/trellis/TrellisChrome.js +18 -7
  218. package/src/modules/trellis/TrellisSync.js +2 -0
  219. package/src/renderers/canvas/CanvasGraphics.js +1 -0
  220. package/src/ssr/DOMShim.js +10 -0
  221. package/src/types/internal.d.ts +9 -3
  222. package/types/apexcharts.d.ts +31 -12
@@ -31,7 +31,7 @@ var __objRest = (source, exclude) => {
31
31
  };
32
32
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
33
33
  /*!
34
- * ApexCharts v8.2.0
34
+ * ApexCharts v8.3.0
35
35
  * (c) 2018-2026 ApexCharts
36
36
  */
37
37
  import * as _core from "apexcharts/core";
@@ -1142,6 +1142,7 @@ let Helpers$3 = class Helpers {
1142
1142
  toggleDataSeries(seriesCnt, isHidden) {
1143
1143
  var _a, _b, _c;
1144
1144
  const w = this.w;
1145
+ if (!w.dom.baseEl) return;
1145
1146
  if (w.globals.axisCharts || w.config.chart.type === "radialBar") {
1146
1147
  w.globals.resized = true;
1147
1148
  let seriesEl = null;
@@ -1611,9 +1612,11 @@ class HeatmapGradientLegend {
1611
1612
  this._min = 0;
1612
1613
  this._max = 0;
1613
1614
  this._geom = null;
1615
+ this._grad = null;
1614
1616
  this._bandHitEls = [];
1615
1617
  this._activeBandIndex = -1;
1616
1618
  this._targetEl = null;
1619
+ this.panelsW = null;
1617
1620
  this._onCellEnter = this._onCellEnter.bind(this);
1618
1621
  this._onCellLeave = this._onCellLeave.bind(this);
1619
1622
  this._onBandEnter = this._onBandEnter.bind(this);
@@ -1728,15 +1731,8 @@ class HeatmapGradientLegend {
1728
1731
  linearGrad.setAttribute("x2", "1");
1729
1732
  linearGrad.setAttribute("y2", "0");
1730
1733
  }
1731
- const { min, max, stops, bands } = this._computeStops();
1732
- this._min = min;
1733
- this._max = max;
1734
- stops.forEach((s) => {
1735
- const stopEl = BrowserAPIs.createElementNS(SVG_NS, "stop");
1736
- stopEl.setAttribute("offset", `${(s.percent * 100).toFixed(2)}%`);
1737
- stopEl.setAttribute("stop-color", s.color);
1738
- linearGrad.appendChild(stopEl);
1739
- });
1734
+ this._grad = linearGrad;
1735
+ const { min, max, bands } = this._paintStops();
1740
1736
  defs.appendChild(linearGrad);
1741
1737
  svg.appendChild(defs);
1742
1738
  const rect = BrowserAPIs.createElementNS(SVG_NS, "rect");
@@ -1945,6 +1941,7 @@ class HeatmapGradientLegend {
1945
1941
  */
1946
1942
  repositionToPlot() {
1947
1943
  var _a, _b;
1944
+ if (this._grad) this._paintStops();
1948
1945
  if (!Environment.isBrowser()) return;
1949
1946
  if (this._targetEl) return;
1950
1947
  const w = this.w;
@@ -2079,14 +2076,25 @@ class HeatmapGradientLegend {
2079
2076
  if (idx < 0 || idx === this._activeBandIndex) return;
2080
2077
  this._activeBandIndex = idx;
2081
2078
  (_d = (_c = (_b = this.ctx) == null ? void 0 : _b.events) == null ? void 0 : _c.fireEvent) == null ? void 0 : _d.call(_c, "legendHover", [this.ctx, idx, w]);
2082
- new Series(w).highlightRangeInSeries(idx, "highlight");
2079
+ this._highlightRange(idx, "highlight");
2083
2080
  }
2084
2081
  /** Leaving a band clears the highlight. */
2085
2082
  _onBandLeave() {
2086
2083
  if (this._activeBandIndex < 0) return;
2087
2084
  const idx = this._activeBandIndex;
2088
2085
  this._activeBandIndex = -1;
2089
- new Series(this.w).highlightRangeInSeries(idx, "reset");
2086
+ this._highlightRange(idx, "reset");
2087
+ }
2088
+ /**
2089
+ * A shared trellis strip sets `panelsW` so a band reaches every panel.
2090
+ * @param {number} idx
2091
+ * @param {'highlight'|'reset'} action
2092
+ */
2093
+ _highlightRange(idx, action) {
2094
+ var _a;
2095
+ (((_a = this.panelsW) == null ? void 0 : _a.call(this)) || [this.w]).forEach(
2096
+ (w) => new Series(w).highlightRangeInSeries(idx, action)
2097
+ );
2090
2098
  }
2091
2099
  _attachHoverListeners() {
2092
2100
  var _a, _b;
@@ -2108,10 +2116,10 @@ class HeatmapGradientLegend {
2108
2116
  */
2109
2117
  _onCellEnter(...args) {
2110
2118
  var _a, _b, _c;
2111
- const w = this.w;
2112
2119
  if (!this.arrowEl) return;
2113
2120
  const opts = args[args.length - 1];
2114
2121
  if (!opts || typeof opts !== "object") return;
2122
+ const w = opts.w || this.w;
2115
2123
  const i = opts.seriesIndex;
2116
2124
  const j = opts.dataPointIndex;
2117
2125
  if (typeof i !== "number" || typeof j !== "number") return;
@@ -2223,6 +2231,21 @@ class HeatmapGradientLegend {
2223
2231
  polygon.setAttribute("pointer-events", "none");
2224
2232
  return polygon;
2225
2233
  }
2234
+ /** (Re)write the strip's stops; returns `_computeStops()`. */
2235
+ _paintStops() {
2236
+ const r = this._computeStops();
2237
+ const grad = this._grad;
2238
+ this._min = r.min;
2239
+ this._max = r.max;
2240
+ grad.innerHTML = "";
2241
+ r.stops.forEach((s) => {
2242
+ const stopEl = BrowserAPIs.createElementNS(SVG_NS, "stop");
2243
+ stopEl.setAttribute("offset", `${(s.percent * 100).toFixed(2)}%`);
2244
+ stopEl.setAttribute("stop-color", s.color);
2245
+ grad.appendChild(stopEl);
2246
+ });
2247
+ return r;
2248
+ }
2226
2249
  /**
2227
2250
  * Build gradient stops + return effective min/max.
2228
2251
  * - If `colorScale.ranges` is set, stops are placed at each range boundary
@@ -2264,7 +2287,8 @@ class HeatmapGradientLegend {
2264
2287
  if (!Number.isFinite(dataMax)) dataMax = 0;
2265
2288
  let min = dataMin;
2266
2289
  let max = dataMax;
2267
- if (typeof cs.min !== "undefined" && typeof cs.max !== "undefined" && cs.max > cs.min) {
2290
+ const csWindow = typeof cs.min !== "undefined" && typeof cs.max !== "undefined" && cs.max > cs.min;
2291
+ if (csWindow) {
2268
2292
  min = cs.min;
2269
2293
  max = cs.max;
2270
2294
  } else {
@@ -2295,34 +2319,30 @@ class HeatmapGradientLegend {
2295
2319
  } else {
2296
2320
  const baseColor = w.globals.colors[0] || "#008FFB";
2297
2321
  const utils = new Utils();
2298
- const plot = w.config.plotOptions[w.config.chart.type] || {};
2322
+ const type = w.config.chart.type;
2323
+ const plot = w.config.plotOptions[type] || {};
2299
2324
  const shadeIntensity = (_b = plot.shadeIntensity) != null ? _b : 0.5;
2300
- const hasNegs = (
2325
+ const g = (
2301
2326
  /** @type {any} */
2302
- w.globals.hasNegs
2327
+ w.globals
2303
2328
  );
2329
+ const hasNegs = g.hasNegs;
2330
+ const yExt = type === "heatmap" && !plot.distributed && !csWindow && g.maxY >= g.minY;
2331
+ const hi = yExt ? g.maxY : max;
2332
+ const total = Math.abs(hi) + Math.abs(yExt ? cs.min < g.minY ? cs.min : g.minY : min);
2333
+ const k2 = shadeIntensity * 1.25;
2304
2334
  const n = Math.max(2, cfg.stops || 16);
2305
2335
  for (let s = 0; s < n; s++) {
2306
2336
  const t = s / (n - 1);
2307
- const v = min + t * (max - min);
2308
- const total = Math.abs(max) + Math.abs(min);
2309
- const percent_v = total === 0 ? 0 : 100 * v / total;
2310
- let colorShadePercent;
2311
- if (hasNegs) {
2312
- if (plot.reverseNegativeShade) {
2313
- colorShadePercent = percent_v < 0 ? percent_v / 100 * (shadeIntensity * 1.25) : (1 - percent_v / 100) * (shadeIntensity * 1.25);
2314
- } else {
2315
- colorShadePercent = percent_v <= 0 ? 1 - (1 + percent_v / 100) * shadeIntensity : (1 - percent_v / 100) * shadeIntensity;
2316
- }
2317
- } else {
2318
- colorShadePercent = 1 - percent_v / 100;
2319
- }
2320
- if (colorShadePercent > 1) colorShadePercent = 1;
2321
- if (colorShadePercent < -1) colorShadePercent = -1;
2322
- const shaded = plot.enableShades ? utils.shadeColor(
2323
- w.config.theme.mode === "dark" ? colorShadePercent * -1 : colorShadePercent,
2324
- baseColor
2325
- ) : baseColor;
2337
+ const p = total === 0 ? 0 : Math.min(min + t * (max - min), hi) / total;
2338
+ const c = Math.max(
2339
+ -1,
2340
+ Math.min(
2341
+ 1,
2342
+ hasNegs ? plot.reverseNegativeShade ? (p < 0 ? p : 1 - p) * k2 : p <= 0 ? 1 - (1 + p) * shadeIntensity : (1 - p) * shadeIntensity : (1 - p) * (type === "treemap" ? k2 : 1)
2343
+ )
2344
+ );
2345
+ const shaded = plot.enableShades ? utils.shadeColor(w.config.theme.mode === "dark" ? -c : c, baseColor) : baseColor;
2326
2346
  stops.push({ percent: t, color: shaded });
2327
2347
  }
2328
2348
  }
@@ -2352,9 +2372,12 @@ class Legend {
2352
2372
  this.legendHelpers = new Helpers$3(this);
2353
2373
  }
2354
2374
  init() {
2375
+ var _a;
2355
2376
  const w = this.w;
2356
2377
  const gl = w.globals;
2357
2378
  const cnf = w.config;
2379
+ (_a = this.heatmapGradientLegend) == null ? void 0 : _a.destroy();
2380
+ this.heatmapGradientLegend = null;
2358
2381
  this.isBarsDistributed = cnf.chart.type === "bar" && cnf.plotOptions.bar.distributed && cnf.series.length === 1;
2359
2382
  const showLegendAlways = cnf.legend.showForSingleSeries && this.w.seriesData.series.length === 1 || this.isBarsDistributed || // Heatmap legends are colorScale-driven (discrete ranges or the
2360
2383
  // gradient strip), not series-driven, so they must render even for a
@@ -2372,10 +2395,6 @@ class Legend {
2372
2395
  while (elLegendWrap.firstChild) {
2373
2396
  elLegendWrap.removeChild(elLegendWrap.firstChild);
2374
2397
  }
2375
- if (this.heatmapGradientLegend) {
2376
- this.heatmapGradientLegend.destroy();
2377
- this.heatmapGradientLegend = null;
2378
- }
2379
2398
  if (HeatmapGradientLegend.isEnabled(w)) {
2380
2399
  this.heatmapGradientLegend = new HeatmapGradientLegend(w, this.ctx);
2381
2400
  this.heatmapGradientLegend.draw();
@@ -2553,7 +2572,7 @@ class Legend {
2553
2572
  }
2554
2573
  }
2555
2574
  const lg = legendGroups[w.labelData.seriesGroupIndex[i]];
2556
- if (lg) elLegendWrap.appendChild(lg);
2575
+ if (lg && !lg.parentNode) elLegendWrap.appendChild(lg);
2557
2576
  (lg || elLegendWrap).appendChild(elLegend);
2558
2577
  elLegendWrap.classList.add(
2559
2578
  `apexcharts-align-${w.config.legend.horizontalAlign}`
@@ -2664,7 +2683,7 @@ class Legend {
2664
2683
  );
2665
2684
  const hoverOverLegend = isLegendItem(target);
2666
2685
  if (w.config.chart.type !== "heatmap" && !this.isBarsDistributed) {
2667
- if (!target.classList.contains("apexcharts-inactive-legend") && hoverOverLegend) {
2686
+ if (hoverOverLegend && !target.closest(".apexcharts-inactive-legend")) {
2668
2687
  const series = new Series(this.ctx.w);
2669
2688
  series.toggleSeriesOnHover(e, target);
2670
2689
  }
@@ -2698,7 +2717,8 @@ class Legend {
2698
2717
  me.onLegendClick(e);
2699
2718
  if (rel !== null && w.config.legend.onItemClick.toggleDataSeries) {
2700
2719
  requestAnimationFrame(() => {
2701
- const restored = w.dom.baseEl.querySelector(
2720
+ var _a;
2721
+ const restored = (_a = w.dom.baseEl) == null ? void 0 : _a.querySelector(
2702
2722
  `.apexcharts-legend-series[rel="${rel}"]`
2703
2723
  );
2704
2724
  if (restored) restored.focus();
@@ -3783,6 +3803,63 @@ class ZoomPanSelection extends Toolbar {
3783
3803
  const { zoom } = this.w.config.chart;
3784
3804
  return this._incidentalZoomEnabled(zoom && zoom.allowMouseWheelZoom);
3785
3805
  }
3806
+ /** An explicit `true` zooms on every wheel; 'auto' needs Ctrl/Cmd. */
3807
+ _wheelZoomGreedy() {
3808
+ return this.w.config.chart.zoom.allowMouseWheelZoom === true;
3809
+ }
3810
+ /**
3811
+ * Tell a viewer whose bare wheel just scrolled past the chart how to zoom it.
3812
+ * Shown over the chart while the scroll goes on and faded out shortly after
3813
+ * it stops. Only for a mostly vertical wheel: a sideways trackpad swipe is
3814
+ * not someone reaching for zoom.
3815
+ *
3816
+ * The node lives in elWrap and the timer on w.interact, since a re-render can
3817
+ * replace both this instance and the wrapper's contents while it is up.
3818
+ *
3819
+ * @param {any} e
3820
+ */
3821
+ _showWheelHint(e) {
3822
+ const w = this.w;
3823
+ if (w.config.chart.zoom.wheelHint === false) return;
3824
+ if (Math.abs(e.deltaY) <= Math.abs(e.deltaX)) return;
3825
+ const wrap = w.dom.elWrap;
3826
+ if (!wrap) return;
3827
+ let el = wrap.querySelector(".apexcharts-wheel-hint");
3828
+ if (!el) {
3829
+ const win = BrowserAPIs.getWindow();
3830
+ const nav = win && win.navigator;
3831
+ const mac = !!nav && /Mac|iPhone|iPad/.test(nav.platform || nav.userAgent);
3832
+ const text = (w.globals.locale.toolbar.wheelZoomHint || "").replace(
3833
+ "{key}",
3834
+ mac ? "⌘" : "Ctrl"
3835
+ );
3836
+ el = BrowserAPIs.createElement("div");
3837
+ el.className = "apexcharts-wheel-hint";
3838
+ el.setAttribute("aria-hidden", "true");
3839
+ const label = BrowserAPIs.createElement("span");
3840
+ label.textContent = text;
3841
+ label.style.fontFamily = w.config.chart.fontFamily;
3842
+ el.appendChild(label);
3843
+ wrap.appendChild(el);
3844
+ void /** @type {HTMLElement} */
3845
+ el.offsetWidth;
3846
+ }
3847
+ el.classList.add("apexcharts-wheel-hint-visible");
3848
+ const it = w.interact;
3849
+ if (it.wheelHintTimer) clearTimeout(it.wheelHintTimer);
3850
+ it.wheelHintTimer = setTimeout(() => this._hideWheelHint(), 1200);
3851
+ }
3852
+ _hideWheelHint() {
3853
+ var _a;
3854
+ const w = this.w;
3855
+ const it = w.interact;
3856
+ if (it.wheelHintTimer) {
3857
+ clearTimeout(it.wheelHintTimer);
3858
+ it.wheelHintTimer = null;
3859
+ }
3860
+ const el = (_a = w.dom.elWrap) == null ? void 0 : _a.querySelector(".apexcharts-wheel-hint");
3861
+ if (el) el.classList.remove("apexcharts-wheel-hint-visible");
3862
+ }
3786
3863
  /**
3787
3864
  * Put keyboard focus on the chart, where the chart is focusable at all.
3788
3865
  *
@@ -3854,8 +3931,13 @@ class ZoomPanSelection extends Toolbar {
3854
3931
  * @param {any} e
3855
3932
  */
3856
3933
  mouseWheelEvent(e) {
3857
- e.preventDefault();
3858
3934
  const st = this._wheel();
3935
+ if (!this._wheelZoomGreedy() && !e.ctrlKey && !e.metaKey && st.endTimer == null) {
3936
+ this._showWheelHint(e);
3937
+ return;
3938
+ }
3939
+ e.preventDefault();
3940
+ this._hideWheelHint();
3859
3941
  let dy = e.deltaY;
3860
3942
  if (e.deltaMode === 1) dy *= 33;
3861
3943
  else if (e.deltaMode === 2) dy *= 330;
@@ -4619,6 +4701,34 @@ class ZoomPanSelection extends Toolbar {
4619
4701
  w.config.chart.events.scrolled(this.ctx, args);
4620
4702
  this.ctx.events.fireEvent("scrolled", args);
4621
4703
  }
4704
+ /**
4705
+ * Pan a zoomed x-window by `fraction` of its width (keyboard Shift+Arrow),
4706
+ * clamped to the data as a drag pan is, and reported as one (`scrolled`).
4707
+ * @param {number} fraction
4708
+ */
4709
+ panBy(fraction) {
4710
+ const w = this.w;
4711
+ if (!w.interact.zoomed) return;
4712
+ const { min, max } = this._currentXWindow();
4713
+ let d = (max - min) * fraction;
4714
+ if (w.config.xaxis.convertedCatToNumeric) {
4715
+ d = d > 0 ? Math.ceil(d) : Math.floor(d);
4716
+ }
4717
+ if (w.axisFlags.isRangeBar) {
4718
+ const r = w.rangeData;
4719
+ let lo = Infinity;
4720
+ let hi = -Infinity;
4721
+ r.seriesRangeStart.concat(r.seriesRangeEnd).flat().forEach((y) => {
4722
+ if (y != null) {
4723
+ lo = Math.min(lo, y);
4724
+ hi = Math.max(hi, y);
4725
+ }
4726
+ });
4727
+ d = d > 0 ? Math.min(d, Math.max(0, hi - max)) : Math.max(d, Math.min(0, lo - min));
4728
+ if (!d) return;
4729
+ }
4730
+ if (this._applyXRange(min + d, max + d, false)) this._fireScrolled();
4731
+ }
4622
4732
  /** @param {number} x @param {number} t */
4623
4733
  _pushSample(x2, t) {
4624
4734
  const s = this._m().samples;
@@ -6083,16 +6193,35 @@ class KeyboardNavigation {
6083
6193
  });
6084
6194
  svgEl.addEventListener("keydown", this._onKeyDown, { passive: false });
6085
6195
  this.ctx.events.addEventListener("legendClick", this._onLegendClick);
6196
+ const kept = w.interact.keyNav;
6197
+ const doc = svgEl.ownerDocument;
6198
+ w.interact.keyNav = null;
6199
+ if (kept && (!doc.activeElement || doc.activeElement === doc.body)) {
6200
+ [this.seriesIndex, this.dataPointIndex, , this._tooltipDismissed] = kept;
6201
+ if (!kept[2]) this.notePointerFocus();
6202
+ svgEl.focus({ preventScroll: true });
6203
+ }
6086
6204
  }
6087
6205
  /**
6088
- * Removes all event listeners. Called from chart.destroy().
6206
+ * Removes all event listeners. Called from chart.destroy(), and with
6207
+ * `updating` when an update is about to replace the SVG.
6208
+ * @param {boolean} [updating]
6089
6209
  */
6090
- destroy() {
6210
+ destroy(updating) {
6211
+ var _a;
6091
6212
  const w = this.w;
6092
6213
  const svgEl = w.dom.Paper && w.dom.Paper.node;
6093
6214
  this.ctx.events.removeEventListener("legendClick", this._onLegendClick);
6094
6215
  clearTimeout(this._announceTimer);
6095
6216
  if (!svgEl) return;
6217
+ if (updating && ((_a = svgEl.getRootNode) == null ? void 0 : _a.call(svgEl).activeElement) === svgEl) {
6218
+ w.interact.keyNav = [
6219
+ this.seriesIndex,
6220
+ this.dataPointIndex,
6221
+ this.active,
6222
+ this._tooltipDismissed
6223
+ ];
6224
+ }
6096
6225
  svgEl.removeEventListener("focus", this._onFocus);
6097
6226
  svgEl.removeEventListener("blur", this._onBlur);
6098
6227
  svgEl.removeEventListener("keydown", this._onKeyDown);
@@ -6144,7 +6273,7 @@ class KeyboardNavigation {
6144
6273
  this.active = true;
6145
6274
  this._clampCursor();
6146
6275
  this._snapToVisibleRange();
6147
- this._showCurrentPoint();
6276
+ if (!this._tooltipDismissed) this._showCurrentPoint();
6148
6277
  }
6149
6278
  _onBlur() {
6150
6279
  this.active = false;
@@ -6190,20 +6319,18 @@ class KeyboardNavigation {
6190
6319
  break;
6191
6320
  case "Home":
6192
6321
  e.preventDefault();
6193
- this.dataPointIndex = 0;
6194
- this._skipNullForward();
6322
+ this._seek(0, 1);
6195
6323
  this._showCurrentPoint();
6196
6324
  break;
6197
6325
  case "End":
6198
6326
  e.preventDefault();
6199
- this.dataPointIndex = this._getDataPointCount(this.seriesIndex) - 1;
6200
- this._skipNullBackward();
6327
+ this._seek(this._getDataPointCount(this.seriesIndex) - 1, -1);
6201
6328
  this._showCurrentPoint();
6202
6329
  break;
6203
6330
  case "Enter":
6204
6331
  case " ":
6205
6332
  e.preventDefault();
6206
- this._fireClick();
6333
+ this._fireClick(e);
6207
6334
  break;
6208
6335
  case "+":
6209
6336
  case "=":
@@ -6251,22 +6378,15 @@ class KeyboardNavigation {
6251
6378
  );
6252
6379
  }
6253
6380
  _canPan() {
6254
- return this._canZoom();
6381
+ return this._canZoom() && this.w.interact.zoomed;
6255
6382
  }
6256
6383
  /**
6257
- * Shift the visible x-range by ~10% in the given direction.
6384
+ * Shift the visible x-range by ~10% in the given direction, as a drag pan.
6258
6385
  * @param {number} direction +1 = right, -1 = left
6259
6386
  */
6260
6387
  _panBy(direction) {
6261
- const toolbar = this.ctx.toolbar;
6262
- if (!toolbar) return;
6263
- const r = toolbar._currentXRange();
6264
- const minX = Number(r.minX);
6265
- const maxX = Number(r.maxX);
6266
- if (!isFinite(minX) || !isFinite(maxX) || minX === maxX) return;
6267
- const span = maxX - minX;
6268
- const step = span * 0.1 * direction;
6269
- toolbar.zoomUpdateOptions(minX + step, maxX + step);
6388
+ var _a;
6389
+ (_a = this.ctx.zoomPanSelection) == null ? void 0 : _a.panBy(direction / 10);
6270
6390
  this._announce(direction > 0 ? "Panned right" : "Panned left");
6271
6391
  }
6272
6392
  // ─── Navigation ───────────────────────────────────────────────────────────
@@ -6281,8 +6401,8 @@ class KeyboardNavigation {
6281
6401
  if (dSeries !== 0) {
6282
6402
  const ttCtx = this.w.globals.tooltip;
6283
6403
  const type = w.config.chart.type;
6284
- const perCell = type === "heatmap" || type === "treemap";
6285
- if (!perCell && ttCtx && ttCtx.tConfig && ttCtx.tConfig.shared) {
6404
+ const perCell = type === "heatmap" || type === "treemap" || type === "radialBar";
6405
+ if (!perCell && (ttCtx == null ? void 0 : ttCtx.ttItems) && ttCtx.tConfig.shared) {
6286
6406
  const j = this.dataPointIndex;
6287
6407
  const isActuallyShared = ttCtx.tooltipUtil && ttCtx.tooltipUtil.isXoverlap(j) && ttCtx.tooltipUtil.isInitialSeriesSameLen();
6288
6408
  if (isActuallyShared) return;
@@ -6308,59 +6428,43 @@ class KeyboardNavigation {
6308
6428
  }
6309
6429
  }
6310
6430
  if (dPoint !== 0) {
6311
- const dpCount = this._getDataPointCount(this.seriesIndex);
6312
- let di = this.dataPointIndex + dPoint;
6313
- if (di < 0) di = wrapAround ? dpCount - 1 : 0;
6314
- if (di >= dpCount) di = wrapAround ? 0 : dpCount - 1;
6315
- this.dataPointIndex = di;
6316
- if (dPoint > 0) {
6317
- this._skipNullForward();
6318
- } else {
6319
- this._skipNullBackward();
6320
- }
6431
+ this._seek(this.dataPointIndex + dPoint, dPoint);
6321
6432
  if (!this._isDataPointVisible(this.seriesIndex, this.dataPointIndex)) {
6322
6433
  this._snapToVisibleRangeInDirection(dPoint);
6323
6434
  }
6324
6435
  }
6325
6436
  this._showCurrentPoint();
6326
6437
  }
6327
- /** Advance dataPointIndex forward past any nulls */
6328
- _skipNullForward() {
6329
- const w = this.w;
6330
- const si = this.seriesIndex;
6331
- const dpCount = this._getDataPointCount(si);
6332
- let di = this.dataPointIndex;
6333
- let attempts = 0;
6334
- if (!Array.isArray(w.seriesData.series[si])) return;
6335
- while (attempts < dpCount && w.seriesData.series[si][di] === null) {
6336
- di = (di + 1) % dpCount;
6337
- attempts++;
6338
- }
6339
- this.dataPointIndex = di;
6340
- }
6341
- /** Retreat dataPointIndex backward past any nulls */
6342
- _skipNullBackward() {
6438
+ /**
6439
+ * Land on the first non-null point from `di` going `dir`. Past an edge it
6440
+ * wraps only with wrapAround; when no point lies ahead the cursor stays.
6441
+ * @param {number} di
6442
+ * @param {number} dir
6443
+ */
6444
+ _seek(di, dir) {
6343
6445
  const w = this.w;
6344
- const si = this.seriesIndex;
6345
- const dpCount = this._getDataPointCount(si);
6346
- let di = this.dataPointIndex;
6347
- let attempts = 0;
6348
- if (!Array.isArray(w.seriesData.series[si])) return;
6349
- while (attempts < dpCount && w.seriesData.series[si][di] === null) {
6350
- di = (di - 1 + dpCount) % dpCount;
6351
- attempts++;
6446
+ const row = w.seriesData.series[this.seriesIndex];
6447
+ const n = this._getDataPointCount(this.seriesIndex);
6448
+ for (let k2 = 0; k2 < n; k2++, di += dir) {
6449
+ if (w.config.chart.accessibility.keyboard.navigation.wrapAround) {
6450
+ di = (di + n) % n;
6451
+ } else if (di < 0 || di >= n) return;
6452
+ if (!Array.isArray(row) || row[di] !== null) {
6453
+ this.dataPointIndex = di;
6454
+ return;
6455
+ }
6352
6456
  }
6353
- this.dataPointIndex = di;
6354
6457
  }
6355
6458
  // ─── Display ──────────────────────────────────────────────────────────────
6356
6459
  _showCurrentPoint() {
6357
6460
  const { seriesIndex: i, dataPointIndex: j } = this;
6358
6461
  const w = this.w;
6359
6462
  const ttCtx = w.globals.tooltip;
6360
- if (!ttCtx || !ttCtx.ttItems) return;
6463
+ this._tooltipDismissed = false;
6361
6464
  w.interact.capturedSeriesIndex = i;
6362
6465
  w.interact.capturedDataPointIndex = j;
6363
6466
  this._applyFocusClass(i, j);
6467
+ if (!(ttCtx == null ? void 0 : ttCtx.ttItems)) return this._announce(this._buildPointLabel(i, j));
6364
6468
  this._showTooltip(
6365
6469
  i,
6366
6470
  j,
@@ -6418,10 +6522,8 @@ class KeyboardNavigation {
6418
6522
  if (w.config.chart.accessibility.enabled && w.config.chart.accessibility.announcements.enabled) {
6419
6523
  tooltipEl.removeAttribute("aria-hidden");
6420
6524
  }
6421
- if (type === "pie" || type === "donut" || type === "polarArea") {
6525
+ if (type === "pie" || type === "donut" || type === "polarArea" || type === "radialBar") {
6422
6526
  this._showTooltipNonAxis(i, j, ttCtx, tooltipEl);
6423
- } else if (type === "radialBar") {
6424
- this._showTooltipRadialBar(i, j, ttCtx, tooltipEl);
6425
6527
  } else if (type === "heatmap" || type === "treemap") {
6426
6528
  this._showTooltipHeatTree(i, j, ttCtx, tooltipEl, type);
6427
6529
  } else if (this._isBarLikeSeries(i)) {
@@ -6776,24 +6878,23 @@ class KeyboardNavigation {
6776
6878
  return true;
6777
6879
  }
6778
6880
  /**
6779
- * pie / donut / polarArea
6881
+ * pie / donut / polarArea (a slice per point, i is 0) and radialBar (a ring
6882
+ * per series, j is 0)
6780
6883
  * @param {number} i
6781
6884
  * @param {number} j
6782
6885
  * @param {import('../tooltip/Tooltip').default} ttCtx
6783
6886
  * @param {HTMLElement} tooltipEl
6784
6887
  */
6785
6888
  _showTooltipNonAxis(i, j, ttCtx, tooltipEl) {
6786
- const w = this.w;
6787
6889
  ttCtx.tooltipLabels.drawSeriesTexts({
6788
6890
  ttItems: ttCtx.ttItems,
6789
- i: j,
6891
+ i: i + j,
6790
6892
  shared: false
6791
6893
  });
6792
6894
  const tooltipBound = tooltipEl.getBoundingClientRect();
6793
6895
  const ttWidth = tooltipBound.width || ttCtx.tooltipRect.ttWidth || 0;
6794
6896
  const ttHeight = tooltipBound.height || ttCtx.tooltipRect.ttHeight || 0;
6795
- const sliceEl = w.dom.baseEl.querySelector(`.apexcharts-pie-area[j='${j}']`);
6796
- const anchor = ttCtx.getSliceAnchor(sliceEl);
6897
+ const anchor = ttCtx.getSliceAnchor(this._getFocusableElement(i, j));
6797
6898
  if (anchor) {
6798
6899
  const pos = ttCtx.tooltipPosition.placeOverAnchor(
6799
6900
  anchor.x,
@@ -6806,56 +6907,6 @@ class KeyboardNavigation {
6806
6907
  tooltipEl.style.top = pos.y + "px";
6807
6908
  }
6808
6909
  }
6809
- /**
6810
- * radialBar — one ring per series, single value each
6811
- * @param {number} i
6812
- * @param {any} _j
6813
- * @param {import('../tooltip/Tooltip').default} ttCtx
6814
- * @param {HTMLElement} tooltipEl
6815
- */
6816
- _showTooltipRadialBar(i, _j, ttCtx, tooltipEl) {
6817
- var _a;
6818
- const w = this.w;
6819
- ttCtx.tooltipLabels.drawSeriesTexts({
6820
- ttItems: ttCtx.ttItems,
6821
- i,
6822
- shared: false
6823
- });
6824
- const { ttWidth = 0, ttHeight = 0 } = ttCtx.getCachedDimensions();
6825
- const arcEl = w.dom.baseEl.querySelector(
6826
- `.apexcharts-radialbar-series[data\\:realIndex='${i}'] path`
6827
- );
6828
- if (arcEl) {
6829
- const angle = parseFloat((_a = arcEl.getAttribute("data:angle")) != null ? _a : "") || 0;
6830
- const initialAngle = w.config.plotOptions.radialBar.startAngle || 0;
6831
- const midAngle = initialAngle + angle / 2;
6832
- const centerX = w.layout.gridWidth / 2;
6833
- const centerY = w.layout.gridHeight / 2;
6834
- const radialSize = w.globals.radialSize || Math.min(w.layout.gridWidth, w.layout.gridHeight) / 2;
6835
- const seriesCount = w.seriesData.series.length;
6836
- const trackSize = radialSize / Math.max(seriesCount, 1);
6837
- const outerRadius = radialSize - i * trackSize;
6838
- const innerRadius = outerRadius - trackSize;
6839
- const ringRadius = (outerRadius + innerRadius) / 2;
6840
- const centroid = Utils.polarToCartesian(
6841
- centerX,
6842
- centerY,
6843
- ringRadius,
6844
- midAngle
6845
- );
6846
- const x2 = centroid.x + (w.layout.translateX || 0);
6847
- const y = centroid.y + (w.layout.translateY || 0);
6848
- const pos = ttCtx.tooltipPosition.placeOverAnchor(
6849
- x2,
6850
- y,
6851
- ttWidth,
6852
- ttHeight,
6853
- 10
6854
- );
6855
- tooltipEl.style.left = pos.x + "px";
6856
- tooltipEl.style.top = pos.y + "px";
6857
- }
6858
- }
6859
6910
  /**
6860
6911
  * heatmap / treemap — position tooltip using element bounding rect
6861
6912
  * @param {number} i
@@ -7115,9 +7166,7 @@ class KeyboardNavigation {
7115
7166
  const mark = this._canvasMark(i, j);
7116
7167
  if (!mark) return this._drawCanvasMarkerFocusRing(i, j);
7117
7168
  const w = this.w;
7118
- const host = Array.from(
7119
- w.dom.baseEl.querySelectorAll(".apexcharts-series")
7120
- ).find((g) => g.getAttribute("data:realIndex") === String(i));
7169
+ const host = this._seriesGroup(i);
7121
7170
  if (!host) return null;
7122
7171
  const ring = new Graphics(w, this.ctx).drawPath({
7123
7172
  d: mark.d,
@@ -7141,9 +7190,7 @@ class KeyboardNavigation {
7141
7190
  const marker = this._canvasMarker(i, j);
7142
7191
  if (!marker) return null;
7143
7192
  const w = this.w;
7144
- const host = Array.from(
7145
- w.dom.baseEl.querySelectorAll(".apexcharts-series")
7146
- ).find((g) => g.getAttribute("data:realIndex") === String(i));
7193
+ const host = this._seriesGroup(i);
7147
7194
  if (!host) return null;
7148
7195
  const ring = new Graphics(w, this.ctx).drawPath({
7149
7196
  d: marker.d,
@@ -7237,6 +7284,7 @@ class KeyboardNavigation {
7237
7284
  * @param {number} j
7238
7285
  */
7239
7286
  _getFocusableElement(i, j) {
7287
+ var _a, _b;
7240
7288
  const w = this.w;
7241
7289
  const type = w.config.chart.type;
7242
7290
  const baseEl = w.dom.baseEl;
@@ -7254,32 +7302,47 @@ class KeyboardNavigation {
7254
7302
  );
7255
7303
  }
7256
7304
  if (type === "radialBar") {
7257
- return baseEl.querySelector(
7258
- `.apexcharts-radialbar-series[data\\:realIndex='${i}'] path`
7259
- );
7305
+ return baseEl.querySelector(`.apexcharts-radialbar-slice-${i}`);
7260
7306
  }
7261
7307
  if (this._isBarLikeSeries(i)) {
7262
7308
  if (this._canvasMark(i, j)) return null;
7263
- return baseEl.querySelector(
7264
- `.apexcharts-series[data\\:realIndex='${i}'] path[j='${j}']`
7265
- );
7309
+ return (_a = this._seriesGroup(i)) == null ? void 0 : _a.querySelector(`path[j='${j}']`);
7266
7310
  }
7267
- const marker = baseEl.querySelector(
7268
- `.apexcharts-series[data\\:realIndex='${i}'] .apexcharts-marker[rel='${j}']`
7269
- );
7270
- return marker || null;
7311
+ return (_b = this._seriesGroup(i)) == null ? void 0 : _b.querySelector(`.apexcharts-marker[rel='${j}']`);
7312
+ }
7313
+ /**
7314
+ * The series' own group, by realIndex (`rel` counts within a type's groups,
7315
+ * which a combo has several of). Matched in script: not every selector
7316
+ * engine takes the escaped `data\:realIndex` attribute.
7317
+ * @param {number} i
7318
+ * @returns {Element | undefined}
7319
+ */
7320
+ _seriesGroup(i) {
7321
+ return Array.from(
7322
+ this.w.dom.baseEl.querySelectorAll(".apexcharts-series")
7323
+ ).find((g) => g.getAttribute("data:realIndex") === String(i));
7271
7324
  }
7272
7325
  // ─── Click / Enter ────────────────────────────────────────────────────────
7273
- _fireClick() {
7274
- const w = this.w;
7275
- const ttCtx = w.globals.tooltip;
7276
- if (!ttCtx) return;
7277
- const syntheticEvent = {
7278
- type: "mouseup",
7279
- clientX: 0,
7280
- clientY: 0
7281
- };
7282
- ttCtx.markerClick(syntheticEvent, this.seriesIndex, this.dataPointIndex);
7326
+ /**
7327
+ * What a click on the focused mark does: its mousedown selects it
7328
+ * (dataPointSelection), its mouseup slides a pie slice out and fires
7329
+ * markerClick.
7330
+ * @param {KeyboardEvent} e
7331
+ */
7332
+ _fireClick(e) {
7333
+ var _a, _b;
7334
+ const el = (
7335
+ /** @type {any} */
7336
+ (_a = this._focusedEl) == null ? void 0 : _a.instance
7337
+ );
7338
+ const pie = this.ctx.pie;
7339
+ if (el) new Graphics(this.w, this.ctx).pathMouseDown(el, e);
7340
+ if (pie && pie.getExpandOffset() > 0) pie.pieClicked(this.dataPointIndex);
7341
+ (_b = this.w.globals.tooltip) == null ? void 0 : _b.markerClick(
7342
+ e,
7343
+ this.seriesIndex,
7344
+ this.dataPointIndex
7345
+ );
7283
7346
  }
7284
7347
  // ─── Helpers ──────────────────────────────────────────────────────────────
7285
7348
  _isNavEnabled() {
@@ -7303,8 +7366,8 @@ class KeyboardNavigation {
7303
7366
  if (type === "pie" || type === "donut" || type === "polarArea") {
7304
7367
  return w.seriesData.series.length;
7305
7368
  }
7306
- const series = w.seriesData.series;
7307
- return series[si] && Array.isArray(series[si]) ? series[si].length : 0;
7369
+ const s = w.seriesData.series[si];
7370
+ return Array.isArray(s) ? s.length : 1;
7308
7371
  }
7309
7372
  _clampCursor() {
7310
7373
  const seriesCount = this._getSeriesCount();
@@ -11739,520 +11802,16 @@ const resolveDataLabelOffset = (value, w, seriesIndex, dataPointIndex) => {
11739
11802
  });
11740
11803
  return Number.isFinite(resolved) ? resolved : 0;
11741
11804
  };
11742
- function buildUnionEntries(join, oldN) {
11743
- const exitSet = new Set(join.exits);
11744
- const entries = [];
11745
- let oi = 0;
11746
- for (let nj = 0; nj < join.toOld.length; nj++) {
11747
- const oj = join.toOld[nj];
11748
- if (oj !== -1) {
11749
- while (oi < oj) {
11750
- if (exitSet.has(oi)) entries.push({ oldJ: oi, newJ: -1 });
11751
- oi++;
11752
- }
11753
- entries.push({ oldJ: oj, newJ: nj });
11754
- oi = oj + 1;
11755
- } else {
11756
- entries.push({ oldJ: -1, newJ: nj });
11757
- }
11758
- }
11759
- while (oi < oldN) {
11760
- if (exitSet.has(oi)) entries.push({ oldJ: oi, newJ: -1 });
11761
- oi++;
11762
- }
11763
- return entries;
11764
- }
11765
- function analyzeSeriesPath(d, expectedAnchors, isArea) {
11766
- if (!d || typeof d !== "string") return null;
11767
- const cmds = parsePath(d);
11768
- if (!cmds.length || cmds[0][0] !== "M") return null;
11769
- for (let i = 1; i < cmds.length; i++) {
11770
- if (cmds[i][0] === "M") return null;
11771
- }
11772
- let body = cmds;
11773
- let closing = null;
11774
- if (isArea) {
11775
- if (cmds.length < 5) return null;
11776
- closing = cmds.slice(-3);
11777
- body = cmds.slice(0, -3);
11778
- if (closing[2][0] !== "Z") return null;
11779
- if (closing[1][0] !== "L") return null;
11780
- if (closing[0][0] !== "L" && closing[0][0] !== "C") return null;
11781
- } else if (cmds[cmds.length - 1][0] === "Z") {
11782
- return null;
11783
- }
11784
- if (body.length !== expectedAnchors || body.length < 2) return null;
11785
- const segType = body[1][0];
11786
- if (segType !== "L" && segType !== "C") return null;
11787
- for (let i = 2; i < body.length; i++) {
11788
- if (body[i][0] !== segType) return null;
11789
- }
11790
- const anchors = body.map(
11791
- (c) => c[0] === "C" ? [Number(c[5]), Number(c[6])] : [Number(c[1]), Number(c[2])]
11792
- );
11793
- for (const a of anchors) {
11794
- if (!isFinite(a[0]) || !isFinite(a[1])) return null;
11795
- }
11796
- return { body, closing, segType, anchors };
11797
- }
11798
- function lerpPt(a, b, t) {
11799
- return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
11800
- }
11801
- function splitCubic(s, cmd, t) {
11802
- const p0 = s;
11803
- const p1 = [cmd[1], cmd[2]];
11804
- const p2 = [cmd[3], cmd[4]];
11805
- const p3 = [cmd[5], cmd[6]];
11806
- const p01 = lerpPt(p0, p1, t);
11807
- const p12 = lerpPt(p1, p2, t);
11808
- const p23 = lerpPt(p2, p3, t);
11809
- const p012 = lerpPt(p01, p12, t);
11810
- const p123 = lerpPt(p12, p23, t);
11811
- const mid = lerpPt(p012, p123, t);
11812
- return {
11813
- first: ["C", p01[0], p01[1], p012[0], p012[1], mid[0], mid[1]],
11814
- second: ["C", p123[0], p123[1], p23[0], p23[1], p3[0], p3[1]],
11815
- mid
11816
- };
11817
- }
11818
- function splitLine(s, cmd, t) {
11819
- const e = [cmd[1], cmd[2]];
11820
- const mid = lerpPt(s, e, t);
11821
- return {
11822
- first: ["L", mid[0], mid[1]],
11823
- second: ["L", e[0], e[1]],
11824
- mid
11825
- };
11826
- }
11827
- function expandPath(analysis, ownIdx) {
11828
- const { body, closing, segType, anchors } = analysis;
11829
- const n = anchors.length;
11830
- const m = ownIdx.length;
11831
- const degen = (p) => segType === "C" ? ["C", p[0], p[1], p[0], p[1], p[0], p[1]] : ["L", p[0], p[1]];
11832
- const out = [["M", anchors[0][0], anchors[0][1]]];
11833
- let firstOwn = 0;
11834
- while (firstOwn < m && ownIdx[firstOwn] !== 0) firstOwn++;
11835
- for (let q = 1; q <= firstOwn; q++) out.push(degen(anchors[0]));
11836
- let entry = firstOwn + 1;
11837
- for (let s = 0; s < n - 1; s++) {
11838
- let interior = 0;
11839
- while (entry + interior < m && ownIdx[entry + interior] === -1) interior++;
11840
- const cmd = body[s + 1];
11841
- if (!interior) {
11842
- out.push(cmd.slice());
11843
- } else {
11844
- const totalParts = interior + 1;
11845
- let start = anchors[s];
11846
- let rest = cmd;
11847
- for (let q = 0; q < interior; q++) {
11848
- const t = 1 / (totalParts - q);
11849
- const sp = segType === "C" ? splitCubic(start, rest, t) : splitLine(start, rest, t);
11850
- out.push(sp.first);
11851
- start = sp.mid;
11852
- rest = sp.second;
11853
- }
11854
- out.push(rest);
11855
- }
11856
- entry += interior + 1;
11857
- }
11858
- while (entry < m) {
11859
- out.push(degen(anchors[n - 1]));
11860
- entry++;
11861
- }
11862
- if (closing) closing.forEach((c) => out.push(c.slice()));
11863
- return out;
11864
- }
11865
- function reconcilePathPair(fromD, toD, entries, oldN, newN, isArea) {
11866
- const fromAnalysis = analyzeSeriesPath(fromD, oldN, isArea);
11867
- if (!fromAnalysis) return null;
11868
- const toAnalysis = analyzeSeriesPath(toD, newN, isArea);
11869
- if (!toAnalysis) return null;
11870
- if (fromAnalysis.segType !== toAnalysis.segType) return null;
11871
- if ((fromAnalysis.closing || toAnalysis.closing) && (!fromAnalysis.closing || !toAnalysis.closing || fromAnalysis.closing[0][0] !== toAnalysis.closing[0][0])) {
11872
- return null;
11873
- }
11874
- const fromOwn = entries.map((e) => e.oldJ);
11875
- const toOwn = entries.map((e) => e.newJ);
11876
- return {
11877
- from: arrayToPath(expandPath(fromAnalysis, fromOwn)),
11878
- toInterp: arrayToPath(expandPath(toAnalysis, toOwn))
11879
- };
11880
- }
11881
- function lengthTransitionEnabled(w) {
11882
- var _a;
11883
- const anim = w.config.chart.animations;
11884
- if (!anim || anim.enabled === false) return false;
11885
- if (!anim.dynamicAnimation || anim.dynamicAnimation.enabled === false) {
11886
- return false;
11887
- }
11888
- const largeThreshold = (_a = anim.largeDatasetThreshold) != null ? _a : 0;
11889
- if (largeThreshold > 0 && w.globals.dataPoints > largeThreshold) return false;
11890
- return !!(Environment.isBrowser() && w.globals.dataChanged && w.globals.shouldAnimate);
11891
- }
11892
- function datumKey(w, realIndex, j) {
11893
- var _a, _b, _c, _d;
11894
- if ((_a = w.axisFlags) == null ? void 0 : _a.isXNumeric) {
11895
- const sx = (_c = (_b = w.seriesData) == null ? void 0 : _b.seriesX) == null ? void 0 : _c[realIndex];
11896
- if (sx && sx.length && sx[j] != null) return "x:" + sx[j];
11897
- }
11898
- const lbl = (_d = w.globals.labels) == null ? void 0 : _d[j];
11899
- if (lbl != null && String(lbl) !== "") {
11900
- return "c:" + (Array.isArray(lbl) ? lbl.join(" ") : String(lbl));
11901
- }
11902
- return "j:" + j;
11903
- }
11904
- function frameDatumKey(frame, realIndex, j) {
11905
- var _a, _b;
11906
- if (frame.isXNumeric) {
11907
- const sx = (_a = frame.seriesX) == null ? void 0 : _a[realIndex];
11908
- if (sx && sx.length && sx[j] != null) return "x:" + sx[j];
11909
- }
11910
- const lbl = (_b = frame.labels) == null ? void 0 : _b[j];
11911
- if (lbl != null && String(lbl) !== "") {
11912
- return "c:" + (Array.isArray(lbl) ? lbl.join(" ") : String(lbl));
11913
- }
11914
- return "j:" + j;
11915
- }
11916
- function joinKeys(oldKeys, newKeys) {
11917
- const oldIndex = /* @__PURE__ */ new Map();
11918
- oldKeys.forEach((k2, i) => {
11919
- if (!oldIndex.has(k2)) oldIndex.set(k2, i);
11920
- });
11921
- const toOld = new Array(newKeys.length);
11922
- const usedOld = /* @__PURE__ */ new Set();
11923
- let prev = -1;
11924
- let ordered = true;
11925
- let identity = oldKeys.length === newKeys.length;
11926
- newKeys.forEach((k2, i) => {
11927
- const oi = oldIndex.has(k2) && !usedOld.has(oldIndex.get(k2)) ? oldIndex.get(k2) : -1;
11928
- toOld[i] = oi;
11929
- if (oi !== -1) {
11930
- usedOld.add(oi);
11931
- if (oi < prev) ordered = false;
11932
- prev = oi;
11933
- }
11934
- if (oi !== i) identity = false;
11935
- });
11936
- const exits = [];
11937
- for (let i = 0; i < oldKeys.length; i++) {
11938
- if (!usedOld.has(i)) exits.push(i);
11939
- }
11940
- return { toOld, exits, ordered, changed: !identity };
11941
- }
11942
- function uniquifyKeys(keys) {
11943
- const seen = /* @__PURE__ */ new Map();
11944
- return keys.map((k2) => {
11945
- const count = seen.get(k2) || 0;
11946
- seen.set(k2, count + 1);
11947
- return count === 0 ? k2 : `${k2}#${count}`;
11948
- });
11949
- }
11950
- function seriesJoin(w, realIndex, includeIdentity = false, allowReorder = false) {
11951
- var _a, _b;
11952
- if (!lengthTransitionEnabled(w)) return null;
11953
- const frame = w.globals.prevStreamFrame;
11954
- if (!frame) return null;
11955
- const oldY = (_a = frame.seriesY) == null ? void 0 : _a[realIndex];
11956
- const newY = (_b = w.seriesData.series) == null ? void 0 : _b[realIndex];
11957
- if (!Array.isArray(oldY) || !Array.isArray(newY)) return null;
11958
- if (!oldY.length || !newY.length) return null;
11959
- const oldKeys = uniquifyKeys(
11960
- oldY.map((_, j) => frameDatumKey(frame, realIndex, j))
11961
- );
11962
- const newKeys = uniquifyKeys(newY.map((_, j) => datumKey(w, realIndex, j)));
11963
- const join = joinKeys(oldKeys, newKeys);
11964
- if (!join.ordered && !allowReorder) return null;
11965
- if (!join.changed && !includeIdentity) return null;
11966
- return { join, oldKeys, newKeys };
11967
- }
11968
- function morphEasing(w) {
11969
- var _a, _b;
11970
- const anim = w.config.chart.animations;
11971
- return resolveEasing((_b = (_a = anim.dynamicAnimation) == null ? void 0 : _a.easing) != null ? _b : anim.easing);
11972
- }
11973
- function rafTween(w, duration, ease, onFrame, onDone) {
11974
- const startAt = performance.now();
11975
- const step = (now) => {
11976
- if (w.globals.isDestroyed) return;
11977
- const raw = Math.max(0, Math.min(1, (now - startAt) / duration));
11978
- onFrame(ease(raw), raw);
11979
- if (raw < 1) {
11980
- BrowserAPIs.requestAnimationFrame(step);
11981
- } else if (onDone) {
11982
- onDone();
11983
- }
11984
- };
11985
- BrowserAPIs.requestAnimationFrame(step);
11986
- }
11987
- function tweenSeriesMarkers(w, { elPointsMain, realIndex, speed }) {
11988
- var _a, _b, _c, _d;
11989
- if (!(elPointsMain == null ? void 0 : elPointsMain.node)) return false;
11990
- const sj = seriesJoin(w, realIndex, true);
11991
- if (!sj) return false;
11992
- const frame = w.globals.prevStreamFrame;
11993
- if (!frame) return false;
11994
- const oldXP = (_a = frame.xPixels) == null ? void 0 : _a[realIndex];
11995
- const oldYP = (_b = frame.yPixels) == null ? void 0 : _b[realIndex];
11996
- if (!oldXP || !oldYP) return false;
11997
- const markers = elPointsMain.node.querySelectorAll(".apexcharts-marker");
11998
- if (!markers.length) return false;
11999
- const newXP = ((_c = w.globals.seriesXvalues) == null ? void 0 : _c[realIndex]) || [];
12000
- const newYP = ((_d = w.globals.seriesYvalues) == null ? void 0 : _d[realIndex]) || [];
12001
- const ease = morphEasing(w);
12002
- const duration = Math.max(1, speed || 1);
12003
- elPointsMain.node.classList.remove("apexcharts-element-hidden");
12004
- markers.forEach((node) => {
12005
- var _a2, _b2, _c2, _d2, _e, _f, _g, _h, _i;
12006
- const j = parseInt(
12007
- (_b2 = (_a2 = node.getAttribute("j")) != null ? _a2 : node.getAttribute("rel")) != null ? _b2 : "",
12008
- 10
12009
- );
12010
- if (!isFinite(j) || j < 0 || j >= sj.join.toOld.length) return;
12011
- const oldJ = sj.join.toOld[j];
12012
- const to = newXP[j] != null && newYP[j] != null ? [newXP[j], newYP[j]] : null;
12013
- if (oldJ === -1 || !to) {
12014
- const style = (
12015
- /** @type {any} */
12016
- node.style
12017
- );
12018
- style.opacity = "0";
12019
- rafTween(
12020
- w,
12021
- duration,
12022
- ease,
12023
- (eased) => {
12024
- style.opacity = String(eased);
12025
- },
12026
- () => {
12027
- style.opacity = "";
12028
- }
12029
- );
12030
- return;
12031
- }
12032
- const dx = ((_c2 = oldXP[oldJ]) != null ? _c2 : NaN) - to[0];
12033
- const dy = ((_d2 = oldYP[oldJ]) != null ? _d2 : NaN) - to[1];
12034
- if (!isFinite(dx) || !isFinite(dy)) return;
12035
- const rFrom = (_g = (_f = (_e = frame.rPixels) == null ? void 0 : _e[realIndex]) == null ? void 0 : _f[oldJ]) != null ? _g : NaN;
12036
- const rTo = parseFloat(
12037
- (_i = (_h = node.getAttribute("r")) != null ? _h : node.getAttribute("default-marker-size")) != null ? _i : ""
12038
- );
12039
- const scales = isFinite(rFrom) && isFinite(rTo) && rTo > 0 && Math.abs(rFrom - rTo) > 0.25;
12040
- const moves = Math.abs(dx) >= 0.5 || Math.abs(dy) >= 0.5;
12041
- if (!moves && !scales) return;
12042
- const apply = (eased) => {
12043
- const offX = dx * (1 - eased);
12044
- const offY = dy * (1 - eased);
12045
- if (scales) {
12046
- const s = (rFrom + (rTo - rFrom) * eased) / rTo;
12047
- node.setAttribute(
12048
- "transform",
12049
- `translate(${offX + to[0] * (1 - s)}, ${offY + to[1] * (1 - s)}) scale(${s})`
12050
- );
12051
- } else {
12052
- node.setAttribute("transform", `translate(${offX}, ${offY})`);
12053
- }
12054
- };
12055
- apply(0);
12056
- rafTween(w, duration, ease, apply, () => {
12057
- node.removeAttribute("transform");
12058
- });
12059
- });
12060
- return true;
12061
- }
12062
- function scaleAbout(node, cx, cy, s) {
12063
- node.setAttribute("transform", `translate(${cx * (1 - s)}, ${cy * (1 - s)}) scale(${s})`);
12064
- }
12065
- function growRisingMarkers(w, { elPointsMain, realIndex, speed }) {
12066
- if (!(elPointsMain == null ? void 0 : elPointsMain.node) || !lengthTransitionEnabled(w)) return false;
12067
- if ((w.globals.risingSeries || []).indexOf(realIndex) === -1) return false;
12068
- const markers = elPointsMain.node.querySelectorAll(".apexcharts-marker");
12069
- if (!markers.length) return false;
12070
- const ease = morphEasing(w);
12071
- elPointsMain.node.classList.remove("apexcharts-element-hidden");
12072
- markers.forEach((node) => {
12073
- const b = node.getBBox();
12074
- const cx = b.x + b.width / 2;
12075
- const cy = b.y + b.height / 2;
12076
- scaleAbout(node, cx, cy, 0);
12077
- rafTween(
12078
- w,
12079
- Math.max(1, speed || 1),
12080
- ease,
12081
- (eased) => scaleAbout(node, cx, cy, eased),
12082
- () => node.removeAttribute("transform")
12083
- );
12084
- });
12085
- return true;
12086
- }
12087
- function shrinkCollapsingMarkers(w, { elPointsMain, realIndex, speed, drawPoint }) {
12088
- var _a, _b, _c;
12089
- if (!(elPointsMain == null ? void 0 : elPointsMain.node) || !lengthTransitionEnabled(w)) return false;
12090
- if ((w.globals.collapsingSeriesIndices || []).indexOf(realIndex) === -1) return false;
12091
- const frame = w.globals.prevStreamFrame;
12092
- const xs = (_a = frame == null ? void 0 : frame.xPixels) == null ? void 0 : _a[realIndex];
12093
- const ys = (_b = frame == null ? void 0 : frame.yPixels) == null ? void 0 : _b[realIndex];
12094
- if (!Array.isArray(xs) || !Array.isArray(ys)) return false;
12095
- const rs = ((_c = frame == null ? void 0 : frame.rPixels) == null ? void 0 : _c[realIndex]) || [];
12096
- const fallbackR = w.globals.markers.size[realIndex] || 0;
12097
- const ease = morphEasing(w);
12098
- let drawn = false;
12099
- for (let j = 0; j < xs.length; j++) {
12100
- const x2 = xs[j];
12101
- const y = ys[j];
12102
- if (x2 == null || y == null || !isFinite(x2) || !isFinite(y)) continue;
12103
- const r = isFinite(rs[j]) ? rs[j] : fallbackR;
12104
- if (!(r > 0)) continue;
12105
- const el = drawPoint(x2, y, r, j);
12106
- if (!(el == null ? void 0 : el.node)) continue;
12107
- elPointsMain.add(el);
12108
- const node = el.node;
12109
- node.classList.add("apexcharts-marker-exit");
12110
- const landed = Animations.trackSeriesTween(w, realIndex);
12111
- rafTween(
12112
- w,
12113
- Math.max(1, speed || 1),
12114
- ease,
12115
- (eased) => scaleAbout(node, x2, y, 1 - eased),
12116
- () => {
12117
- scaleAbout(node, x2, y, 0);
12118
- landed();
12119
- }
12120
- );
12121
- drawn = true;
12122
- }
12123
- if (drawn) elPointsMain.node.classList.remove("apexcharts-element-hidden");
12124
- return drawn;
12125
- }
12126
- function reconcileSeriesPaths(w, { type, realIndex, pathFromLine, pathFromArea, linePaths, areaPaths }) {
12127
- var _a, _b;
12128
- const sj = seriesJoin(w, realIndex);
12129
- if (!sj) return null;
12130
- const { join, oldKeys, newKeys } = sj;
12131
- const frame = w.globals.prevStreamFrame;
12132
- if (!frame) return null;
12133
- const oldY = (_a = frame.seriesY) == null ? void 0 : _a[realIndex];
12134
- const newY = (_b = w.seriesData.series) == null ? void 0 : _b[realIndex];
12135
- if (oldY.length < 2 || newY.length < 2) return null;
12136
- if (oldY.some((v) => v === null) || newY.some((v) => v === null)) return null;
12137
- const entries = buildUnionEntries(join, oldKeys.length);
12138
- const out = {};
12139
- if (Array.isArray(linePaths) && linePaths.length === 1 && pathFromLine) {
12140
- out.line = reconcilePathPair(
12141
- pathFromLine,
12142
- linePaths[0],
12143
- entries,
12144
- oldKeys.length,
12145
- newKeys.length,
12146
- false
12147
- );
12148
- }
12149
- if (type === "area" && Array.isArray(areaPaths) && areaPaths.length === 1 && pathFromArea) {
12150
- out.area = reconcilePathPair(
12151
- pathFromArea,
12152
- areaPaths[0],
12153
- entries,
12154
- oldKeys.length,
12155
- newKeys.length,
12156
- true
12157
- );
12158
- }
12159
- if (!out.line && !out.area) return null;
12160
- return out;
12161
- }
12162
- function firstMove(d) {
12163
- const m = /^M\s*([+-]?[\d.eE]+)[\s,]+([+-]?[\d.eE]+)/.exec(d || "");
12164
- if (!m) return null;
12165
- const x2 = parseFloat(m[1]);
12166
- const y = parseFloat(m[2]);
12167
- return isFinite(x2) && isFinite(y) ? { x: x2, y } : null;
12168
- }
12169
- function renderBarExitGhosts({
12170
- w,
12171
- elSeries,
12172
- record,
12173
- newKeys,
12174
- isHorizontal,
12175
- speed
12176
- }) {
12177
- var _a;
12178
- if (!lengthTransitionEnabled(w)) return;
12179
- if (!record || !Array.isArray(record.paths) || !(elSeries == null ? void 0 : elSeries.node)) return;
12180
- const newKeySet = new Set(newKeys);
12181
- const exits = record.paths.filter(
12182
- (p) => p && p.d && p.key != null && !newKeySet.has(p.key)
12183
- );
12184
- if (!exits.length) return;
12185
- const graphics = new Graphics(w);
12186
- const fallbackFill = (_a = w.globals.colors) == null ? void 0 : _a[parseInt(String(record.realIndex), 10)];
12187
- exits.forEach((p) => {
12188
- let fill = p.fill || fallbackFill || "#c8c8c8";
12189
- if (String(fill).indexOf("url(") === 0) fill = fallbackFill || "#c8c8c8";
12190
- const ghost = graphics.drawPath({
12191
- d: p.d,
12192
- stroke: "none",
12193
- strokeWidth: 0,
12194
- fill,
12195
- fillOpacity: 1,
12196
- classes: "apexcharts-bar-ghost"
12197
- });
12198
- const node = ghost.node;
12199
- node.setAttribute("pointer-events", "none");
12200
- ghost.attr(
12201
- "clip-path",
12202
- `url(#gridRectBarMask${w.globals.cuid})`
12203
- );
12204
- elSeries.node.insertBefore(node, elSeries.node.firstChild);
12205
- const start = firstMove(p.d);
12206
- let origin = isHorizontal ? "left center" : "center bottom";
12207
- try {
12208
- const bb = node.getBBox();
12209
- if (start && bb) {
12210
- if (isHorizontal) {
12211
- origin = Math.abs(start.x - bb.x) <= Math.abs(start.x - (bb.x + bb.width)) ? "left center" : "right center";
12212
- } else {
12213
- origin = Math.abs(start.y - (bb.y + bb.height)) <= Math.abs(start.y - bb.y) ? "center bottom" : "center top";
12214
- }
12215
- }
12216
- } catch (_) {
12217
- }
12218
- const style = node.style;
12219
- style.transformBox = "fill-box";
12220
- style.transformOrigin = origin;
12221
- node.setAttribute("data:ghostKey", `${record.realIndex}::${p.key}`);
12222
- try {
12223
- const bb = node.getBBox();
12224
- const edge = isHorizontal ? origin.startsWith("left") ? bb.x : bb.x + bb.width : origin.endsWith("bottom") ? bb.y + bb.height : bb.y;
12225
- if (isFinite(edge)) node.setAttribute("data:ghostEdge", String(edge));
12226
- } catch (_) {
12227
- }
12228
- const duration = Math.max(1, speed || 1);
12229
- const startAt = performance.now();
12230
- const step = (now) => {
12231
- if (w.globals.isDestroyed || !node.parentNode) return;
12232
- const t = Math.max(0, Math.min(1, (now - startAt) / duration));
12233
- const eased = 1 - Math.pow(1 - t, 3);
12234
- const scale = 1 - eased;
12235
- style.transform = isHorizontal ? `scaleX(${scale})` : `scaleY(${scale})`;
12236
- style.opacity = String(1 - eased);
12237
- if (t < 1) {
12238
- BrowserAPIs.requestAnimationFrame(step);
12239
- } else {
12240
- node.parentNode.removeChild(node);
12241
- }
12242
- };
12243
- BrowserAPIs.requestAnimationFrame(step);
12244
- });
12245
- }
12246
- class BarDataLabels {
12247
- /**
12248
- * @param {import('../../../charts/Bar').default} barCtx
12249
- */
12250
- constructor(barCtx) {
12251
- this.w = barCtx.w;
12252
- this.barCtx = barCtx;
12253
- this.totalFormatter = this.w.config.plotOptions.bar.dataLabels.total.formatter;
12254
- if (!this.totalFormatter) {
12255
- this.totalFormatter = this.w.config.dataLabels.formatter;
11805
+ class BarDataLabels {
11806
+ /**
11807
+ * @param {import('../../../charts/Bar').default} barCtx
11808
+ */
11809
+ constructor(barCtx) {
11810
+ this.w = barCtx.w;
11811
+ this.barCtx = barCtx;
11812
+ this.totalFormatter = this.w.config.plotOptions.bar.dataLabels.total.formatter;
11813
+ if (!this.totalFormatter) {
11814
+ this.totalFormatter = this.w.config.dataLabels.formatter;
12256
11815
  }
12257
11816
  }
12258
11817
  /** handleBarDataLabels is used to calculate the positions for the data-labels
@@ -12278,7 +11837,8 @@ class BarDataLabels {
12278
11837
  barXPosition,
12279
11838
  barYPosition,
12280
11839
  visibleSeries,
12281
- hl
11840
+ hl,
11841
+ noLabel
12282
11842
  } = opts;
12283
11843
  const w = this.w;
12284
11844
  const graphics = new Graphics(this.barCtx.w);
@@ -12392,7 +11952,7 @@ class BarDataLabels {
12392
11952
  dataLabelsPos.dataLabelsX = (box.levelStart + box.levelEnd) / 2 + offX;
12393
11953
  }
12394
11954
  }
12395
- dataLabels = this.drawCalculatedDataLabels({
11955
+ dataLabels = noLabel ? null : this.drawCalculatedDataLabels({
12396
11956
  x: dataLabelsPos.dataLabelsX,
12397
11957
  y: dataLabelsPos.dataLabelsY,
12398
11958
  neg: params.neg,
@@ -12478,8 +12038,8 @@ class BarDataLabels {
12478
12038
  return ctx && byGroups && byGroups[ctx.groupIndex] ? byGroups[ctx.groupIndex][j] : this.barCtx.stackedSeriesTotals[j];
12479
12039
  }
12480
12040
  /**
12481
- * The running stack at this column's x (BarStacked `tops`, columns only) on
12482
- * a numeric axis, where columns stack by x rather than by index.
12041
+ * The running stack at this bar's x (BarStacked `tops`) on a numeric axis,
12042
+ * where bars stack by x rather than by index.
12483
12043
  * @param {number} realIndex @param {number} j
12484
12044
  */
12485
12045
  xStackTop(realIndex, j) {
@@ -12488,6 +12048,21 @@ class BarDataLabels {
12488
12048
  return w.axisFlags.isXNumeric && /** @type {any} */
12489
12049
  ((_b = (_a = this.barCtx.stacks) == null ? void 0 : _a[w.labelData.seriesGroupIndex[realIndex]]) == null ? void 0 : _b.tops.get(w.seriesData.seriesX[realIndex][j]));
12490
12050
  }
12051
+ /**
12052
+ * The stacked total's text box, measured in the total's own font.
12053
+ * @param {number} realIndex @param {number} j
12054
+ */
12055
+ totalRects(realIndex, j) {
12056
+ const s = this.barCtx.barOptions.dataLabels.total.style;
12057
+ return new Graphics(this.w).getTextRects(
12058
+ this.getStackedTotalDataLabel({ realIndex, j }),
12059
+ s.fontSize,
12060
+ s.fontFamily,
12061
+ void 0,
12062
+ true,
12063
+ s.fontWeight
12064
+ );
12065
+ }
12491
12066
  /** @param {{realIndex: any, j: any}} opts */
12492
12067
  getStackedTotalDataLabel({ realIndex, j }) {
12493
12068
  const w = this.w;
@@ -12508,7 +12083,6 @@ class BarDataLabels {
12508
12083
  var _a;
12509
12084
  const w = this.w;
12510
12085
  let {
12511
- i,
12512
12086
  j,
12513
12087
  realIndex,
12514
12088
  y,
@@ -12518,7 +12092,6 @@ class BarDataLabels {
12518
12092
  textRects,
12519
12093
  dataLabelsX,
12520
12094
  dataLabelsY,
12521
- dataLabelsConfig,
12522
12095
  barDataLabelsConfig,
12523
12096
  barTotalDataLabelsConfig,
12524
12097
  strokeWidth,
@@ -12532,7 +12105,7 @@ class BarDataLabels {
12532
12105
  barHeight = Math.abs(barHeight);
12533
12106
  const vertical = w.config.plotOptions.bar.dataLabels.orientation === "vertical";
12534
12107
  const { zeroEncounters } = this.barCtx.barHelpers.getZeroValueEncounters({
12535
- i,
12108
+ i: realIndex,
12536
12109
  j
12537
12110
  });
12538
12111
  bcx = bcx - strokeWidth / 2;
@@ -12553,7 +12126,7 @@ class BarDataLabels {
12553
12126
  const offsetDLX = 2;
12554
12127
  dataLabelsX = dataLabelsX + textRects.height / 2 - strokeWidth / 2 - offsetDLX;
12555
12128
  }
12556
- const valIsNegative = (_a = opts.neg) != null ? _a : w.seriesData.series[i][j] < 0;
12129
+ const valIsNegative = (_a = opts.neg) != null ? _a : w.seriesData.series[realIndex][j] < 0;
12557
12130
  let newY = y;
12558
12131
  if (this.barCtx.isReversed) {
12559
12132
  newY = y + (valIsNegative ? barHeight : -barHeight);
@@ -12627,16 +12200,11 @@ class BarDataLabels {
12627
12200
  });
12628
12201
  if (this.hlt) lowestPrevY = this.hlt.edge;
12629
12202
  if (this.drawsStackedTotal(realIndex) && barTotalDataLabelsConfig.enabled) {
12630
- const ADDITIONAL_OFFY = 18;
12631
- const graphics = new Graphics(this.barCtx.w);
12632
- const totalLabeltextRects = graphics.getTextRects(
12633
- this.getStackedTotalDataLabel({ realIndex, j }),
12634
- dataLabelsConfig.fontSize
12635
- );
12203
+ const h = this.totalRects(realIndex, j).height;
12636
12204
  if (valIsNegative) {
12637
- totalDataLabelsY = lowestPrevY - totalLabeltextRects.height / 2 - offY - barTotalDataLabelsConfig.offsetY + ADDITIONAL_OFFY;
12205
+ totalDataLabelsY = lowestPrevY + h * 0.77 - offY - barTotalDataLabelsConfig.offsetY;
12638
12206
  } else {
12639
- totalDataLabelsY = lowestPrevY + totalLabeltextRects.height + offY + barTotalDataLabelsConfig.offsetY - ADDITIONAL_OFFY;
12207
+ totalDataLabelsY = lowestPrevY - h * 0.3 + offY + barTotalDataLabelsConfig.offsetY;
12640
12208
  }
12641
12209
  const xDivision = dataPointsDividedWidth;
12642
12210
  totalDataLabelsX = totalDataLabelsBcx + (w.axisFlags.isXNumeric ? -barWidth / 2 : barWidth / 2 - xDivision) + barTotalDataLabelsConfig.offsetX;
@@ -12666,7 +12234,6 @@ class BarDataLabels {
12666
12234
  const w = this.w;
12667
12235
  let {
12668
12236
  x: x2,
12669
- i,
12670
12237
  j,
12671
12238
  realIndex,
12672
12239
  bcy,
@@ -12683,7 +12250,7 @@ class BarDataLabels {
12683
12250
  } = opts;
12684
12251
  const dataPointsDividedHeight = w.layout.gridHeight / w.globals.dataPoints;
12685
12252
  const { zeroEncounters } = this.barCtx.barHelpers.getZeroValueEncounters({
12686
- i,
12253
+ i: realIndex,
12687
12254
  j
12688
12255
  });
12689
12256
  barWidth = Math.abs(barWidth);
@@ -12700,7 +12267,7 @@ class BarDataLabels {
12700
12267
  let totalDataLabelsX;
12701
12268
  let totalDataLabelsY;
12702
12269
  let totalDataLabelsAnchor = "start";
12703
- const valIsNegative = (_b = opts.neg) != null ? _b : w.seriesData.series[i][j] < 0;
12270
+ const valIsNegative = (_b = opts.neg) != null ? _b : w.seriesData.series[realIndex][j] < 0;
12704
12271
  let newX = x2;
12705
12272
  if (this.barCtx.isReversed) {
12706
12273
  newX = x2 + (valIsNegative ? -barWidth : barWidth);
@@ -12735,10 +12302,14 @@ class BarDataLabels {
12735
12302
  }
12736
12303
  let lowestPrevX = newX;
12737
12304
  const totalGroupCtx = this.getTotalGroupContext(realIndex);
12738
- const stacks = (
12305
+ const top = this.xStackTop(realIndex, j);
12306
+ const stacks = top ? [] : (
12739
12307
  /** @type {any} */
12740
12308
  this.barCtx.stacks || []
12741
12309
  );
12310
+ if (top) {
12311
+ lowestPrevX = valIsNegative ? Math.min(newX, top[4]) : Math.max(newX, top[5]);
12312
+ }
12742
12313
  stacks.forEach((g, gi) => {
12743
12314
  if (totalGroupCtx && gi !== totalGroupCtx.groupIndex) return;
12744
12315
  g.prevX.forEach((arr) => {
@@ -12751,11 +12322,7 @@ class BarDataLabels {
12751
12322
  });
12752
12323
  if (this.hlt) lowestPrevX = this.hlt.edge;
12753
12324
  if (this.drawsStackedTotal(realIndex) && barTotalDataLabelsConfig.enabled) {
12754
- const graphics = new Graphics(this.barCtx.w);
12755
- const totalLabeltextRects = graphics.getTextRects(
12756
- this.getStackedTotalDataLabel({ realIndex, j }),
12757
- dataLabelsConfig.fontSize
12758
- );
12325
+ const totalLabeltextRects = this.totalRects(realIndex, j);
12759
12326
  if (valIsNegative) {
12760
12327
  totalDataLabelsX = lowestPrevX - strokeWidth - offX - barTotalDataLabelsConfig.offsetX;
12761
12328
  totalDataLabelsAnchor = "end";
@@ -12824,8 +12391,9 @@ class BarDataLabels {
12824
12391
  let elDataLabelsWrap = null;
12825
12392
  const isSeriesCollapsed = w.globals.collapsedSeriesIndices.indexOf(i) > -1;
12826
12393
  const isSeriesCollapsing = (w.globals.collapsingSeriesIndices || []).indexOf(i) > -1;
12394
+ const dlKey = `${i}::${this.barCtx._keys(i)[j]}`;
12827
12395
  if (isSeriesCollapsing) {
12828
- const prev = (_a = w.globals.prevDataLabels) == null ? void 0 : _a.get(`${i}::${datumKey(w, i, j)}`);
12396
+ const prev = (_a = w.globals.prevDataLabels) == null ? void 0 : _a.get(dlKey);
12829
12397
  if (prev && isFinite(prev.val)) {
12830
12398
  val = prev.val;
12831
12399
  text = void 0;
@@ -12838,10 +12406,7 @@ class BarDataLabels {
12838
12406
  });
12839
12407
  const dlCfg = w.config.dataLabels;
12840
12408
  if (((_b = dlCfg.animate) == null ? void 0 : _b.enabled) || ((_c = dlCfg.countUp) == null ? void 0 : _c.enabled)) {
12841
- elDataLabelsWrap.node.setAttribute(
12842
- "data:dlKey",
12843
- `${i}::${datumKey(w, i, j)}`
12844
- );
12409
+ elDataLabelsWrap.node.setAttribute("data:dlKey", dlKey);
12845
12410
  elDataLabelsWrap.node.setAttribute("data:dlJ", String(j));
12846
12411
  if (typeof val === "number" && isFinite(val)) {
12847
12412
  elDataLabelsWrap.node.setAttribute("data:dlVal", String(val));
@@ -12859,29 +12424,12 @@ class BarDataLabels {
12859
12424
  if (!val && w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
12860
12425
  text = "";
12861
12426
  }
12862
- const valIsNegative = neg != null ? neg : w.seriesData.series[i][j] < 0;
12863
- const position = w.config.plotOptions.bar.dataLabels.position;
12427
+ let anchor = dataLabelsConfig.textAnchor;
12864
12428
  if (w.config.plotOptions.bar.dataLabels.orientation === "vertical") {
12865
- if (position === "top") {
12866
- if (valIsNegative) dataLabelsConfig.textAnchor = "end";
12867
- else dataLabelsConfig.textAnchor = "start";
12868
- }
12869
- if (position === "center") {
12870
- dataLabelsConfig.textAnchor = "middle";
12871
- }
12872
- if (position === "bottom") {
12873
- if (valIsNegative) dataLabelsConfig.textAnchor = "end";
12874
- else dataLabelsConfig.textAnchor = "start";
12875
- }
12429
+ anchor = w.config.plotOptions.bar.dataLabels.position === "center" ? "middle" : (neg != null ? neg : w.seriesData.series[i][j] < 0) ? "end" : "start";
12876
12430
  }
12877
- if (this.barCtx.isRangeBar && this.barCtx.barOptions.dataLabels.hideOverflowingLabels) {
12878
- const txRect = graphics.getTextRects(
12879
- text,
12880
- parseFloat(dataLabelsConfig.style.fontSize).toString()
12881
- );
12882
- if (barWidth < txRect.width) {
12883
- text = "";
12884
- }
12431
+ if (this.barCtx.isRangeBar && this.barCtx.barOptions.dataLabels.hideOverflowingLabels && barWidth < textRects.width) {
12432
+ text = "";
12885
12433
  }
12886
12434
  if (w.config.chart.stacked && this.barCtx.barOptions.dataLabels.hideOverflowingLabels && // A collapsing series is measured against its NEW extent, which is
12887
12435
  // already zero, so this would blank a label whose bar is still at full
@@ -12897,14 +12445,14 @@ class BarDataLabels {
12897
12445
  }
12898
12446
  }
12899
12447
  }
12900
- const modifiedDataLabelsConfig = __spreadValues({}, dataLabelsConfig);
12901
- if (this.barCtx.isHorizontal) {
12902
- if (val < 0) {
12903
- if (dataLabelsConfig.textAnchor === "start") {
12904
- modifiedDataLabelsConfig.textAnchor = "end";
12905
- } else if (dataLabelsConfig.textAnchor === "end") {
12906
- modifiedDataLabelsConfig.textAnchor = "start";
12907
- }
12448
+ const modifiedDataLabelsConfig = __spreadProps(__spreadValues({}, dataLabelsConfig), {
12449
+ textAnchor: anchor
12450
+ });
12451
+ if (this.barCtx.isHorizontal && val < 0) {
12452
+ if (anchor === "start") {
12453
+ modifiedDataLabelsConfig.textAnchor = "end";
12454
+ } else if (anchor === "end") {
12455
+ modifiedDataLabelsConfig.textAnchor = "start";
12908
12456
  }
12909
12457
  }
12910
12458
  dataLabels.plotDataLabelsText({
@@ -12956,7 +12504,7 @@ class BarDataLabels {
12956
12504
  const { groupIndex } = this.barCtx.barHelpers.getGroupIndex(realIndex);
12957
12505
  totalDataLabelText.node.setAttribute(
12958
12506
  "data:dlTotalKey",
12959
- `${groupIndex}::${datumKey(this.w, realIndex, j)}`
12507
+ `${groupIndex}::${this.barCtx._keys(realIndex)[j]}`
12960
12508
  );
12961
12509
  totalDataLabelText.node.setAttribute(
12962
12510
  "data:dlTotalSeries",
@@ -12986,9 +12534,11 @@ let Helpers$1 = class Helpers3 {
12986
12534
  }
12987
12535
  /**
12988
12536
  * @param {any[]} series
12537
+ * @param {any} [seriesIndex] a combo's real indices of `series`
12989
12538
  */
12990
- initVariables(series) {
12539
+ initVariables(series, seriesIndex) {
12991
12540
  const w = this.w;
12541
+ this.seriesIndex = seriesIndex;
12992
12542
  this.barCtx.series = series;
12993
12543
  this.barCtx.totalItems = 0;
12994
12544
  this.barCtx.seriesLen = 0;
@@ -13009,6 +12559,8 @@ let Helpers$1 = class Helpers3 {
13009
12559
  this.barCtx.visibleItems = w.globals.dataPoints;
13010
12560
  }
13011
12561
  }
12562
+ const labels = w.labelData.labels;
12563
+ this.rows = w.globals.isBarHorizontal && w.axisFlags.isXNumeric && !this.barCtx.isRangeBar && w.seriesData.seriesX.some((s) => s == null ? void 0 : s.some((x2, j) => x2 !== labels[j])) ? new Map(labels.map((x2, r) => [x2, r])) : null;
13012
12564
  this.arrBorderRadius = this.createBorderRadiusArr(w.seriesData.series);
13013
12565
  if (Utils.isSafari()) {
13014
12566
  this.arrBorderRadius = this.arrBorderRadius.map(
@@ -13073,15 +12625,19 @@ let Helpers$1 = class Helpers3 {
13073
12625
  * Collapsed series count too, exactly as they did for `minXDiff`. Skipping
13074
12626
  * them would widen every bar the moment someone hid the tightest-spaced
13075
12627
  * series from the legend, so bar geometry would depend on legend state.
12628
+ * In a combo only this renderer's own series count: a line's x values say
12629
+ * nothing about how wide a column may be.
13076
12630
  *
13077
12631
  * @returns {number}
13078
12632
  */
13079
12633
  _unionMinXGap() {
13080
12634
  const w = this.w;
13081
12635
  const seriesX = w.seriesData.seriesX || [];
12636
+ const own = this.seriesIndex;
13082
12637
  const arrays = [];
13083
12638
  for (let i = 0; i < seriesX.length; i++) {
13084
12639
  const xs = seriesX[i];
12640
+ if (own && own.indexOf(i) < 0) continue;
13085
12641
  if (Array.isArray(xs) && xs.length > 0) {
13086
12642
  arrays.push(
13087
12643
  xs.some((v, n) => v < xs[n - 1]) ? xs.filter((v) => v === +v).sort((a, b) => a - b) : xs
@@ -13122,6 +12678,15 @@ let Helpers$1 = class Helpers3 {
13122
12678
  }
13123
12679
  return isFinite(min) ? min : 0;
13124
12680
  }
12681
+ /**
12682
+ * The band a horizontal bar is drawn in: its x's band when the series do
12683
+ * not line up by index (see initVariables), else its index.
12684
+ * @param {number} realIndex @param {number} j
12685
+ */
12686
+ barRow(realIndex, j) {
12687
+ var _a, _b, _c;
12688
+ return (_c = (_b = this.rows) == null ? void 0 : _b.get((_a = this.w.seriesData.seriesX[realIndex]) == null ? void 0 : _a[j])) != null ? _c : j;
12689
+ }
13125
12690
  /**
13126
12691
  * @param {number} realIndex
13127
12692
  */
@@ -13244,7 +12809,7 @@ let Helpers$1 = class Helpers3 {
13244
12809
  });
13245
12810
  }
13246
12811
  const connectorFill = this.getDumbbellConnectorFill(i, j);
13247
- const datumFill = connectorFill || ((_a = w.config.series[i].data[j]) == null ? void 0 : _a.fill);
12812
+ const datumFill = connectorFill || ((_a = w.config.series[realIndex].data[j]) == null ? void 0 : _a.fill);
13248
12813
  const connector = this.barCtx.barOptions.isDumbbell ? w.config.plotOptions.bar.dumbbell.connector : null;
13249
12814
  let connectorOpacity;
13250
12815
  if (connector && connector.color) {
@@ -13397,11 +12962,10 @@ let Helpers$1 = class Helpers3 {
13397
12962
  * @returns {string[][]}
13398
12963
  */
13399
12964
  createBorderRadiusArr(series) {
13400
- var _a;
13401
12965
  const w = this.w;
13402
12966
  const alwaysApplyRadius = !this.w.config.chart.stacked || w.config.plotOptions.bar.borderRadius <= 0;
13403
12967
  const numSeries = series.length;
13404
- const numColumns = ((_a = series[0]) == null ? void 0 : _a.length) | 0;
12968
+ const numColumns = Math.max(0, ...series.map((s) => (s == null ? void 0 : s.length) | 0));
13405
12969
  const output = Array.from(
13406
12970
  { length: numSeries },
13407
12971
  () => Array(numColumns).fill(alwaysApplyRadius ? "top" : "none")
@@ -13557,7 +13121,7 @@ let Helpers$1 = class Helpers3 {
13557
13121
  j,
13558
13122
  w
13559
13123
  }) {
13560
- var _a, _b;
13124
+ var _a, _b, _c;
13561
13125
  const r = this.barRect({
13562
13126
  a: barXPosition,
13563
13127
  len: barWidth,
@@ -13588,7 +13152,7 @@ let Helpers$1 = class Helpers3 {
13588
13152
  const _ctx = this.barCtx.groupCtx;
13589
13153
  _ctx.yArrj.push(y2 - strokeCenter * direction);
13590
13154
  _ctx.yArrjF.push(Math.abs(y1 - y2 + r.strokeWidth * direction));
13591
- _ctx.yArrjVal.push(this.barCtx.series[i][j]);
13155
+ _ctx.yArrjVal.push((_c = this.barCtx.series[i][j]) != null ? _c : null);
13592
13156
  }
13593
13157
  return {
13594
13158
  pathTo,
@@ -13602,43 +13166,140 @@ let Helpers$1 = class Helpers3 {
13602
13166
  };
13603
13167
  }
13604
13168
  /**
13605
- * Build a trapezoidal funnel-stage path. Used when
13606
- * `plotOptions.funnel.shape === 'trapezoid'` is active alongside `isFunnel`.
13169
+ * Build a trapezoidal funnel-stage path. Used when
13170
+ * `plotOptions.funnel.shape === 'trapezoid'` is active alongside `isFunnel`.
13171
+ *
13172
+ * Each stage is a 4-corner polygon whose top width matches the current
13173
+ * stage's value and bottom width matches the next stage's value, producing
13174
+ * continuous sloped sides between consecutive stages.
13175
+ *
13176
+ * For the last stage, the bottom width is configurable:
13177
+ * - `lastShape: 'flat'` → bottom width = top width (parallel sides)
13178
+ * - `lastShape: 'taper'` → bottom width = 0 (taper to a point)
13179
+ *
13180
+ * @param {{ barYPosition: number, barHeight: number, series: any[][], i: number, j: number, realIndex: number, strokeWidth: number, w: any }} opts
13181
+ */
13182
+ getFunnelTrapezoidPaths({
13183
+ barYPosition,
13184
+ barHeight,
13185
+ series,
13186
+ i,
13187
+ j,
13188
+ realIndex,
13189
+ strokeWidth,
13190
+ w
13191
+ }) {
13192
+ var _a, _b;
13193
+ const graphics = new Graphics(this.barCtx.w);
13194
+ const center = w.layout.gridWidth / 2;
13195
+ const halfWidthFor = (v) => Math.abs(v / this.barCtx.invertedYRatio) / 2;
13196
+ const topHalf = halfWidthFor(series[i][j]);
13197
+ const lastIdx = series[i].length - 1;
13198
+ const isLast = j === lastIdx;
13199
+ const lastShape = w.config.plotOptions.funnel.lastShape === "taper" ? "taper" : "flat";
13200
+ let bottomHalf;
13201
+ if (isLast) {
13202
+ bottomHalf = lastShape === "taper" ? 0 : topHalf;
13203
+ } else {
13204
+ bottomHalf = halfWidthFor(series[i][j + 1]);
13205
+ }
13206
+ const strokeCenter = strokeWidth / 2;
13207
+ const y1 = barYPosition + strokeCenter;
13208
+ const y2 = barYPosition + barHeight - strokeCenter;
13209
+ const topLeftX = center - topHalf;
13210
+ const topRightX = center + topHalf;
13211
+ const bottomLeftX = center - bottomHalf;
13212
+ const bottomRightX = center + bottomHalf;
13213
+ const pathTo = graphics.move(topLeftX, y1) + graphics.line(topRightX, y1) + graphics.line(bottomRightX, y2) + graphics.line(bottomLeftX, y2) + " Z";
13214
+ let pathFrom = null;
13215
+ const morphFrom = (_b = (_a = this.barCtx.ctx) == null ? void 0 : _a.morphTypeChange) == null ? void 0 : _b.getInitialPathFor(
13216
+ realIndex,
13217
+ j
13218
+ );
13219
+ if (morphFrom) {
13220
+ pathFrom = morphFrom;
13221
+ } else if (w.globals.previousPaths.length > 0) {
13222
+ pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo);
13223
+ }
13224
+ if (pathFrom == null) {
13225
+ pathFrom = graphics.move(center, y1) + graphics.line(center, y1) + graphics.line(center, y2) + graphics.line(center, y2) + " Z";
13226
+ }
13227
+ return {
13228
+ pathTo,
13229
+ pathFrom,
13230
+ // x is the right edge of the wider (top) side — used by dataLabel
13231
+ // positioning helpers that expect a "right" reference.
13232
+ x: topRightX,
13233
+ x1: topLeftX,
13234
+ barXPosition: center
13235
+ };
13236
+ }
13237
+ /**
13238
+ * Pre-compute the per-segment layout for a value-proportional pyramid.
13607
13239
  *
13608
- * Each stage is a 4-corner polygon whose top width matches the current
13609
- * stage's value and bottom width matches the next stage's value, producing
13610
- * continuous sloped sides between consecutive stages.
13240
+ * Each segment is a horizontal slice of a triangle whose apex sits at the
13241
+ * top of the plot area (width = 0) and whose base spans `gridWidth` at the
13242
+ * bottom. The vertical extent of each slice is its share of the total
13243
+ * series value, so areas track value contribution and segments share
13244
+ * edges (no gaps). The first data point is the apex, the last is the base.
13611
13245
  *
13612
- * For the last stage, the bottom width is configurable:
13613
- * - `lastShape: 'flat'` → bottom width = top width (parallel sides)
13614
- * - `lastShape: 'taper'` → bottom width = 0 (taper to a point)
13246
+ * @param {any[]} seriesData - 1D array of values for a single series row
13247
+ * @returns {{ y: number, height: number, topHalf: number, bottomHalf: number }[]}
13248
+ */
13249
+ computePyramidLayout(seriesData) {
13250
+ const w = this.w;
13251
+ const gridHeight = w.layout.gridHeight;
13252
+ const gridWidth = w.layout.gridWidth;
13253
+ const values = seriesData.map(
13254
+ /** @param {any} v */
13255
+ (v) => Math.abs(Number(v) || 0)
13256
+ );
13257
+ const total = values.reduce(
13258
+ /** @param {number} a @param {number} b */
13259
+ (a, b) => a + b,
13260
+ 0
13261
+ );
13262
+ if (total === 0 || gridHeight <= 0) {
13263
+ return values.map(() => ({ y: 0, height: 0, topHalf: 0, bottomHalf: 0 }));
13264
+ }
13265
+ const halfWidth = gridWidth / 2;
13266
+ let cumulative = 0;
13267
+ const layout = [];
13268
+ for (let j = 0; j < values.length; j++) {
13269
+ const topRatio = cumulative / total;
13270
+ cumulative += values[j];
13271
+ const bottomRatio = cumulative / total;
13272
+ const topY = topRatio * gridHeight;
13273
+ const bottomY = bottomRatio * gridHeight;
13274
+ layout.push({
13275
+ y: topY,
13276
+ height: bottomY - topY,
13277
+ topHalf: topRatio * halfWidth,
13278
+ bottomHalf: bottomRatio * halfWidth
13279
+ });
13280
+ }
13281
+ return layout;
13282
+ }
13283
+ /**
13284
+ * Build a single pyramid stage path. Geometry is precomputed by
13285
+ * `computePyramidLayout`; this method only renders that geometry into an
13286
+ * SVG path string plus a `pathFrom` for entry/morph animations.
13615
13287
  *
13616
- * @param {{ barYPosition: number, barHeight: number, series: any[][], i: number, j: number, realIndex: number, strokeWidth: number, w: any }} opts
13288
+ * @param {{ barYPosition: number, barHeight: number, topHalf: number, bottomHalf: number, realIndex: number, j: number, strokeWidth: number, w: any }} opts
13617
13289
  */
13618
- getFunnelTrapezoidPaths({
13290
+ getPyramidPaths({
13619
13291
  barYPosition,
13620
13292
  barHeight,
13621
- series,
13622
- i,
13623
- j,
13293
+ topHalf,
13294
+ bottomHalf,
13624
13295
  realIndex,
13296
+ j,
13625
13297
  strokeWidth,
13626
13298
  w
13627
13299
  }) {
13628
13300
  var _a, _b;
13629
13301
  const graphics = new Graphics(this.barCtx.w);
13630
13302
  const center = w.layout.gridWidth / 2;
13631
- const halfWidthFor = (v) => Math.abs(v / this.barCtx.invertedYRatio) / 2;
13632
- const topHalf = halfWidthFor(series[i][j]);
13633
- const lastIdx = series[i].length - 1;
13634
- const isLast = j === lastIdx;
13635
- const lastShape = w.config.plotOptions.funnel.lastShape === "taper" ? "taper" : "flat";
13636
- let bottomHalf;
13637
- if (isLast) {
13638
- bottomHalf = lastShape === "taper" ? 0 : topHalf;
13639
- } else {
13640
- bottomHalf = halfWidthFor(series[i][j + 1]);
13641
- }
13642
13303
  const strokeCenter = strokeWidth / 2;
13643
13304
  const y1 = barYPosition + strokeCenter;
13644
13305
  const y2 = barYPosition + barHeight - strokeCenter;
@@ -13663,497 +13324,912 @@ let Helpers$1 = class Helpers3 {
13663
13324
  return {
13664
13325
  pathTo,
13665
13326
  pathFrom,
13666
- // x is the right edge of the wider (top) side — used by dataLabel
13667
- // positioning helpers that expect a "right" reference.
13668
13327
  x: topRightX,
13669
13328
  x1: topLeftX,
13670
13329
  barXPosition: center
13671
13330
  };
13672
13331
  }
13332
+ /** @param {{ barYPosition?: any, barHeight?: any, x1?: any, x2?: any, strokeWidth?: any, isReversed?: any, series?: any, realIndex?: any, i?: any, j?: any, w?: any }} opts */
13333
+ getBarpaths({
13334
+ barYPosition,
13335
+ barHeight,
13336
+ x1,
13337
+ x2,
13338
+ strokeWidth,
13339
+ series,
13340
+ realIndex,
13341
+ i,
13342
+ j,
13343
+ w
13344
+ }) {
13345
+ var _a, _b, _c;
13346
+ const graphics = new Graphics(this.barCtx.w);
13347
+ const r = this.barRect({
13348
+ a: barYPosition,
13349
+ len: barHeight,
13350
+ v1: x1,
13351
+ v2: x2,
13352
+ strokeWidth,
13353
+ realIndex,
13354
+ j,
13355
+ dir: series[i][j] >= 0 ? 1 : -1,
13356
+ horizontal: true
13357
+ });
13358
+ const { y1, y2, sl, closing, squarePathTo, pathTo, strokeCenter, direction } = r;
13359
+ x1 = r.x1;
13360
+ x2 = r.x2;
13361
+ const isFunnel = this.barCtx.isFunnel;
13362
+ const fromX = isFunnel ? (x1 + x2) / 2 : x1;
13363
+ let pathFrom = null;
13364
+ const morphFrom = (_b = (_a = this.barCtx.ctx) == null ? void 0 : _a.morphTypeChange) == null ? void 0 : _b.getInitialPathFor(
13365
+ realIndex,
13366
+ j
13367
+ );
13368
+ if (morphFrom) {
13369
+ pathFrom = morphFrom;
13370
+ } else if (w.globals.previousPaths.length > 0) {
13371
+ pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo, squarePathTo);
13372
+ }
13373
+ if (pathFrom == null) {
13374
+ const slFrom = isFunnel ? graphics.line(fromX, y2) : sl;
13375
+ pathFrom = graphics.move(fromX, y1) + graphics.line(fromX, y1) + slFrom + slFrom + slFrom + slFrom + slFrom + graphics.line(fromX, y1) + closing;
13376
+ }
13377
+ if (w.config.chart.stacked) {
13378
+ const _ctx = this.barCtx.groupCtx;
13379
+ _ctx.xArrj.push(x2 + strokeCenter * direction);
13380
+ _ctx.xArrjF.push(Math.abs(x1 - x2 - r.strokeWidth * direction));
13381
+ _ctx.xArrjVal.push((_c = this.barCtx.series[i][j]) != null ? _c : null);
13382
+ }
13383
+ return {
13384
+ pathTo,
13385
+ pathFrom,
13386
+ // See getColumnPaths. Here `x1` is the start value's edge and `x2` the
13387
+ // end value's, because a horizontal bar's two ends arrive unsorted.
13388
+ drawnBox: { x1, x2, y1, y2 }
13389
+ };
13390
+ }
13673
13391
  /**
13674
- * Pre-compute the per-segment layout for a value-proportional pyramid.
13392
+ * @param {number} value
13393
+ * @param {number} zeroW
13394
+ */
13395
+ getXForValue(value, zeroW, zeroPositionForNull = true) {
13396
+ let xForVal = zeroPositionForNull ? zeroW : null;
13397
+ if (typeof value !== "undefined" && value !== null) {
13398
+ xForVal = zeroW + value / this.barCtx.invertedYRatio - (this.barCtx.isReversed ? value / this.barCtx.invertedYRatio : 0) * 2;
13399
+ }
13400
+ return xForVal;
13401
+ }
13402
+ /**
13403
+ * @param {number} value
13404
+ * @param {number} zeroH
13405
+ * @param {number} translationsIndex
13406
+ */
13407
+ getYForValue(value, zeroH, translationsIndex, zeroPositionForNull = true) {
13408
+ let yForVal = zeroPositionForNull ? zeroH : null;
13409
+ if (typeof value !== "undefined" && value !== null) {
13410
+ yForVal = zeroH - value / this.barCtx.yRatio[translationsIndex] + (this.barCtx.isReversed ? value / this.barCtx.yRatio[translationsIndex] : 0) * 2;
13411
+ }
13412
+ return yForVal;
13413
+ }
13414
+ /**
13415
+ * @param {string} type
13416
+ * @param {number} zeroW
13417
+ * @param {number} zeroH
13418
+ * @param {number} i
13419
+ * @param {number} j
13420
+ * @param {number} translationsIndex
13421
+ */
13422
+ getGoalValues(type, zeroW, zeroH, i, j, translationsIndex) {
13423
+ const w = this.w;
13424
+ const goals = [];
13425
+ const pushGoal = (value, attrs) => {
13426
+ if (!w.globals.invalidLogScale) {
13427
+ value = new CoreUtils(w).getLogValAtSeriesIndex(value, i);
13428
+ }
13429
+ goals.push({
13430
+ [type]: type === "x" ? this.getXForValue(value, zeroW, false) : this.getYForValue(value, zeroH, translationsIndex, false),
13431
+ attrs
13432
+ });
13433
+ };
13434
+ if (w.seriesData.seriesGoals[i] && w.seriesData.seriesGoals[i][j] && Array.isArray(w.seriesData.seriesGoals[i][j])) {
13435
+ w.seriesData.seriesGoals[i][j].forEach((goal) => {
13436
+ pushGoal(goal.value, goal);
13437
+ });
13438
+ }
13439
+ if (this.barCtx.barOptions.isDumbbell) {
13440
+ const ends = this.getDumbbellEnds(i, j);
13441
+ if (ends.length) {
13442
+ const commonAttrs = {
13443
+ strokeHeight: type === "x" ? 0 : w.globals.markers.size[i],
13444
+ strokeWidth: type === "x" ? w.globals.markers.size[i] : 0,
13445
+ strokeDashArray: 0,
13446
+ strokeLineCap: "round"
13447
+ };
13448
+ let lo = 0;
13449
+ let hi = 0;
13450
+ for (let e = 1; e < ends.length; e++) {
13451
+ if (ends[e].value < ends[lo].value) lo = e;
13452
+ if (ends[e].value > ends[hi].value) hi = e;
13453
+ }
13454
+ const labelsCnf = w.config.plotOptions.bar.dumbbell.dataLabels;
13455
+ ends.forEach((end, e) => {
13456
+ const attrs = __spreadProps(__spreadValues({}, commonAttrs), { strokeColor: end.color });
13457
+ if (labelsCnf.enabled && (e === lo || e === hi)) {
13458
+ attrs.label = {
13459
+ text: this.getDumbbellLabelText(end.value, i, j, end.index),
13460
+ color: labelsCnf.colorFromMarker ? end.color : Array.isArray(labelsCnf.style.colors) ? labelsCnf.style.colors[end.index] || labelsCnf.style.colors[0] : labelsCnf.style.colors,
13461
+ // Away from the connector: the low end reads to its left (below,
13462
+ // on a column), the high end to its right. A lone endpoint has no
13463
+ // connector to be clear of, so it takes the outward side.
13464
+ outward: e === lo && lo !== hi ? -1 : 1
13465
+ };
13466
+ }
13467
+ pushGoal(end.value, attrs);
13468
+ });
13469
+ }
13470
+ }
13471
+ return goals;
13472
+ }
13473
+ /**
13474
+ * The marked ends of one dumbbell row: a value and the colour that says which
13475
+ * measure it belongs to.
13476
+ *
13477
+ * `chart.type: 'dumbbell'` merged N measures into one interval and left the
13478
+ * endpoint identities on `w.dumbbellData`, so an end is coloured after the
13479
+ * SERIES it came from. A row where the two measures cross therefore keeps its
13480
+ * colours, which the interval alone could not say: it is emitted low-to-high
13481
+ * and has forgotten which end was which.
13482
+ *
13483
+ * The `y: [lo, hi]` form names no measures, so it keeps the positional
13484
+ * `dumbbellColors` pathway: colour 0 for the start, colour 1 for the end.
13485
+ *
13486
+ * @param {number} i @param {number} j
13487
+ * @returns {Array<{ value: number, color: string, index: number }>}
13488
+ */
13489
+ getDumbbellEnds(i, j) {
13490
+ const w = this.w;
13491
+ const ends = [];
13492
+ const dumbbell = w.dumbbellData;
13493
+ if (dumbbell && dumbbell.form === "series") {
13494
+ const values = dumbbell.values[j] || [];
13495
+ for (let k2 = 0; k2 < values.length; k2++) {
13496
+ const v = values[k2];
13497
+ if (v === null || dumbbell.hidden.indexOf(k2) !== -1) continue;
13498
+ ends.push({ value: v, color: w.globals.colors[k2], index: k2 });
13499
+ }
13500
+ return ends;
13501
+ }
13502
+ if (!w.rangeData.seriesRange.length) return ends;
13503
+ const colors = this.barCtx.barOptions.dumbbellColors ? this.barCtx.barOptions.dumbbellColors : w.globals.colors;
13504
+ const pick = (n) => Array.isArray(colors[i]) ? colors[i][n] : colors[i];
13505
+ return [
13506
+ { value: w.rangeData.seriesRangeStart[i][j], color: pick(0), index: 0 },
13507
+ { value: w.rangeData.seriesRangeEnd[i][j], color: pick(1), index: 1 }
13508
+ ];
13509
+ }
13510
+ /**
13511
+ * The text for one end label.
13675
13512
  *
13676
- * Each segment is a horizontal slice of a triangle whose apex sits at the
13677
- * top of the plot area (width = 0) and whose base spans `gridWidth` at the
13678
- * bottom. The vertical extent of each slice is its share of the total
13679
- * series value, so areas track value contribution and segments share
13680
- * edges (no gaps). The first data point is the apex, the last is the base.
13513
+ * Deliberately NOT `dataLabels.formatter`: on a range bar that one reads out
13514
+ * `end - start`, so an endpoint run through it would print the gap twice and
13515
+ * the values never. The value-axis formatter is the one that already knows
13516
+ * these numbers are percentages, or dollars, or dates.
13681
13517
  *
13682
- * @param {any[]} seriesData - 1D array of values for a single series row
13683
- * @returns {{ y: number, height: number, topHalf: number, bottomHalf: number }[]}
13518
+ * @param {number} value @param {number} i @param {number} j @param {number} k
13519
+ * @returns {string}
13684
13520
  */
13685
- computePyramidLayout(seriesData) {
13521
+ getDumbbellLabelText(value, i, j, k2) {
13686
13522
  const w = this.w;
13687
- const gridHeight = w.layout.gridHeight;
13688
- const gridWidth = w.layout.gridWidth;
13689
- const values = seriesData.map(
13690
- /** @param {any} v */
13691
- (v) => Math.abs(Number(v) || 0)
13692
- );
13693
- const total = values.reduce(
13694
- /** @param {number} a @param {number} b */
13695
- (a, b) => a + b,
13696
- 0
13697
- );
13698
- if (total === 0 || gridHeight <= 0) {
13699
- return values.map(() => ({ y: 0, height: 0, topHalf: 0, bottomHalf: 0 }));
13700
- }
13701
- const halfWidth = gridWidth / 2;
13702
- let cumulative = 0;
13703
- const layout = [];
13704
- for (let j = 0; j < values.length; j++) {
13705
- const topRatio = cumulative / total;
13706
- cumulative += values[j];
13707
- const bottomRatio = cumulative / total;
13708
- const topY = topRatio * gridHeight;
13709
- const bottomY = bottomRatio * gridHeight;
13710
- layout.push({
13711
- y: topY,
13712
- height: bottomY - topY,
13713
- topHalf: topRatio * halfWidth,
13714
- bottomHalf: bottomRatio * halfWidth
13523
+ const cnf = w.config.plotOptions.bar.dumbbell.dataLabels;
13524
+ if (typeof cnf.formatter === "function") {
13525
+ return cnf.formatter(value, {
13526
+ seriesIndex: i,
13527
+ dataPointIndex: j,
13528
+ endpointIndex: k2,
13529
+ w
13715
13530
  });
13716
13531
  }
13717
- return layout;
13532
+ const axisFormatter = this.barCtx.isHorizontal ? w.formatters.xLabelFormatter : w.formatters.yLabelFormatters[0];
13533
+ if (typeof axisFormatter === "function") {
13534
+ return axisFormatter(value, j, w);
13535
+ }
13536
+ return String(value);
13718
13537
  }
13719
- /**
13720
- * Build a single pyramid stage path. Geometry is precomputed by
13721
- * `computePyramidLayout`; this method only renders that geometry into an
13722
- * SVG path string plus a `pathFrom` for entry/morph animations.
13723
- *
13724
- * @param {{ barYPosition: number, barHeight: number, topHalf: number, bottomHalf: number, realIndex: number, j: number, strokeWidth: number, w: any }} opts
13725
- */
13726
- getPyramidPaths({
13538
+ /** @param {{barXPosition: any, barYPosition: any, goalX: any, goalY: any, barWidth: any, barHeight: any}} opts */
13539
+ drawGoalLine({
13540
+ barXPosition,
13727
13541
  barYPosition,
13728
- barHeight,
13729
- topHalf,
13730
- bottomHalf,
13731
- realIndex,
13732
- j,
13733
- strokeWidth,
13734
- w
13542
+ goalX,
13543
+ goalY,
13544
+ barWidth,
13545
+ barHeight
13735
13546
  }) {
13736
- var _a, _b;
13547
+ const hasGoals = Array.isArray(goalX) && goalX.length > 0 || Array.isArray(goalY) && goalY.length > 0;
13548
+ if (!hasGoals) {
13549
+ return null;
13550
+ }
13737
13551
  const graphics = new Graphics(this.barCtx.w);
13738
- const center = w.layout.gridWidth / 2;
13739
- const strokeCenter = strokeWidth / 2;
13740
- const y1 = barYPosition + strokeCenter;
13741
- const y2 = barYPosition + barHeight - strokeCenter;
13742
- const topLeftX = center - topHalf;
13743
- const topRightX = center + topHalf;
13744
- const bottomLeftX = center - bottomHalf;
13745
- const bottomRightX = center + bottomHalf;
13746
- const pathTo = graphics.move(topLeftX, y1) + graphics.line(topRightX, y1) + graphics.line(bottomRightX, y2) + graphics.line(bottomLeftX, y2) + " Z";
13747
- let pathFrom = null;
13748
- const morphFrom = (_b = (_a = this.barCtx.ctx) == null ? void 0 : _a.morphTypeChange) == null ? void 0 : _b.getInitialPathFor(
13749
- realIndex,
13750
- j
13552
+ const lineGroup = graphics.group({
13553
+ class: "apexcharts-bar-goals-groups"
13554
+ });
13555
+ lineGroup.node.classList.add("apexcharts-element-hidden");
13556
+ this.barCtx.w.globals.delayedElements.push({
13557
+ el: lineGroup.node
13558
+ });
13559
+ lineGroup.attr(
13560
+ "clip-path",
13561
+ `url(#gridRectMarkerMask${this.barCtx.w.globals.cuid})`
13751
13562
  );
13752
- if (morphFrom) {
13753
- pathFrom = morphFrom;
13754
- } else if (w.globals.previousPaths.length > 0) {
13755
- pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo);
13756
- }
13757
- if (pathFrom == null) {
13758
- pathFrom = graphics.move(center, y1) + graphics.line(center, y1) + graphics.line(center, y2) + graphics.line(center, y2) + " Z";
13563
+ let line = null;
13564
+ if (this.barCtx.isHorizontal) {
13565
+ if (Array.isArray(goalX)) {
13566
+ goalX.forEach((goal) => {
13567
+ if (goal.x >= -1 && goal.x <= graphics.w.layout.gridWidth + 1) {
13568
+ const sHeight = typeof goal.attrs.strokeHeight !== "undefined" ? goal.attrs.strokeHeight : barHeight / 2;
13569
+ const y = barYPosition + sHeight + barHeight / 2;
13570
+ line = graphics.drawLine(
13571
+ goal.x,
13572
+ y - sHeight * 2,
13573
+ goal.x,
13574
+ y,
13575
+ goal.attrs.strokeColor ? goal.attrs.strokeColor : void 0,
13576
+ goal.attrs.strokeDashArray,
13577
+ goal.attrs.strokeWidth ? goal.attrs.strokeWidth : 2,
13578
+ goal.attrs.strokeLineCap
13579
+ );
13580
+ lineGroup.add(line);
13581
+ if (goal.attrs.label) {
13582
+ lineGroup.add(
13583
+ this.drawDumbbellLabel(goal.attrs, {
13584
+ x: goal.x,
13585
+ y: y - sHeight,
13586
+ horizontal: true,
13587
+ markerSize: goal.attrs.strokeWidth || 0
13588
+ })
13589
+ );
13590
+ }
13591
+ }
13592
+ });
13593
+ }
13594
+ } else {
13595
+ if (Array.isArray(goalY)) {
13596
+ goalY.forEach((goal) => {
13597
+ if (goal.y >= -1 && goal.y <= graphics.w.layout.gridHeight + 1) {
13598
+ const sWidth = typeof goal.attrs.strokeWidth !== "undefined" ? goal.attrs.strokeWidth : barWidth / 2;
13599
+ const x2 = barXPosition + sWidth + barWidth / 2;
13600
+ line = graphics.drawLine(
13601
+ x2 - sWidth * 2,
13602
+ goal.y,
13603
+ x2,
13604
+ goal.y,
13605
+ goal.attrs.strokeColor ? goal.attrs.strokeColor : void 0,
13606
+ goal.attrs.strokeDashArray,
13607
+ goal.attrs.strokeHeight ? goal.attrs.strokeHeight : 2,
13608
+ goal.attrs.strokeLineCap
13609
+ );
13610
+ lineGroup.add(line);
13611
+ if (goal.attrs.label) {
13612
+ lineGroup.add(
13613
+ this.drawDumbbellLabel(goal.attrs, {
13614
+ x: x2 - sWidth,
13615
+ y: goal.y,
13616
+ horizontal: false,
13617
+ markerSize: goal.attrs.strokeHeight || 0
13618
+ })
13619
+ );
13620
+ }
13621
+ }
13622
+ });
13623
+ }
13759
13624
  }
13760
- return {
13761
- pathTo,
13762
- pathFrom,
13763
- x: topRightX,
13764
- x1: topLeftX,
13765
- barXPosition: center
13766
- };
13625
+ return lineGroup;
13767
13626
  }
13768
- /** @param {{ barYPosition?: any, barHeight?: any, x1?: any, x2?: any, strokeWidth?: any, isReversed?: any, series?: any, realIndex?: any, i?: any, j?: any, w?: any }} opts */
13769
- getBarpaths({
13770
- barYPosition,
13771
- barHeight,
13772
- x1,
13773
- x2,
13774
- strokeWidth,
13775
- series,
13776
- realIndex,
13777
- i,
13778
- j,
13779
- w
13780
- }) {
13781
- var _a, _b;
13627
+ /**
13628
+ * One dumbbell end label, placed clear of the marker it belongs to.
13629
+ *
13630
+ * Offset from the marker's EDGE rather than its centre, so growing
13631
+ * `markers.size` never walks a label under its own dot. Vertically it is
13632
+ * centred on the marker with `dominant-baseline`, which is exact whatever the
13633
+ * font metrics are, where a dy fudge factor drifts with font size.
13634
+ *
13635
+ * @param {Record<string, any>} attrs the goal's attrs, carrying `label`
13636
+ * @param {{x: number, y: number, horizontal: boolean, markerSize: number}} pos
13637
+ */
13638
+ drawDumbbellLabel(attrs, pos) {
13639
+ const w = this.w;
13640
+ const graphics = new Graphics(w);
13641
+ const cnf = w.config.plotOptions.bar.dumbbell.dataLabels;
13642
+ const gap = pos.markerSize / 2 + cnf.offset;
13643
+ const away = attrs.label.outward;
13644
+ return graphics.drawText({
13645
+ x: pos.x + (pos.horizontal ? gap * away : 0),
13646
+ y: pos.y - (pos.horizontal ? 0 : gap * away),
13647
+ text: attrs.label.text,
13648
+ textAnchor: pos.horizontal ? away < 0 ? "end" : "start" : "middle",
13649
+ dominantBaseline: pos.horizontal ? "central" : away < 0 ? "hanging" : "auto",
13650
+ foreColor: attrs.label.color,
13651
+ fontSize: cnf.style.fontSize,
13652
+ fontFamily: cnf.style.fontFamily,
13653
+ fontWeight: cnf.style.fontWeight,
13654
+ cssClass: "apexcharts-dumbbell-label"
13655
+ });
13656
+ }
13657
+ /** @param {{prevPaths: any, currPaths: any, color: any, realIndex: any, j: any}} opts */
13658
+ drawBarShadow({ prevPaths, currPaths, color, realIndex, j }) {
13659
+ const w = this.w;
13660
+ const { x: prevX2, x1: prevX1, barYPosition: prevY1 } = prevPaths;
13661
+ const { x: currX2, x1: currX1, barYPosition: currY1 } = currPaths;
13662
+ const prevY2 = prevY1 + currPaths.barHeight;
13782
13663
  const graphics = new Graphics(this.barCtx.w);
13783
- const r = this.barRect({
13784
- a: barYPosition,
13785
- len: barHeight,
13786
- v1: x1,
13787
- v2: x2,
13788
- strokeWidth,
13789
- realIndex,
13790
- j,
13791
- dir: series[i][j] >= 0 ? 1 : -1,
13792
- horizontal: true
13664
+ const utils = new Utils();
13665
+ const shadowPath = graphics.move(prevX1, prevY2) + graphics.line(prevX2, prevY2) + graphics.line(currX2, currY1) + graphics.line(currX1, currY1) + graphics.line(prevX1, prevY2) + (w.config.plotOptions.bar.borderRadiusApplication === "around" || this.arrBorderRadius[realIndex][j] === "both" ? " Z" : " z");
13666
+ return graphics.drawPath({
13667
+ d: shadowPath,
13668
+ fill: utils.shadeColor(0.5, Utils.rgb2hex(color)),
13669
+ stroke: "none",
13670
+ strokeWidth: 0,
13671
+ fillOpacity: 1,
13672
+ classes: "apexcharts-bar-shadow apexcharts-decoration-element"
13673
+ });
13674
+ }
13675
+ /** @param {{i: any, j: any}} opts */
13676
+ getZeroValueEncounters({ i, j }) {
13677
+ var _a;
13678
+ const w = this.w;
13679
+ let nonZeroColumns = 0;
13680
+ let zeroEncounters = 0;
13681
+ const seriesIndices = w.config.plotOptions.bar.horizontal ? w.seriesData.series.map((_, _i) => _i) : ((_a = w.globals.columnSeries) == null ? void 0 : _a.i.map((_i) => _i)) || [];
13682
+ seriesIndices.forEach((_si) => {
13683
+ const val = w.seriesData.series[_si][j];
13684
+ if (val) {
13685
+ nonZeroColumns++;
13686
+ }
13687
+ if (_si < i && !val) {
13688
+ zeroEncounters++;
13689
+ }
13793
13690
  });
13794
- const { y1, y2, sl, closing, squarePathTo, pathTo, strokeCenter, direction } = r;
13795
- x1 = r.x1;
13796
- x2 = r.x2;
13797
- const isFunnel = this.barCtx.isFunnel;
13798
- const fromX = isFunnel ? (x1 + x2) / 2 : x1;
13799
- let pathFrom = null;
13800
- const morphFrom = (_b = (_a = this.barCtx.ctx) == null ? void 0 : _a.morphTypeChange) == null ? void 0 : _b.getInitialPathFor(
13801
- realIndex,
13802
- j
13803
- );
13804
- if (morphFrom) {
13805
- pathFrom = morphFrom;
13806
- } else if (w.globals.previousPaths.length > 0) {
13807
- pathFrom = this.barCtx.getPreviousPath(realIndex, j, pathTo, squarePathTo);
13808
- }
13809
- if (pathFrom == null) {
13810
- const slFrom = isFunnel ? graphics.line(fromX, y2) : sl;
13811
- pathFrom = graphics.move(fromX, y1) + graphics.line(fromX, y1) + slFrom + slFrom + slFrom + slFrom + slFrom + graphics.line(fromX, y1) + closing;
13812
- }
13813
- if (w.config.chart.stacked) {
13814
- const _ctx = this.barCtx.groupCtx;
13815
- _ctx.xArrj.push(x2 + strokeCenter * direction);
13816
- _ctx.xArrjF.push(Math.abs(x1 - x2 - r.strokeWidth * direction));
13817
- _ctx.xArrjVal.push(this.barCtx.series[i][j]);
13818
- }
13819
13691
  return {
13820
- pathTo,
13821
- pathFrom,
13822
- // See getColumnPaths. Here `x1` is the start value's edge and `x2` the
13823
- // end value's, because a horizontal bar's two ends arrive unsorted.
13824
- drawnBox: { x1, x2, y1, y2 }
13692
+ nonZeroColumns,
13693
+ zeroEncounters
13825
13694
  };
13826
13695
  }
13827
13696
  /**
13828
- * @param {number} value
13829
- * @param {number} zeroW
13697
+ * Index of the series group `seriesIndex` belongs to within
13698
+ * `w.labelData.seriesGroups`, or -1 when the chart has no groups.
13699
+ *
13700
+ * Unlike `getGroupIndex` this is a pure lookup: it never appends to
13701
+ * `columnGroupIndices`, so it is safe to call from positioning/label code
13702
+ * that must not perturb the draw order bookkeeping.
13703
+ * @param {number} seriesIndex
13704
+ * @returns {number}
13830
13705
  */
13831
- getXForValue(value, zeroW, zeroPositionForNull = true) {
13832
- let xForVal = zeroPositionForNull ? zeroW : null;
13833
- if (typeof value !== "undefined" && value !== null) {
13834
- xForVal = zeroW + value / this.barCtx.invertedYRatio - (this.barCtx.isReversed ? value / this.barCtx.invertedYRatio : 0) * 2;
13835
- }
13836
- return xForVal;
13706
+ getSeriesGroupIndex(seriesIndex) {
13707
+ var _a;
13708
+ return (_a = this.w.labelData.seriesGroupIndex[seriesIndex]) != null ? _a : -1;
13837
13709
  }
13838
13710
  /**
13839
- * @param {number} value
13840
- * @param {number} zeroH
13841
- * @param {number} translationsIndex
13711
+ * @param {number} seriesIndex
13842
13712
  */
13843
- getYForValue(value, zeroH, translationsIndex, zeroPositionForNull = true) {
13844
- let yForVal = zeroPositionForNull ? zeroH : null;
13845
- if (typeof value !== "undefined" && value !== null) {
13846
- yForVal = zeroH - value / this.barCtx.yRatio[translationsIndex] + (this.barCtx.isReversed ? value / this.barCtx.yRatio[translationsIndex] : 0) * 2;
13713
+ getGroupIndex(seriesIndex) {
13714
+ const groupIndex = this.getSeriesGroupIndex(seriesIndex);
13715
+ const cGI = this.barCtx.columnGroupIndices;
13716
+ let columnGroupIndex = cGI.indexOf(groupIndex);
13717
+ if (columnGroupIndex < 0) {
13718
+ cGI.push(groupIndex);
13719
+ columnGroupIndex = cGI.length - 1;
13847
13720
  }
13848
- return yForVal;
13721
+ return { groupIndex, columnGroupIndex };
13849
13722
  }
13850
- /**
13851
- * @param {string} type
13852
- * @param {number} zeroW
13853
- * @param {number} zeroH
13854
- * @param {number} i
13855
- * @param {number} j
13856
- * @param {number} translationsIndex
13857
- */
13858
- getGoalValues(type, zeroW, zeroH, i, j, translationsIndex) {
13859
- const w = this.w;
13860
- const goals = [];
13861
- const pushGoal = (value, attrs) => {
13862
- goals.push({
13863
- [type]: type === "x" ? this.getXForValue(value, zeroW, false) : this.getYForValue(value, zeroH, translationsIndex, false),
13864
- attrs
13865
- });
13866
- };
13867
- if (w.seriesData.seriesGoals[i] && w.seriesData.seriesGoals[i][j] && Array.isArray(w.seriesData.seriesGoals[i][j])) {
13868
- w.seriesData.seriesGoals[i][j].forEach((goal) => {
13869
- pushGoal(goal.value, goal);
13870
- });
13871
- }
13872
- if (this.barCtx.barOptions.isDumbbell) {
13873
- const ends = this.getDumbbellEnds(i, j);
13874
- if (ends.length) {
13875
- const commonAttrs = {
13876
- strokeHeight: type === "x" ? 0 : w.globals.markers.size[i],
13877
- strokeWidth: type === "x" ? w.globals.markers.size[i] : 0,
13878
- strokeDashArray: 0,
13879
- strokeLineCap: "round"
13880
- };
13881
- let lo = 0;
13882
- let hi = 0;
13883
- for (let e = 1; e < ends.length; e++) {
13884
- if (ends[e].value < ends[lo].value) lo = e;
13885
- if (ends[e].value > ends[hi].value) hi = e;
13886
- }
13887
- const labelsCnf = w.config.plotOptions.bar.dumbbell.dataLabels;
13888
- ends.forEach((end, e) => {
13889
- const attrs = __spreadProps(__spreadValues({}, commonAttrs), { strokeColor: end.color });
13890
- if (labelsCnf.enabled && (e === lo || e === hi)) {
13891
- attrs.label = {
13892
- text: this.getDumbbellLabelText(end.value, i, j, end.index),
13893
- color: labelsCnf.colorFromMarker ? end.color : Array.isArray(labelsCnf.style.colors) ? labelsCnf.style.colors[end.index] || labelsCnf.style.colors[0] : labelsCnf.style.colors,
13894
- // Away from the connector: the low end reads to its left (below,
13895
- // on a column), the high end to its right. A lone endpoint has no
13896
- // connector to be clear of, so it takes the outward side.
13897
- outward: e === lo && lo !== hi ? -1 : 1
13898
- };
13899
- }
13900
- pushGoal(end.value, attrs);
13901
- });
13723
+ };
13724
+ function buildUnionEntries(join, oldN) {
13725
+ const exitSet = new Set(join.exits);
13726
+ const entries = [];
13727
+ let oi = 0;
13728
+ for (let nj = 0; nj < join.toOld.length; nj++) {
13729
+ const oj = join.toOld[nj];
13730
+ if (oj !== -1) {
13731
+ while (oi < oj) {
13732
+ if (exitSet.has(oi)) entries.push({ oldJ: oi, newJ: -1 });
13733
+ oi++;
13902
13734
  }
13735
+ entries.push({ oldJ: oj, newJ: nj });
13736
+ oi = oj + 1;
13737
+ } else {
13738
+ entries.push({ oldJ: -1, newJ: nj });
13903
13739
  }
13904
- return goals;
13905
13740
  }
13906
- /**
13907
- * The marked ends of one dumbbell row: a value and the colour that says which
13908
- * measure it belongs to.
13909
- *
13910
- * `chart.type: 'dumbbell'` merged N measures into one interval and left the
13911
- * endpoint identities on `w.dumbbellData`, so an end is coloured after the
13912
- * SERIES it came from. A row where the two measures cross therefore keeps its
13913
- * colours, which the interval alone could not say: it is emitted low-to-high
13914
- * and has forgotten which end was which.
13915
- *
13916
- * The `y: [lo, hi]` form names no measures, so it keeps the positional
13917
- * `dumbbellColors` pathway: colour 0 for the start, colour 1 for the end.
13918
- *
13919
- * @param {number} i @param {number} j
13920
- * @returns {Array<{ value: number, color: string, index: number }>}
13921
- */
13922
- getDumbbellEnds(i, j) {
13923
- const w = this.w;
13924
- const ends = [];
13925
- const dumbbell = w.dumbbellData;
13926
- if (dumbbell && dumbbell.form === "series") {
13927
- const values = dumbbell.values[j] || [];
13928
- for (let k2 = 0; k2 < values.length; k2++) {
13929
- const v = values[k2];
13930
- if (v === null || dumbbell.hidden.indexOf(k2) !== -1) continue;
13931
- ends.push({ value: v, color: w.globals.colors[k2], index: k2 });
13741
+ while (oi < oldN) {
13742
+ if (exitSet.has(oi)) entries.push({ oldJ: oi, newJ: -1 });
13743
+ oi++;
13744
+ }
13745
+ return entries;
13746
+ }
13747
+ function analyzeSeriesPath(d, expectedAnchors, isArea) {
13748
+ if (!d || typeof d !== "string") return null;
13749
+ const cmds = parsePath(d);
13750
+ if (!cmds.length || cmds[0][0] !== "M") return null;
13751
+ for (let i = 1; i < cmds.length; i++) {
13752
+ if (cmds[i][0] === "M") return null;
13753
+ }
13754
+ let body = cmds;
13755
+ let closing = null;
13756
+ if (isArea) {
13757
+ if (cmds.length < 5) return null;
13758
+ closing = cmds.slice(-3);
13759
+ body = cmds.slice(0, -3);
13760
+ if (closing[2][0] !== "Z") return null;
13761
+ if (closing[1][0] !== "L") return null;
13762
+ if (closing[0][0] !== "L" && closing[0][0] !== "C") return null;
13763
+ } else if (cmds[cmds.length - 1][0] === "Z") {
13764
+ return null;
13765
+ }
13766
+ if (body.length !== expectedAnchors || body.length < 2) return null;
13767
+ const segType = body[1][0];
13768
+ if (segType !== "L" && segType !== "C") return null;
13769
+ for (let i = 2; i < body.length; i++) {
13770
+ if (body[i][0] !== segType) return null;
13771
+ }
13772
+ const anchors = body.map(
13773
+ (c) => c[0] === "C" ? [Number(c[5]), Number(c[6])] : [Number(c[1]), Number(c[2])]
13774
+ );
13775
+ for (const a of anchors) {
13776
+ if (!isFinite(a[0]) || !isFinite(a[1])) return null;
13777
+ }
13778
+ return { body, closing, segType, anchors };
13779
+ }
13780
+ function lerpPt(a, b, t) {
13781
+ return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t];
13782
+ }
13783
+ function splitCubic(s, cmd, t) {
13784
+ const p0 = s;
13785
+ const p1 = [cmd[1], cmd[2]];
13786
+ const p2 = [cmd[3], cmd[4]];
13787
+ const p3 = [cmd[5], cmd[6]];
13788
+ const p01 = lerpPt(p0, p1, t);
13789
+ const p12 = lerpPt(p1, p2, t);
13790
+ const p23 = lerpPt(p2, p3, t);
13791
+ const p012 = lerpPt(p01, p12, t);
13792
+ const p123 = lerpPt(p12, p23, t);
13793
+ const mid = lerpPt(p012, p123, t);
13794
+ return {
13795
+ first: ["C", p01[0], p01[1], p012[0], p012[1], mid[0], mid[1]],
13796
+ second: ["C", p123[0], p123[1], p23[0], p23[1], p3[0], p3[1]],
13797
+ mid
13798
+ };
13799
+ }
13800
+ function splitLine(s, cmd, t) {
13801
+ const e = [cmd[1], cmd[2]];
13802
+ const mid = lerpPt(s, e, t);
13803
+ return {
13804
+ first: ["L", mid[0], mid[1]],
13805
+ second: ["L", e[0], e[1]],
13806
+ mid
13807
+ };
13808
+ }
13809
+ function expandPath(analysis, ownIdx) {
13810
+ const { body, closing, segType, anchors } = analysis;
13811
+ const n = anchors.length;
13812
+ const m = ownIdx.length;
13813
+ const degen = (p) => segType === "C" ? ["C", p[0], p[1], p[0], p[1], p[0], p[1]] : ["L", p[0], p[1]];
13814
+ const out = [["M", anchors[0][0], anchors[0][1]]];
13815
+ let firstOwn = 0;
13816
+ while (firstOwn < m && ownIdx[firstOwn] !== 0) firstOwn++;
13817
+ for (let q = 1; q <= firstOwn; q++) out.push(degen(anchors[0]));
13818
+ let entry = firstOwn + 1;
13819
+ for (let s = 0; s < n - 1; s++) {
13820
+ let interior = 0;
13821
+ while (entry + interior < m && ownIdx[entry + interior] === -1) interior++;
13822
+ const cmd = body[s + 1];
13823
+ if (!interior) {
13824
+ out.push(cmd.slice());
13825
+ } else {
13826
+ const totalParts = interior + 1;
13827
+ let start = anchors[s];
13828
+ let rest = cmd;
13829
+ for (let q = 0; q < interior; q++) {
13830
+ const t = 1 / (totalParts - q);
13831
+ const sp = segType === "C" ? splitCubic(start, rest, t) : splitLine(start, rest, t);
13832
+ out.push(sp.first);
13833
+ start = sp.mid;
13834
+ rest = sp.second;
13932
13835
  }
13933
- return ends;
13836
+ out.push(rest);
13934
13837
  }
13935
- if (!w.rangeData.seriesRange.length) return ends;
13936
- const colors = this.barCtx.barOptions.dumbbellColors ? this.barCtx.barOptions.dumbbellColors : w.globals.colors;
13937
- const pick = (n) => Array.isArray(colors[i]) ? colors[i][n] : colors[i];
13938
- return [
13939
- { value: w.rangeData.seriesRangeStart[i][j], color: pick(0), index: 0 },
13940
- { value: w.rangeData.seriesRangeEnd[i][j], color: pick(1), index: 1 }
13941
- ];
13838
+ entry += interior + 1;
13942
13839
  }
13943
- /**
13944
- * The text for one end label.
13945
- *
13946
- * Deliberately NOT `dataLabels.formatter`: on a range bar that one reads out
13947
- * `end - start`, so an endpoint run through it would print the gap twice and
13948
- * the values never. The value-axis formatter is the one that already knows
13949
- * these numbers are percentages, or dollars, or dates.
13950
- *
13951
- * @param {number} value @param {number} i @param {number} j @param {number} k
13952
- * @returns {string}
13953
- */
13954
- getDumbbellLabelText(value, i, j, k2) {
13955
- const w = this.w;
13956
- const cnf = w.config.plotOptions.bar.dumbbell.dataLabels;
13957
- if (typeof cnf.formatter === "function") {
13958
- return cnf.formatter(value, {
13959
- seriesIndex: i,
13960
- dataPointIndex: j,
13961
- endpointIndex: k2,
13962
- w
13963
- });
13964
- }
13965
- const axisFormatter = this.barCtx.isHorizontal ? w.formatters.xLabelFormatter : w.formatters.yLabelFormatters[0];
13966
- if (typeof axisFormatter === "function") {
13967
- return axisFormatter(value, j, w);
13840
+ while (entry < m) {
13841
+ out.push(degen(anchors[n - 1]));
13842
+ entry++;
13843
+ }
13844
+ if (closing) closing.forEach((c) => out.push(c.slice()));
13845
+ return out;
13846
+ }
13847
+ function reconcilePathPair(fromD, toD, entries, oldN, newN, isArea) {
13848
+ const fromAnalysis = analyzeSeriesPath(fromD, oldN, isArea);
13849
+ if (!fromAnalysis) return null;
13850
+ const toAnalysis = analyzeSeriesPath(toD, newN, isArea);
13851
+ if (!toAnalysis) return null;
13852
+ if (fromAnalysis.segType !== toAnalysis.segType) return null;
13853
+ if ((fromAnalysis.closing || toAnalysis.closing) && (!fromAnalysis.closing || !toAnalysis.closing || fromAnalysis.closing[0][0] !== toAnalysis.closing[0][0])) {
13854
+ return null;
13855
+ }
13856
+ const fromOwn = entries.map((e) => e.oldJ);
13857
+ const toOwn = entries.map((e) => e.newJ);
13858
+ return {
13859
+ from: arrayToPath(expandPath(fromAnalysis, fromOwn)),
13860
+ toInterp: arrayToPath(expandPath(toAnalysis, toOwn))
13861
+ };
13862
+ }
13863
+ function lengthTransitionEnabled(w) {
13864
+ var _a;
13865
+ const anim = w.config.chart.animations;
13866
+ if (!anim || anim.enabled === false) return false;
13867
+ if (!anim.dynamicAnimation || anim.dynamicAnimation.enabled === false) {
13868
+ return false;
13869
+ }
13870
+ const largeThreshold = (_a = anim.largeDatasetThreshold) != null ? _a : 0;
13871
+ if (largeThreshold > 0 && w.globals.dataPoints > largeThreshold) return false;
13872
+ return !!(Environment.isBrowser() && w.globals.dataChanged && w.globals.shouldAnimate);
13873
+ }
13874
+ function datumKey(w, realIndex, j) {
13875
+ var _a, _b, _c, _d;
13876
+ if ((_a = w.axisFlags) == null ? void 0 : _a.isXNumeric) {
13877
+ const sx = (_c = (_b = w.seriesData) == null ? void 0 : _b.seriesX) == null ? void 0 : _c[realIndex];
13878
+ if (sx && sx.length && sx[j] != null) return "x:" + sx[j];
13879
+ }
13880
+ const lbl = (_d = w.globals.labels) == null ? void 0 : _d[j];
13881
+ if (lbl != null && String(lbl) !== "") {
13882
+ return "c:" + (Array.isArray(lbl) ? lbl.join(" ") : String(lbl));
13883
+ }
13884
+ return "j:" + j;
13885
+ }
13886
+ function frameDatumKey(frame, realIndex, j) {
13887
+ var _a, _b;
13888
+ if (frame.isXNumeric) {
13889
+ const sx = (_a = frame.seriesX) == null ? void 0 : _a[realIndex];
13890
+ if (sx && sx.length && sx[j] != null) return "x:" + sx[j];
13891
+ }
13892
+ const lbl = (_b = frame.labels) == null ? void 0 : _b[j];
13893
+ if (lbl != null && String(lbl) !== "") {
13894
+ return "c:" + (Array.isArray(lbl) ? lbl.join(" ") : String(lbl));
13895
+ }
13896
+ return "j:" + j;
13897
+ }
13898
+ function joinKeys(oldKeys, newKeys) {
13899
+ const oldIndex = /* @__PURE__ */ new Map();
13900
+ oldKeys.forEach((k2, i) => {
13901
+ if (!oldIndex.has(k2)) oldIndex.set(k2, i);
13902
+ });
13903
+ const toOld = new Array(newKeys.length);
13904
+ const usedOld = /* @__PURE__ */ new Set();
13905
+ let prev = -1;
13906
+ let ordered = true;
13907
+ let identity = oldKeys.length === newKeys.length;
13908
+ newKeys.forEach((k2, i) => {
13909
+ const oi = oldIndex.has(k2) && !usedOld.has(oldIndex.get(k2)) ? oldIndex.get(k2) : -1;
13910
+ toOld[i] = oi;
13911
+ if (oi !== -1) {
13912
+ usedOld.add(oi);
13913
+ if (oi < prev) ordered = false;
13914
+ prev = oi;
13968
13915
  }
13969
- return String(value);
13916
+ if (oi !== i) identity = false;
13917
+ });
13918
+ const exits = [];
13919
+ for (let i = 0; i < oldKeys.length; i++) {
13920
+ if (!usedOld.has(i)) exits.push(i);
13970
13921
  }
13971
- /** @param {{barXPosition: any, barYPosition: any, goalX: any, goalY: any, barWidth: any, barHeight: any}} opts */
13972
- drawGoalLine({
13973
- barXPosition,
13974
- barYPosition,
13975
- goalX,
13976
- goalY,
13977
- barWidth,
13978
- barHeight
13979
- }) {
13980
- const hasGoals = Array.isArray(goalX) && goalX.length > 0 || Array.isArray(goalY) && goalY.length > 0;
13981
- if (!hasGoals) {
13982
- return null;
13922
+ return { toOld, exits, ordered, changed: !identity };
13923
+ }
13924
+ function uniquifyKeys(keys) {
13925
+ const seen = /* @__PURE__ */ new Map();
13926
+ return keys.map((k2) => {
13927
+ const count = seen.get(k2) || 0;
13928
+ seen.set(k2, count + 1);
13929
+ return count === 0 ? k2 : `${k2}#${count}`;
13930
+ });
13931
+ }
13932
+ function seriesKeys(w, realIndex, n = ((_a) => (_a = w.seriesData.series[realIndex]) == null ? void 0 : _a.length)() | 0) {
13933
+ return uniquifyKeys(
13934
+ Array.from({ length: n }, (_, j) => datumKey(w, realIndex, j))
13935
+ );
13936
+ }
13937
+ function seriesJoin(w, realIndex, includeIdentity = false, allowReorder = false) {
13938
+ var _a, _b;
13939
+ if (!lengthTransitionEnabled(w)) return null;
13940
+ const frame = w.globals.prevStreamFrame;
13941
+ if (!frame) return null;
13942
+ const oldY = (_a = frame.seriesY) == null ? void 0 : _a[realIndex];
13943
+ const newY = (_b = w.seriesData.series) == null ? void 0 : _b[realIndex];
13944
+ if (!Array.isArray(oldY) || !Array.isArray(newY)) return null;
13945
+ if (!oldY.length || !newY.length) return null;
13946
+ const oldKeys = uniquifyKeys(
13947
+ oldY.map((_, j) => frameDatumKey(frame, realIndex, j))
13948
+ );
13949
+ const newKeys = seriesKeys(w, realIndex);
13950
+ const join = joinKeys(oldKeys, newKeys);
13951
+ if (!join.ordered && !allowReorder) return null;
13952
+ if (!join.changed && !includeIdentity) return null;
13953
+ return { join, oldKeys, newKeys };
13954
+ }
13955
+ function morphEasing(w) {
13956
+ var _a, _b;
13957
+ const anim = w.config.chart.animations;
13958
+ return resolveEasing((_b = (_a = anim.dynamicAnimation) == null ? void 0 : _a.easing) != null ? _b : anim.easing);
13959
+ }
13960
+ function rafTween(w, duration, ease, onFrame, onDone) {
13961
+ const startAt = performance.now();
13962
+ const step = (now) => {
13963
+ if (w.globals.isDestroyed) return;
13964
+ const raw = Math.max(0, Math.min(1, (now - startAt) / duration));
13965
+ onFrame(ease(raw), raw);
13966
+ if (raw < 1) {
13967
+ BrowserAPIs.requestAnimationFrame(step);
13968
+ } else if (onDone) {
13969
+ onDone();
13983
13970
  }
13984
- const graphics = new Graphics(this.barCtx.w);
13985
- const lineGroup = graphics.group({
13986
- class: "apexcharts-bar-goals-groups"
13987
- });
13988
- lineGroup.node.classList.add("apexcharts-element-hidden");
13989
- this.barCtx.w.globals.delayedElements.push({
13990
- el: lineGroup.node
13971
+ };
13972
+ BrowserAPIs.requestAnimationFrame(step);
13973
+ }
13974
+ function tweenSeriesMarkers(w, { elPointsMain, realIndex, speed }) {
13975
+ var _a, _b, _c, _d;
13976
+ if (!(elPointsMain == null ? void 0 : elPointsMain.node)) return false;
13977
+ const sj = seriesJoin(w, realIndex, true);
13978
+ if (!sj) return false;
13979
+ const frame = w.globals.prevStreamFrame;
13980
+ if (!frame) return false;
13981
+ const oldXP = (_a = frame.xPixels) == null ? void 0 : _a[realIndex];
13982
+ const oldYP = (_b = frame.yPixels) == null ? void 0 : _b[realIndex];
13983
+ if (!oldXP || !oldYP) return false;
13984
+ const markers = elPointsMain.node.querySelectorAll(".apexcharts-marker");
13985
+ if (!markers.length) return false;
13986
+ const newXP = ((_c = w.globals.seriesXvalues) == null ? void 0 : _c[realIndex]) || [];
13987
+ const newYP = ((_d = w.globals.seriesYvalues) == null ? void 0 : _d[realIndex]) || [];
13988
+ const ease = morphEasing(w);
13989
+ const duration = Math.max(1, speed || 1);
13990
+ elPointsMain.node.classList.remove("apexcharts-element-hidden");
13991
+ markers.forEach((node) => {
13992
+ var _a2, _b2, _c2, _d2, _e, _f, _g, _h, _i;
13993
+ const j = parseInt(
13994
+ (_b2 = (_a2 = node.getAttribute("j")) != null ? _a2 : node.getAttribute("rel")) != null ? _b2 : "",
13995
+ 10
13996
+ );
13997
+ if (!isFinite(j) || j < 0 || j >= sj.join.toOld.length) return;
13998
+ const oldJ = sj.join.toOld[j];
13999
+ const to = newXP[j] != null && newYP[j] != null ? [newXP[j], newYP[j]] : null;
14000
+ if (oldJ === -1 || !to) {
14001
+ const style = (
14002
+ /** @type {any} */
14003
+ node.style
14004
+ );
14005
+ style.opacity = "0";
14006
+ rafTween(
14007
+ w,
14008
+ duration,
14009
+ ease,
14010
+ (eased) => {
14011
+ style.opacity = String(eased);
14012
+ },
14013
+ () => {
14014
+ style.opacity = "";
14015
+ }
14016
+ );
14017
+ return;
14018
+ }
14019
+ const dx = ((_c2 = oldXP[oldJ]) != null ? _c2 : NaN) - to[0];
14020
+ const dy = ((_d2 = oldYP[oldJ]) != null ? _d2 : NaN) - to[1];
14021
+ if (!isFinite(dx) || !isFinite(dy)) return;
14022
+ const rFrom = (_g = (_f = (_e = frame.rPixels) == null ? void 0 : _e[realIndex]) == null ? void 0 : _f[oldJ]) != null ? _g : NaN;
14023
+ const rTo = parseFloat(
14024
+ (_i = (_h = node.getAttribute("r")) != null ? _h : node.getAttribute("default-marker-size")) != null ? _i : ""
14025
+ );
14026
+ const scales = isFinite(rFrom) && isFinite(rTo) && rTo > 0 && Math.abs(rFrom - rTo) > 0.25;
14027
+ const moves = Math.abs(dx) >= 0.5 || Math.abs(dy) >= 0.5;
14028
+ if (!moves && !scales) return;
14029
+ const apply = (eased) => {
14030
+ const offX = dx * (1 - eased);
14031
+ const offY = dy * (1 - eased);
14032
+ if (scales) {
14033
+ const s = (rFrom + (rTo - rFrom) * eased) / rTo;
14034
+ node.setAttribute(
14035
+ "transform",
14036
+ `translate(${offX + to[0] * (1 - s)}, ${offY + to[1] * (1 - s)}) scale(${s})`
14037
+ );
14038
+ } else {
14039
+ node.setAttribute("transform", `translate(${offX}, ${offY})`);
14040
+ }
14041
+ };
14042
+ apply(0);
14043
+ rafTween(w, duration, ease, apply, () => {
14044
+ node.removeAttribute("transform");
13991
14045
  });
13992
- lineGroup.attr(
13993
- "clip-path",
13994
- `url(#gridRectMarkerMask${this.barCtx.w.globals.cuid})`
14046
+ });
14047
+ return true;
14048
+ }
14049
+ function scaleAbout(node, cx, cy, s) {
14050
+ node.setAttribute("transform", `translate(${cx * (1 - s)}, ${cy * (1 - s)}) scale(${s})`);
14051
+ }
14052
+ function growRisingMarkers(w, { elPointsMain, realIndex, speed }) {
14053
+ if (!(elPointsMain == null ? void 0 : elPointsMain.node) || !lengthTransitionEnabled(w)) return false;
14054
+ if ((w.globals.risingSeries || []).indexOf(realIndex) === -1) return false;
14055
+ const markers = elPointsMain.node.querySelectorAll(".apexcharts-marker");
14056
+ if (!markers.length) return false;
14057
+ const ease = morphEasing(w);
14058
+ elPointsMain.node.classList.remove("apexcharts-element-hidden");
14059
+ markers.forEach((node) => {
14060
+ const b = node.getBBox();
14061
+ const cx = b.x + b.width / 2;
14062
+ const cy = b.y + b.height / 2;
14063
+ scaleAbout(node, cx, cy, 0);
14064
+ rafTween(
14065
+ w,
14066
+ Math.max(1, speed || 1),
14067
+ ease,
14068
+ (eased) => scaleAbout(node, cx, cy, eased),
14069
+ () => node.removeAttribute("transform")
13995
14070
  );
13996
- let line = null;
13997
- if (this.barCtx.isHorizontal) {
13998
- if (Array.isArray(goalX)) {
13999
- goalX.forEach((goal) => {
14000
- if (goal.x >= -1 && goal.x <= graphics.w.layout.gridWidth + 1) {
14001
- const sHeight = typeof goal.attrs.strokeHeight !== "undefined" ? goal.attrs.strokeHeight : barHeight / 2;
14002
- const y = barYPosition + sHeight + barHeight / 2;
14003
- line = graphics.drawLine(
14004
- goal.x,
14005
- y - sHeight * 2,
14006
- goal.x,
14007
- y,
14008
- goal.attrs.strokeColor ? goal.attrs.strokeColor : void 0,
14009
- goal.attrs.strokeDashArray,
14010
- goal.attrs.strokeWidth ? goal.attrs.strokeWidth : 2,
14011
- goal.attrs.strokeLineCap
14012
- );
14013
- lineGroup.add(line);
14014
- if (goal.attrs.label) {
14015
- lineGroup.add(
14016
- this.drawDumbbellLabel(goal.attrs, {
14017
- x: goal.x,
14018
- y: y - sHeight,
14019
- horizontal: true,
14020
- markerSize: goal.attrs.strokeWidth || 0
14021
- })
14022
- );
14023
- }
14024
- }
14025
- });
14026
- }
14027
- } else {
14028
- if (Array.isArray(goalY)) {
14029
- goalY.forEach((goal) => {
14030
- if (goal.y >= -1 && goal.y <= graphics.w.layout.gridHeight + 1) {
14031
- const sWidth = typeof goal.attrs.strokeWidth !== "undefined" ? goal.attrs.strokeWidth : barWidth / 2;
14032
- const x2 = barXPosition + sWidth + barWidth / 2;
14033
- line = graphics.drawLine(
14034
- x2 - sWidth * 2,
14035
- goal.y,
14036
- x2,
14037
- goal.y,
14038
- goal.attrs.strokeColor ? goal.attrs.strokeColor : void 0,
14039
- goal.attrs.strokeDashArray,
14040
- goal.attrs.strokeHeight ? goal.attrs.strokeHeight : 2,
14041
- goal.attrs.strokeLineCap
14042
- );
14043
- lineGroup.add(line);
14044
- if (goal.attrs.label) {
14045
- lineGroup.add(
14046
- this.drawDumbbellLabel(goal.attrs, {
14047
- x: x2 - sWidth,
14048
- y: goal.y,
14049
- horizontal: false,
14050
- markerSize: goal.attrs.strokeHeight || 0
14051
- })
14052
- );
14053
- }
14054
- }
14055
- });
14071
+ });
14072
+ return true;
14073
+ }
14074
+ function shrinkCollapsingMarkers(w, { elPointsMain, realIndex, speed, drawPoint }) {
14075
+ var _a, _b, _c;
14076
+ if (!(elPointsMain == null ? void 0 : elPointsMain.node) || !lengthTransitionEnabled(w)) return false;
14077
+ if ((w.globals.collapsingSeriesIndices || []).indexOf(realIndex) === -1) return false;
14078
+ const frame = w.globals.prevStreamFrame;
14079
+ const xs = (_a = frame == null ? void 0 : frame.xPixels) == null ? void 0 : _a[realIndex];
14080
+ const ys = (_b = frame == null ? void 0 : frame.yPixels) == null ? void 0 : _b[realIndex];
14081
+ if (!Array.isArray(xs) || !Array.isArray(ys)) return false;
14082
+ const rs = ((_c = frame == null ? void 0 : frame.rPixels) == null ? void 0 : _c[realIndex]) || [];
14083
+ const fallbackR = w.globals.markers.size[realIndex] || 0;
14084
+ const ease = morphEasing(w);
14085
+ let drawn = false;
14086
+ for (let j = 0; j < xs.length; j++) {
14087
+ const x2 = xs[j];
14088
+ const y = ys[j];
14089
+ if (x2 == null || y == null || !isFinite(x2) || !isFinite(y)) continue;
14090
+ const r = isFinite(rs[j]) ? rs[j] : fallbackR;
14091
+ if (!(r > 0)) continue;
14092
+ const el = drawPoint(x2, y, r, j);
14093
+ if (!(el == null ? void 0 : el.node)) continue;
14094
+ elPointsMain.add(el);
14095
+ const node = el.node;
14096
+ node.classList.add("apexcharts-marker-exit");
14097
+ const landed = Animations.trackSeriesTween(w, realIndex);
14098
+ rafTween(
14099
+ w,
14100
+ Math.max(1, speed || 1),
14101
+ ease,
14102
+ (eased) => scaleAbout(node, x2, y, 1 - eased),
14103
+ () => {
14104
+ scaleAbout(node, x2, y, 0);
14105
+ landed();
14056
14106
  }
14057
- }
14058
- return lineGroup;
14107
+ );
14108
+ drawn = true;
14059
14109
  }
14060
- /**
14061
- * One dumbbell end label, placed clear of the marker it belongs to.
14062
- *
14063
- * Offset from the marker's EDGE rather than its centre, so growing
14064
- * `markers.size` never walks a label under its own dot. Vertically it is
14065
- * centred on the marker with `dominant-baseline`, which is exact whatever the
14066
- * font metrics are, where a dy fudge factor drifts with font size.
14067
- *
14068
- * @param {Record<string, any>} attrs the goal's attrs, carrying `label`
14069
- * @param {{x: number, y: number, horizontal: boolean, markerSize: number}} pos
14070
- */
14071
- drawDumbbellLabel(attrs, pos) {
14072
- const w = this.w;
14073
- const graphics = new Graphics(w);
14074
- const cnf = w.config.plotOptions.bar.dumbbell.dataLabels;
14075
- const gap = pos.markerSize / 2 + cnf.offset;
14076
- const away = attrs.label.outward;
14077
- return graphics.drawText({
14078
- x: pos.x + (pos.horizontal ? gap * away : 0),
14079
- y: pos.y - (pos.horizontal ? 0 : gap * away),
14080
- text: attrs.label.text,
14081
- textAnchor: pos.horizontal ? away < 0 ? "end" : "start" : "middle",
14082
- dominantBaseline: pos.horizontal ? "central" : away < 0 ? "hanging" : "auto",
14083
- foreColor: attrs.label.color,
14084
- fontSize: cnf.style.fontSize,
14085
- fontFamily: cnf.style.fontFamily,
14086
- fontWeight: cnf.style.fontWeight,
14087
- cssClass: "apexcharts-dumbbell-label"
14088
- });
14110
+ if (drawn) elPointsMain.node.classList.remove("apexcharts-element-hidden");
14111
+ return drawn;
14112
+ }
14113
+ function reconcileSeriesPaths(w, { type, realIndex, pathFromLine, pathFromArea, linePaths, areaPaths }) {
14114
+ var _a, _b;
14115
+ const sj = seriesJoin(w, realIndex);
14116
+ if (!sj) return null;
14117
+ const { join, oldKeys, newKeys } = sj;
14118
+ const frame = w.globals.prevStreamFrame;
14119
+ if (!frame) return null;
14120
+ const oldY = (_a = frame.seriesY) == null ? void 0 : _a[realIndex];
14121
+ const newY = (_b = w.seriesData.series) == null ? void 0 : _b[realIndex];
14122
+ if (oldY.length < 2 || newY.length < 2) return null;
14123
+ if (oldY.some((v) => v === null) || newY.some((v) => v === null)) return null;
14124
+ const entries = buildUnionEntries(join, oldKeys.length);
14125
+ const out = {};
14126
+ if (Array.isArray(linePaths) && linePaths.length === 1 && pathFromLine) {
14127
+ out.line = reconcilePathPair(
14128
+ pathFromLine,
14129
+ linePaths[0],
14130
+ entries,
14131
+ oldKeys.length,
14132
+ newKeys.length,
14133
+ false
14134
+ );
14089
14135
  }
14090
- /** @param {{prevPaths: any, currPaths: any, color: any, realIndex: any, j: any}} opts */
14091
- drawBarShadow({ prevPaths, currPaths, color, realIndex, j }) {
14092
- const w = this.w;
14093
- const { x: prevX2, x1: prevX1, barYPosition: prevY1 } = prevPaths;
14094
- const { x: currX2, x1: currX1, barYPosition: currY1 } = currPaths;
14095
- const prevY2 = prevY1 + currPaths.barHeight;
14096
- const graphics = new Graphics(this.barCtx.w);
14097
- const utils = new Utils();
14098
- const shadowPath = graphics.move(prevX1, prevY2) + graphics.line(prevX2, prevY2) + graphics.line(currX2, currY1) + graphics.line(currX1, currY1) + graphics.line(prevX1, prevY2) + (w.config.plotOptions.bar.borderRadiusApplication === "around" || this.arrBorderRadius[realIndex][j] === "both" ? " Z" : " z");
14099
- return graphics.drawPath({
14100
- d: shadowPath,
14101
- fill: utils.shadeColor(0.5, Utils.rgb2hex(color)),
14136
+ if (type === "area" && Array.isArray(areaPaths) && areaPaths.length === 1 && pathFromArea) {
14137
+ out.area = reconcilePathPair(
14138
+ pathFromArea,
14139
+ areaPaths[0],
14140
+ entries,
14141
+ oldKeys.length,
14142
+ newKeys.length,
14143
+ true
14144
+ );
14145
+ }
14146
+ if (!out.line && !out.area) return null;
14147
+ return out;
14148
+ }
14149
+ function firstMove(d) {
14150
+ const m = /^M\s*([+-]?[\d.eE]+)[\s,]+([+-]?[\d.eE]+)/.exec(d || "");
14151
+ if (!m) return null;
14152
+ const x2 = parseFloat(m[1]);
14153
+ const y = parseFloat(m[2]);
14154
+ return isFinite(x2) && isFinite(y) ? { x: x2, y } : null;
14155
+ }
14156
+ function renderBarExitGhosts({
14157
+ w,
14158
+ elSeries,
14159
+ record,
14160
+ newKeys,
14161
+ isHorizontal,
14162
+ speed
14163
+ }) {
14164
+ var _a;
14165
+ if (!lengthTransitionEnabled(w)) return;
14166
+ if (!record || !Array.isArray(record.paths) || !(elSeries == null ? void 0 : elSeries.node)) return;
14167
+ const newKeySet = new Set(newKeys);
14168
+ const exits = record.paths.filter(
14169
+ (p) => p && p.d && p.key != null && !newKeySet.has(p.key)
14170
+ );
14171
+ if (!exits.length) return;
14172
+ const graphics = new Graphics(w);
14173
+ const fallbackFill = (_a = w.globals.colors) == null ? void 0 : _a[parseInt(String(record.realIndex), 10)];
14174
+ exits.forEach((p) => {
14175
+ let fill = p.fill || fallbackFill || "#c8c8c8";
14176
+ if (String(fill).indexOf("url(") === 0) fill = fallbackFill || "#c8c8c8";
14177
+ const ghost = graphics.drawPath({
14178
+ d: p.d,
14102
14179
  stroke: "none",
14103
14180
  strokeWidth: 0,
14104
- fillOpacity: 1,
14105
- classes: "apexcharts-bar-shadow apexcharts-decoration-element"
14106
- });
14107
- }
14108
- /** @param {{i: any, j: any}} opts */
14109
- getZeroValueEncounters({ i, j }) {
14110
- var _a;
14111
- const w = this.w;
14112
- let nonZeroColumns = 0;
14113
- let zeroEncounters = 0;
14114
- const seriesIndices = w.config.plotOptions.bar.horizontal ? w.seriesData.series.map((_, _i) => _i) : ((_a = w.globals.columnSeries) == null ? void 0 : _a.i.map((_i) => _i)) || [];
14115
- seriesIndices.forEach((_si) => {
14116
- const val = w.globals.seriesPercent[_si][j];
14117
- if (val) {
14118
- nonZeroColumns++;
14181
+ fill,
14182
+ fillOpacity: 1,
14183
+ classes: "apexcharts-bar-ghost"
14184
+ });
14185
+ const node = ghost.node;
14186
+ node.setAttribute("pointer-events", "none");
14187
+ ghost.attr(
14188
+ "clip-path",
14189
+ `url(#gridRectBarMask${w.globals.cuid})`
14190
+ );
14191
+ elSeries.node.insertBefore(node, elSeries.node.firstChild);
14192
+ const start = firstMove(p.d);
14193
+ let origin = isHorizontal ? "left center" : "center bottom";
14194
+ try {
14195
+ const bb = node.getBBox();
14196
+ if (start && bb) {
14197
+ if (isHorizontal) {
14198
+ origin = Math.abs(start.x - bb.x) <= Math.abs(start.x - (bb.x + bb.width)) ? "left center" : "right center";
14199
+ } else {
14200
+ origin = Math.abs(start.y - (bb.y + bb.height)) <= Math.abs(start.y - bb.y) ? "center bottom" : "center top";
14201
+ }
14119
14202
  }
14120
- if (_si < i && val === 0) {
14121
- zeroEncounters++;
14203
+ } catch (_) {
14204
+ }
14205
+ const style = node.style;
14206
+ style.transformBox = "fill-box";
14207
+ style.transformOrigin = origin;
14208
+ node.setAttribute("data:ghostKey", `${record.realIndex}::${p.key}`);
14209
+ try {
14210
+ const bb = node.getBBox();
14211
+ const edge = isHorizontal ? origin.startsWith("left") ? bb.x : bb.x + bb.width : origin.endsWith("bottom") ? bb.y + bb.height : bb.y;
14212
+ if (isFinite(edge)) node.setAttribute("data:ghostEdge", String(edge));
14213
+ } catch (_) {
14214
+ }
14215
+ const duration = Math.max(1, speed || 1);
14216
+ const startAt = performance.now();
14217
+ const step = (now) => {
14218
+ if (w.globals.isDestroyed || !node.parentNode) return;
14219
+ const t = Math.max(0, Math.min(1, (now - startAt) / duration));
14220
+ const eased = 1 - Math.pow(1 - t, 3);
14221
+ const scale = 1 - eased;
14222
+ style.transform = isHorizontal ? `scaleX(${scale})` : `scaleY(${scale})`;
14223
+ style.opacity = String(1 - eased);
14224
+ if (t < 1) {
14225
+ BrowserAPIs.requestAnimationFrame(step);
14226
+ } else {
14227
+ node.parentNode.removeChild(node);
14122
14228
  }
14123
- });
14124
- return {
14125
- nonZeroColumns,
14126
- zeroEncounters
14127
14229
  };
14128
- }
14129
- /**
14130
- * Index of the series group `seriesIndex` belongs to within
14131
- * `w.labelData.seriesGroups`, or -1 when the chart has no groups.
14132
- *
14133
- * Unlike `getGroupIndex` this is a pure lookup: it never appends to
14134
- * `columnGroupIndices`, so it is safe to call from positioning/label code
14135
- * that must not perturb the draw order bookkeeping.
14136
- * @param {number} seriesIndex
14137
- * @returns {number}
14138
- */
14139
- getSeriesGroupIndex(seriesIndex) {
14140
- var _a;
14141
- return (_a = this.w.labelData.seriesGroupIndex[seriesIndex]) != null ? _a : -1;
14142
- }
14143
- /**
14144
- * @param {number} seriesIndex
14145
- */
14146
- getGroupIndex(seriesIndex) {
14147
- const groupIndex = this.getSeriesGroupIndex(seriesIndex);
14148
- const cGI = this.barCtx.columnGroupIndices;
14149
- let columnGroupIndex = cGI.indexOf(groupIndex);
14150
- if (columnGroupIndex < 0) {
14151
- cGI.push(groupIndex);
14152
- columnGroupIndex = cGI.length - 1;
14153
- }
14154
- return { groupIndex, columnGroupIndex };
14155
- }
14156
- };
14230
+ BrowserAPIs.requestAnimationFrame(step);
14231
+ });
14232
+ }
14157
14233
  class Bar {
14158
14234
  /**
14159
14235
  * @param {import('../types/internal').ChartStateW} w
@@ -14220,15 +14296,17 @@ class Bar {
14220
14296
  /**
14221
14297
  * Point the per-series axis state at this series' y axis. Every bar-family
14222
14298
  * renderer calls it before initialPositions, which reads the baseline by
14223
- * this.translationsIndex.
14299
+ * this.translationsIndex and flips it for a reversed axis.
14224
14300
  * @param {number} realIndex
14225
14301
  * @return {number} translationsIndex
14226
14302
  */
14227
14303
  setSeriesAxis(realIndex) {
14304
+ var _a;
14228
14305
  if (this.yRatio.length > 1) {
14229
14306
  this.yaxisIndex = this.w.globals.seriesYAxisReverseMap[realIndex];
14230
14307
  this.translationsIndex = realIndex;
14231
14308
  }
14309
+ this.isReversed = (_a = this.w.config.yaxis[this.yaxisIndex]) == null ? void 0 : _a.reversed;
14232
14310
  return this.translationsIndex;
14233
14311
  }
14234
14312
  /** primary draw method which is called on bar object
@@ -14245,7 +14323,7 @@ class Bar {
14245
14323
  series = coreUtils.getLogSeries(series);
14246
14324
  this.series = series;
14247
14325
  this.yRatio = coreUtils.getLogYRatios(this.yRatio);
14248
- this.barHelpers.initVariables(series);
14326
+ this.barHelpers.initVariables(series, seriesIndex);
14249
14327
  const ret = graphics.group({
14250
14328
  class: "apexcharts-bar-series apexcharts-plot-series"
14251
14329
  });
@@ -14277,7 +14355,6 @@ class Bar {
14277
14355
  this.visibleI = this.visibleI + 1;
14278
14356
  }
14279
14357
  const translationsIndex = this.setSeriesAxis(realIndex);
14280
- this.isReversed = w.config.yaxis[this.yaxisIndex] && w.config.yaxis[this.yaxisIndex].reversed;
14281
14358
  if (this.isPyramid) {
14282
14359
  this.pyramidLayout = this.barHelpers.computePyramidLayout(series[i]);
14283
14360
  }
@@ -14355,7 +14432,9 @@ class Bar {
14355
14432
  elSeries
14356
14433
  };
14357
14434
  if (this.isHorizontal) {
14358
- paths = this.drawBarPaths(__spreadProps(__spreadValues({}, pathsParams), {
14435
+ paths = this.drawBarPaths(__spreadProps(__spreadValues(__spreadValues({}, pathsParams), this.barHelpers.rows && {
14436
+ y: initY + this.barHelpers.barRow(realIndex, j) * yDivision
14437
+ }), {
14359
14438
  barHeight,
14360
14439
  zeroW,
14361
14440
  yDivision
@@ -14437,6 +14516,7 @@ class Bar {
14437
14516
  series,
14438
14517
  barHeight: Math.abs(paths.barHeight ? paths.barHeight : barHeight),
14439
14518
  barWidth: Math.abs(paths.barWidth ? paths.barWidth : barWidth),
14519
+ barXPosition: paths.barXPosition,
14440
14520
  elDataLabelsWrap,
14441
14521
  elGoalsMarkers,
14442
14522
  elBarShadows,
@@ -14447,15 +14527,11 @@ class Bar {
14447
14527
  w.globals.seriesXvalues[realIndex] = xArrj;
14448
14528
  w.globals.seriesYvalues[realIndex] = yArrj;
14449
14529
  if (w.globals.previousPaths.length > 0) {
14450
- const newKeys = [];
14451
- for (let j = 0; j < series[i].length; j++) {
14452
- newKeys.push(datumKey(w, realIndex, j));
14453
- }
14454
14530
  renderBarExitGhosts({
14455
14531
  w,
14456
14532
  elSeries,
14457
14533
  record: this._prevRecord(realIndex),
14458
- newKeys,
14534
+ newKeys: this._keys(realIndex),
14459
14535
  isHorizontal: this.isHorizontal,
14460
14536
  speed: w.config.chart.animations.dynamicAnimation.speed
14461
14537
  });
@@ -14464,7 +14540,7 @@ class Bar {
14464
14540
  }
14465
14541
  return ret;
14466
14542
  }
14467
- /** @param {{ hl?: any, realIndex?: any, pathFill?: any, lineFill?: any, j?: any, i?: any, columnGroupIndex?: any, pathFrom?: any, pathTo?: any, strokeWidth?: any, elSeries?: any, x?: any, y?: any, y1?: any, y2?: any, series?: any, barHeight?: any, barWidth?: any, barXPosition?: any, barYPosition?: any, elDataLabelsWrap?: any, elGoalsMarkers?: any, elBarShadows?: any, visibleSeries?: any, type?: any, classes?: any, fadeReveal?: boolean }} opts */
14543
+ /** @param {{ hl?: any, realIndex?: any, pathFill?: any, lineFill?: any, j?: any, i?: any, columnGroupIndex?: any, pathFrom?: any, pathTo?: any, strokeWidth?: any, elSeries?: any, x?: any, y?: any, y1?: any, y2?: any, series?: any, barHeight?: any, barWidth?: any, barXPosition?: any, barYPosition?: any, elDataLabelsWrap?: any, elGoalsMarkers?: any, elBarShadows?: any, visibleSeries?: any, type?: any, classes?: any, fadeReveal?: boolean, noLabel?: boolean }} opts */
14468
14544
  renderSeries({
14469
14545
  hl,
14470
14546
  realIndex,
@@ -14496,7 +14572,9 @@ class Bar {
14496
14572
  visibleSeries,
14497
14573
  type,
14498
14574
  classes,
14499
- fadeReveal = false
14575
+ fadeReveal = false,
14576
+ noLabel
14577
+ // a datum's extra paths (box halves, box lane) label nothing
14500
14578
  }) {
14501
14579
  var _a, _b, _c, _d, _e, _f, _g;
14502
14580
  const w = this.w;
@@ -14570,7 +14648,8 @@ class Bar {
14570
14648
  barXPosition,
14571
14649
  barYPosition,
14572
14650
  visibleSeries,
14573
- hl: hl == null ? void 0 : hl.label
14651
+ hl: hl == null ? void 0 : hl.label,
14652
+ noLabel
14574
14653
  })
14575
14654
  );
14576
14655
  if (delayMs > 0) {
@@ -14586,19 +14665,18 @@ class Bar {
14586
14665
  }
14587
14666
  let leaving = false;
14588
14667
  if (!w.globals.isBarHorizontal) {
14589
- if (dataLabelsObj.dataLabelsPos.dataLabelsX + Math.max(barWidth, w.globals.barPadForNumericAxis) < 0 || dataLabelsObj.dataLabelsPos.dataLabelsX - Math.max(barWidth, w.globals.barPadForNumericAxis) > w.layout.gridWidth) {
14668
+ const cx = barXPosition === void 0 ? dataLabelsObj.dataLabelsPos.dataLabelsX : barXPosition + barWidth / 2;
14669
+ const pad = Math.max(barWidth, w.globals.barPadForNumericAxis);
14670
+ if (cx + pad < 0 || cx - pad > w.layout.gridWidth) {
14590
14671
  if (this._wasOnScreen(realIndex, j)) leaving = true;
14591
14672
  else skipDrawing = true;
14592
14673
  }
14593
14674
  }
14594
- if (
14595
- /** @type {Record<string,any>} */
14596
- w.config.series[i].data[j] && /** @type {Record<string,any>} */
14597
- w.config.series[i].data[j].strokeColor
14598
- ) {
14599
- lineFill = /** @type {Record<string,any>} */
14600
- w.config.series[i].data[j].strokeColor;
14601
- }
14675
+ const datum = (
14676
+ /** @type {any} */
14677
+ w.config.series[realIndex].data[j]
14678
+ );
14679
+ if (datum && datum.strokeColor) lineFill = datum.strokeColor;
14602
14680
  const fill = pathFill;
14603
14681
  if (this.isNullValue && w.globals.collapsingSeriesIndices.indexOf(realIndex) === -1) {
14604
14682
  pathFill = "none";
@@ -14621,7 +14699,7 @@ class Bar {
14621
14699
  pathTo,
14622
14700
  stroke: lineFill,
14623
14701
  strokeWidth,
14624
- strokeLineCap: w.config.stroke.lineCap,
14702
+ strokeLinecap: w.config.stroke.lineCap,
14625
14703
  fill: pathFill,
14626
14704
  pathToInterp,
14627
14705
  animationDelay: delay,
@@ -14673,12 +14751,12 @@ class Bar {
14673
14751
  cy: dataLabelsObj.dataLabelsPos.bcy,
14674
14752
  cx: dataLabelsObj.dataLabelsPos.bcx,
14675
14753
  j,
14676
- val: w.seriesData.series[i][j],
14754
+ val: w.seriesData.series[realIndex][j],
14677
14755
  barHeight,
14678
14756
  barWidth,
14679
14757
  // Datum identity for the next update's keyed join (see
14680
14758
  // LengthTransition): survivors match by key, not array position.
14681
- "data:pathKey": datumKey(w, realIndex, j)
14759
+ "data:pathKey": this._keys(realIndex)[j]
14682
14760
  });
14683
14761
  hl == null ? void 0 : hl.paint(renderedPath, {
14684
14762
  delay,
@@ -14754,7 +14832,10 @@ class Bar {
14754
14832
  const j = indexes.j;
14755
14833
  let barYPosition;
14756
14834
  if (w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
14757
- const { nonZeroColumns, zeroEncounters } = this.barHelpers.getZeroValueEncounters({ i, j });
14835
+ const { nonZeroColumns, zeroEncounters } = this.barHelpers.getZeroValueEncounters({
14836
+ i: indexes.realIndex,
14837
+ j
14838
+ });
14758
14839
  if (nonZeroColumns > 0) {
14759
14840
  barHeight = this.seriesLen * barHeight / nonZeroColumns;
14760
14841
  }
@@ -14893,7 +14974,7 @@ class Bar {
14893
14974
  barXPosition = xForNumericX.barXPosition;
14894
14975
  } else {
14895
14976
  if (w.config.plotOptions.bar.hideZeroBarsWhenGrouped) {
14896
- const { nonZeroColumns, zeroEncounters } = this.barHelpers.getZeroValueEncounters({ i, j });
14977
+ const { nonZeroColumns, zeroEncounters } = this.barHelpers.getZeroValueEncounters({ i: realIndex, j });
14897
14978
  if (nonZeroColumns > 0) {
14898
14979
  barWidth = this.seriesLen * barWidth / nonZeroColumns;
14899
14980
  }
@@ -14957,15 +15038,16 @@ class Bar {
14957
15038
  /** @param {{x: any, barWidth: any, realIndex: any, j: any}} opts */
14958
15039
  getBarXForNumericXAxis({ x: x2, barWidth, realIndex, j }) {
14959
15040
  const w = this.w;
15041
+ const overlay = isHistogramOverlay(w);
14960
15042
  let sxI = realIndex;
14961
15043
  if (!w.seriesData.seriesX[realIndex].length) {
14962
15044
  sxI = w.globals.maxValsInArrayIndex;
14963
15045
  }
14964
15046
  if (Utils.isNumber(w.seriesData.seriesX[sxI][j])) {
14965
- x2 = AxisMapping.dataXToPx(w, w.seriesData.seriesX[sxI][j]) - barWidth * this.seriesLen / 2;
15047
+ x2 = AxisMapping.dataXToPx(w, w.seriesData.seriesX[sxI][j]) - barWidth * (overlay ? 1 : this.seriesLen) / 2;
14966
15048
  }
14967
15049
  return {
14968
- barXPosition: x2 + (isHistogramOverlay(w) ? 0 : barWidth * this.visibleI),
15050
+ barXPosition: x2 + (overlay ? 0 : barWidth * this.visibleI),
14969
15051
  x: x2
14970
15052
  };
14971
15053
  }
@@ -14986,7 +15068,20 @@ class Bar {
14986
15068
  _wasOnScreen(realIndex, j) {
14987
15069
  if (!lengthTransitionEnabled(this.w)) return false;
14988
15070
  const keyed = this._prevKeyedPaths(realIndex);
14989
- return !!keyed && keyed.has(datumKey(this.w, realIndex, j));
15071
+ return !!keyed && keyed.has(this._keys(realIndex)[j]);
15072
+ }
15073
+ /**
15074
+ * This render's datum keys for a series (see seriesKeys), as stamped on
15075
+ * each bar and looked up in the previous render's.
15076
+ * @param {number} realIndex
15077
+ * @returns {string[]}
15078
+ */
15079
+ _keys(realIndex) {
15080
+ const c = (
15081
+ /** @type {any} */
15082
+ this._keyCache || (this._keyCache = {})
15083
+ );
15084
+ return c[realIndex] || (c[realIndex] = seriesKeys(this.w, realIndex));
14990
15085
  }
14991
15086
  /**
14992
15087
  * The captured previous-render record for a series (last match wins, same
@@ -15042,7 +15137,7 @@ class Bar {
15042
15137
  * @returns {boolean}
15043
15138
  */
15044
15139
  isLengthTransition(realIndex) {
15045
- var _a, _b;
15140
+ var _a, _b, _c, _d, _e, _f;
15046
15141
  if (!this._ltCache) this._ltCache = {};
15047
15142
  if (this._ltCache[realIndex] !== void 0) return this._ltCache[realIndex];
15048
15143
  const w = this.w;
@@ -15050,20 +15145,14 @@ class Bar {
15050
15145
  if (lengthTransitionEnabled(w) && w.globals.previousPaths.length > 0) {
15051
15146
  const record = this._prevRecord(realIndex);
15052
15147
  const dataLen = (_b = (_a = w.seriesData.series[realIndex]) == null ? void 0 : _a.length) != null ? _b : 0;
15148
+ const keyed = record && this._prevKeyedPaths(realIndex);
15053
15149
  if (!record) {
15054
15150
  result = dataLen > 0;
15055
- } else if (record.paths.length !== dataLen) {
15056
- result = true;
15151
+ } else if (keyed) {
15152
+ const now = new Set(this._keys(realIndex));
15153
+ result = ((_f = (_e = (_d = (_c = w.globals.prevStreamFrame) == null ? void 0 : _c.seriesY) == null ? void 0 : _d[realIndex]) == null ? void 0 : _e.length) != null ? _f : dataLen) !== dataLen || [...keyed.keys()].some((k2) => !now.has(k2));
15057
15154
  } else {
15058
- const keyed = this._prevKeyedPaths(realIndex);
15059
- if (keyed) {
15060
- for (let j = 0; j < dataLen; j++) {
15061
- if (!keyed.has(datumKey(w, realIndex, j))) {
15062
- result = true;
15063
- break;
15064
- }
15065
- }
15066
- }
15155
+ result = record.paths.length !== dataLen;
15067
15156
  }
15068
15157
  }
15069
15158
  this._ltCache[realIndex] = result;
@@ -15123,7 +15212,7 @@ class Bar {
15123
15212
  let isNewDatum = false;
15124
15213
  const keyed = this._prevKeyedPaths(realIndex);
15125
15214
  if (keyed) {
15126
- const prev = keyed.get(datumKey(w, realIndex, j));
15215
+ const prev = keyed.get(this._keys(realIndex)[j]);
15127
15216
  if (prev) {
15128
15217
  oldD = prev.d;
15129
15218
  } else {
@@ -15266,11 +15355,10 @@ class Bar {
15266
15355
  * @returns {boolean | null} null when there is no previous record to consult
15267
15356
  */
15268
15357
  getPreviousFlip(realIndex, j) {
15269
- const w = this.w;
15270
15358
  const record = this._prevRecord(realIndex);
15271
15359
  if (!record) return null;
15272
15360
  const keyed = this._prevKeyedPaths(realIndex);
15273
- const prev = keyed ? keyed.get(datumKey(w, realIndex, j)) : record.paths[j];
15361
+ const prev = keyed ? keyed.get(this._keys(realIndex)[j]) : record.paths[j];
15274
15362
  return prev ? !!prev.flip : null;
15275
15363
  }
15276
15364
  /**
@@ -15297,7 +15385,7 @@ class BarStacked extends Bar {
15297
15385
  const coreUtils = new CoreUtils(this.w);
15298
15386
  series = coreUtils.getLogSeries(series);
15299
15387
  this.yRatio = coreUtils.getLogYRatios(this.yRatio);
15300
- this.barHelpers.initVariables(series);
15388
+ this.barHelpers.initVariables(series, seriesIndex);
15301
15389
  if (w.config.chart.stackType === "100%") {
15302
15390
  series = w.globals.comboCharts ? (
15303
15391
  /** @type {any} */
@@ -15328,7 +15416,6 @@ class BarStacked extends Bar {
15328
15416
  const xArrValues = [];
15329
15417
  const yArrValues = [];
15330
15418
  const translationsIndex = this.setSeriesAxis(realIndex);
15331
- this.isReversed = w.config.yaxis[this.yaxisIndex] && w.config.yaxis[this.yaxisIndex].reversed;
15332
15419
  let elSeries = this.graphics.group({
15333
15420
  class: `apexcharts-series`,
15334
15421
  seriesName: Utils.escapeString(w.seriesData.seriesNames[realIndex]),
@@ -15398,7 +15485,9 @@ class BarStacked extends Bar {
15398
15485
  null
15399
15486
  );
15400
15487
  if (this.isHorizontal) {
15401
- paths = this.drawStackedBarPaths(__spreadProps(__spreadValues({}, commonPathOpts), {
15488
+ paths = this.drawStackedBarPaths(__spreadProps(__spreadValues(__spreadValues({}, commonPathOpts), this.barHelpers.rows && {
15489
+ y: initPositions.y + this.barHelpers.barRow(realIndex, j) * yDivision
15490
+ }), {
15402
15491
  zeroW,
15403
15492
  barHeight,
15404
15493
  yDivision
@@ -15472,6 +15561,7 @@ class BarStacked extends Bar {
15472
15561
  series,
15473
15562
  barHeight,
15474
15563
  barWidth,
15564
+ barXPosition: paths.barXPosition,
15475
15565
  elDataLabelsWrap,
15476
15566
  elGoalsMarkers,
15477
15567
  type: "bar",
@@ -15489,7 +15579,7 @@ class BarStacked extends Bar {
15489
15579
  this.groupCtx.prevXVal.push(this.groupCtx.xArrjVal);
15490
15580
  ret.add(elSeries);
15491
15581
  }
15492
- if (heldMirrors) this.settleHeldMirrors();
15582
+ if (heldMirrors) this.settleHeldMirrors(ret);
15493
15583
  return ret;
15494
15584
  }
15495
15585
  /**
@@ -15510,15 +15600,21 @@ class BarStacked extends Bar {
15510
15600
  * 'bottom' → 'top', where the endpoint really is rounded at the other end;
15511
15601
  * everywhere else the mirror is an exact identity on the settled shape, so
15512
15602
  * removing it changes nothing on screen.
15603
+ *
15604
+ * The marks are collected now, not when the timer fires: a query then also
15605
+ * stripped the mirrors a LATER update was still holding mid-tween.
15606
+ * @param {any} [ret] this draw's series group (default: the whole chart)
15513
15607
  */
15514
- settleHeldMirrors() {
15608
+ settleHeldMirrors(ret) {
15515
15609
  const w = this.w;
15516
15610
  if (!Environment.isBrowser()) return;
15517
15611
  const anim = w.config.chart.animations;
15518
15612
  const hold = (anim.dynamicAnimation.speed || 0) + (anim.speed || 0) + 100;
15613
+ const held = (ret ? ret.node : w.dom.baseEl).querySelectorAll(
15614
+ ".apexcharts-flip-held"
15615
+ );
15519
15616
  setTimeout(() => {
15520
- if (w.globals.isDestroyed || !Utils.elementExists(w.dom.baseEl)) return;
15521
- w.dom.baseEl.querySelectorAll(".apexcharts-flip-held").forEach((el) => {
15617
+ held.forEach((el) => {
15522
15618
  el.classList.remove(
15523
15619
  "apexcharts-flip-held",
15524
15620
  "apexcharts-flip-y",
@@ -15594,7 +15690,7 @@ class BarStacked extends Bar {
15594
15690
  yDivision,
15595
15691
  elSeries
15596
15692
  }) {
15597
- var _a, _b, _c, _d, _e;
15693
+ var _a, _b;
15598
15694
  const w = this.w;
15599
15695
  const barYPosition = y + columnGroupIndex * barHeight;
15600
15696
  let barXPosition;
@@ -15602,36 +15698,21 @@ class BarStacked extends Bar {
15602
15698
  const j = indexes.j;
15603
15699
  const realIndex = indexes.realIndex;
15604
15700
  const translationsIndex = indexes.translationsIndex;
15605
- let prevBarW = 0;
15606
- for (let k2 = 0; k2 < this.groupCtx.prevXF.length; k2++) {
15607
- prevBarW = prevBarW + this.groupCtx.prevXF[k2][j];
15608
- }
15609
- const gsi = this.groupCtx.prevX.length;
15610
- if (gsi > 0) {
15611
- let bXP = zeroW;
15612
- if (this.groupCtx.prevXVal[gsi - 1][j] < 0) {
15613
- bXP = /** @type {any} */
15614
- ((_a = this.series[i]) == null ? void 0 : _a[j]) >= 0 ? this.groupCtx.prevX[gsi - 1][j] + prevBarW - (this.isReversed ? prevBarW : 0) * 2 : this.groupCtx.prevX[gsi - 1][j];
15615
- } else if (this.groupCtx.prevXVal[gsi - 1][j] >= 0) {
15616
- bXP = /** @type {any} */
15617
- ((_b = this.series[i]) == null ? void 0 : _b[j]) >= 0 ? this.groupCtx.prevX[gsi - 1][j] : this.groupCtx.prevX[gsi - 1][j] - prevBarW + (this.isReversed ? prevBarW : 0) * 2;
15618
- }
15619
- barXPosition = bXP;
15620
- } else {
15621
- barXPosition = zeroW;
15622
- }
15623
- if (
15701
+ const v = (
15624
15702
  /** @type {any} */
15625
- ((_c = this.series[i]) == null ? void 0 : _c[j]) === null
15626
- ) {
15627
- x2 = barXPosition;
15703
+ (_b = (_a = this.series[i]) == null ? void 0 : _a[j]) != null ? _b : null
15704
+ );
15705
+ const g = this.groupCtx;
15706
+ const key = w.axisFlags.isXNumeric ? w.seriesData.seriesX[realIndex][j] : j;
15707
+ const top = g.tops.get(key);
15708
+ if (top) {
15709
+ const [prevX, prevVal, prevBarW] = top;
15710
+ const flip = (this.isReversed ? prevBarW : 0) * 2;
15711
+ barXPosition = prevVal < 0 ? v >= 0 ? prevX + prevBarW - flip : prevX : v >= 0 ? prevX : prevX - prevBarW + flip;
15628
15712
  } else {
15629
- x2 = barXPosition + /** @type {any} */
15630
- ((_d = this.series[i]) == null ? void 0 : _d[j]) / this.invertedYRatio - (this.isReversed ? (
15631
- /** @type {any} */
15632
- ((_e = this.series[i]) == null ? void 0 : _e[j]) / this.invertedYRatio
15633
- ) : 0) * 2;
15713
+ barXPosition = zeroW;
15634
15714
  }
15715
+ x2 = barXPosition + v / this.invertedYRatio * (this.isReversed ? -1 : 1);
15635
15716
  const paths = this.barHelpers.getBarpaths({
15636
15717
  barYPosition,
15637
15718
  barHeight,
@@ -15645,6 +15726,7 @@ class BarStacked extends Bar {
15645
15726
  j,
15646
15727
  w
15647
15728
  });
15729
+ this._setTop(key, top, g.xArrj[j], g.xArrjVal[j], g.xArrjF[j], realIndex, j);
15648
15730
  this.barHelpers.barBackground({
15649
15731
  j,
15650
15732
  i,
@@ -15682,13 +15764,17 @@ class BarStacked extends Bar {
15682
15764
  columnGroupIndex,
15683
15765
  elSeries
15684
15766
  }) {
15685
- var _a, _b, _c, _d, _e, _f;
15767
+ var _a, _b, _c;
15686
15768
  const w = this.w;
15687
15769
  const i = indexes.i;
15688
15770
  const j = indexes.j;
15689
15771
  const bc = indexes.bc;
15690
15772
  const realIndex = indexes.realIndex;
15691
15773
  const translationsIndex = indexes.translationsIndex;
15774
+ const v = (
15775
+ /** @type {any} */
15776
+ (_b = (_a = this.series[i]) == null ? void 0 : _a[j]) != null ? _b : null
15777
+ );
15692
15778
  if (w.axisFlags.isXNumeric) {
15693
15779
  let seriesVal = w.seriesData.seriesX[realIndex][j];
15694
15780
  if (!seriesVal) seriesVal = 0;
@@ -15703,11 +15789,9 @@ class BarStacked extends Bar {
15703
15789
  const [prevYValue, prevVal, prevBarH] = top;
15704
15790
  let bYP;
15705
15791
  if (prevVal < 0) {
15706
- bYP = /** @type {any} */
15707
- ((_a = this.series[i]) == null ? void 0 : _a[j]) >= 0 ? prevYValue - prevBarH + (this.isReversed ? prevBarH : 0) * 2 : prevYValue;
15792
+ bYP = v >= 0 ? prevYValue - prevBarH + (this.isReversed ? prevBarH : 0) * 2 : prevYValue;
15708
15793
  } else if (prevVal >= 0) {
15709
- bYP = /** @type {any} */
15710
- ((_b = this.series[i]) == null ? void 0 : _b[j]) >= 0 ? prevYValue : prevYValue + prevBarH - (this.isReversed ? prevBarH : 0) * 2;
15794
+ bYP = v >= 0 ? prevYValue : prevYValue + prevBarH - (this.isReversed ? prevBarH : 0) * 2;
15711
15795
  }
15712
15796
  if (typeof bYP === "undefined") bYP = w.layout.gridHeight;
15713
15797
  if (((_c = g.prevYF[0]) == null ? void 0 : _c.every((val) => val === 0)) && g.prevYF.slice(1).every(
@@ -15720,25 +15804,16 @@ class BarStacked extends Bar {
15720
15804
  } else {
15721
15805
  barYPosition = zeroH;
15722
15806
  }
15723
- if (
15724
- /** @type {any} */
15725
- (_d = this.series[i]) == null ? void 0 : _d[j]
15726
- ) {
15727
- y = barYPosition - /** @type {any} */
15728
- ((_e = this.series[i]) == null ? void 0 : _e[j]) / this.yRatio[translationsIndex] + (this.isReversed ? (
15729
- /** @type {any} */
15730
- ((_f = this.series[i]) == null ? void 0 : _f[j]) / this.yRatio[translationsIndex]
15731
- ) : 0) * 2;
15732
- } else {
15733
- y = barYPosition;
15734
- }
15807
+ y = barYPosition - v / this.yRatio[translationsIndex] * (this.isReversed ? -1 : 1);
15735
15808
  const paths = this.barHelpers.getColumnPaths({
15736
15809
  barXPosition,
15737
15810
  barWidth,
15738
15811
  y1: barYPosition,
15739
15812
  y2: y,
15740
15813
  yRatio: this.yRatio[translationsIndex],
15741
- strokeWidth: this.strokeWidth,
15814
+ // the series' width even for an empty segment, so a hidden layer keeps
15815
+ // its place, but no inset at all when no stroke is drawn
15816
+ strokeWidth: w.config.stroke.show ? this.strokeWidth : 0,
15742
15817
  isReversed: this.isReversed,
15743
15818
  series: this.series,
15744
15819
  realIndex: indexes.realIndex,
@@ -15746,17 +15821,7 @@ class BarStacked extends Bar {
15746
15821
  j,
15747
15822
  w
15748
15823
  });
15749
- const t = g.yArrj[j];
15750
- if (!isNaN(t)) {
15751
- g.tops.set(key, [
15752
- t,
15753
- g.yArrjVal[j],
15754
- (top ? top[2] : 0) + g.yArrjF[j],
15755
- (top ? top[3] : 0) + (w.seriesData.series[realIndex][j] || 0),
15756
- top ? Math.min(top[0], top[4]) : 1 / 0,
15757
- top ? Math.max(top[0], top[5]) : -1 / 0
15758
- ]);
15759
- }
15824
+ this._setTop(key, top, g.yArrj[j], g.yArrjVal[j], g.yArrjF[j], realIndex, j);
15760
15825
  this.barHelpers.barBackground({
15761
15826
  bc,
15762
15827
  j,
@@ -15775,17 +15840,47 @@ class BarStacked extends Bar {
15775
15840
  zeroH,
15776
15841
  realIndex,
15777
15842
  j,
15778
- 0
15843
+ translationsIndex
15779
15844
  ),
15780
15845
  barXPosition,
15781
15846
  x: w.axisFlags.isXNumeric ? x2 : x2 + xDivision,
15782
15847
  y
15783
15848
  };
15784
15849
  }
15850
+ /**
15851
+ * Record the segment just drawn as the top of its stack. Per key it holds
15852
+ * the top and value of the last segment drawn there, the summed lengths and
15853
+ * raw values of every segment so far (the total label's value), and the
15854
+ * extreme tops below that segment (the total label's position).
15855
+ * @param {any} key @param {any} top @param {number} t @param {any} val
15856
+ * @param {number} len @param {number} realIndex @param {number} j
15857
+ */
15858
+ _setTop(key, top, t, val, len, realIndex, j) {
15859
+ if (isNaN(t)) return;
15860
+ this.groupCtx.tops.set(key, [
15861
+ t,
15862
+ val,
15863
+ (top ? top[2] : 0) + len,
15864
+ (top ? top[3] : 0) + (this.w.seriesData.series[realIndex][j] || 0),
15865
+ top ? Math.min(top[0], top[4]) : 1 / 0,
15866
+ top ? Math.max(top[0], top[5]) : -1 / 0
15867
+ ]);
15868
+ }
15869
+ }
15870
+ function jitterExtent(pool, w) {
15871
+ let lo = Infinity;
15872
+ let hi = -Infinity;
15873
+ pool.slice(0, w.seriesData.series.length).flat(2).forEach((v) => {
15874
+ if (v === +v) {
15875
+ if (v < lo) lo = v;
15876
+ if (v > hi) hi = v;
15877
+ }
15878
+ });
15879
+ return [lo, hi];
15785
15880
  }
15786
15881
  function buildJitterGroups({
15787
- w,
15788
15882
  points,
15883
+ extent,
15789
15884
  seedA,
15790
15885
  seedB,
15791
15886
  center,
@@ -15796,6 +15891,7 @@ function buildJitterGroups({
15796
15891
  clampAt,
15797
15892
  sideSign
15798
15893
  }) {
15894
+ var _a, _b;
15799
15895
  const opts = options;
15800
15896
  if (!opts || opts.show === false) return [];
15801
15897
  if (!points || !points.length) return [];
@@ -15809,8 +15905,8 @@ function buildJitterGroups({
15809
15905
  const scale = opts.colorScale;
15810
15906
  const useScale = scale && Array.isArray(scale.colors) && scale.colors.length > 0;
15811
15907
  const steps = useScale ? Math.max(2, scale.steps || 24) : 1;
15812
- const sMin = useScale && scale.min != null ? scale.min : w.globals.minY;
15813
- const sMax = useScale && scale.max != null ? scale.max : w.globals.maxY;
15908
+ const sMin = (_a = scale == null ? void 0 : scale.min) != null ? _a : extent[0];
15909
+ const sMax = (_b = scale == null ? void 0 : scale.max) != null ? _b : extent[1];
15814
15910
  const span = sMax - sMin || 1;
15815
15911
  const buckets = useScale ? new Array(steps).fill("") : [""];
15816
15912
  for (let k2 = 0; k2 < points.length; k2 += stride) {
@@ -15896,7 +15992,7 @@ function renderJitter({
15896
15992
  elSeries.add(elPointsWrap);
15897
15993
  }
15898
15994
  function darkenColor(color, amount) {
15899
- const rgb = Utils.parseHex(color);
15995
+ const rgb = Utils.parseColor(color) || Utils.parseColor(Utils.resolveColor(color));
15900
15996
  if (!rgb) return color;
15901
15997
  const f = Math.max(0, 1 - amount);
15902
15998
  return `rgb(${Math.round(rgb[0] * f)},${Math.round(rgb[1] * f)},${Math.round(rgb[2] * f)})`;
@@ -15961,7 +16057,7 @@ class BoxCandleStick extends Bar {
15961
16057
  if (!keyed || keyed.size === 0 || !row || row.length === 0) return false;
15962
16058
  let survivors = 0;
15963
16059
  for (let j = 0; j < row.length; j++) {
15964
- if (keyed.has(datumKey(this.w, realIndex, j))) survivors++;
16060
+ if (keyed.has(this._keys(realIndex)[j])) survivors++;
15965
16061
  }
15966
16062
  return survivors / keyed.size < 0.5;
15967
16063
  }
@@ -15990,7 +16086,7 @@ class BoxCandleStick extends Bar {
15990
16086
  }
15991
16087
  this._prevHalves[realIndex] = map;
15992
16088
  }
15993
- const halves = map && map.get(datumKey(this.w, realIndex, j));
16089
+ const halves = map && map.get(this._keys(realIndex)[j]);
15994
16090
  return halves && halves.length === 2 ? halves[pi] : null;
15995
16091
  }
15996
16092
  /**
@@ -16000,7 +16096,7 @@ class BoxCandleStick extends Bar {
16000
16096
  */
16001
16097
  // @ts-ignore -- BoxCandleStick.draw has an extra ctype param compared to Bar.draw
16002
16098
  draw(series, ctype, seriesIndex) {
16003
- var _a;
16099
+ var _a, _b;
16004
16100
  const w = this.w;
16005
16101
  const graphics = new Graphics(this.w);
16006
16102
  const type = w.globals.comboCharts ? ctype : w.config.chart.type;
@@ -16008,16 +16104,17 @@ class BoxCandleStick extends Bar {
16008
16104
  this.candlestickOptions = this.w.config.plotOptions.candlestick;
16009
16105
  this.boxOptions = this.w.config.plotOptions.boxPlot;
16010
16106
  this.isHorizontal = w.config.plotOptions.bar.horizontal;
16011
- this.isOHLC = this.candlestickOptions && this.candlestickOptions.type === "ohlc";
16012
16107
  this.coreUtils = new CoreUtils(this.w);
16013
16108
  series = this.coreUtils.getLogSeries(series);
16014
16109
  this.series = series;
16015
16110
  this.yRatio = this.coreUtils.getLogYRatios(this.yRatio);
16016
- this.barHelpers.initVariables(series);
16111
+ this.barHelpers.initVariables(series, seriesIndex);
16017
16112
  const ret = graphics.group({
16018
16113
  class: `apexcharts-${type}-series apexcharts-plot-series`
16019
16114
  });
16020
16115
  this.isBoxPlot = type === "boxPlot";
16116
+ this.isOHLC = !this.isBoxPlot && ((_a = this.candlestickOptions) == null ? void 0 : _a.type) === "ohlc";
16117
+ const jx = jitterExtent(w.candleData.seriesBoxPoints, w);
16021
16118
  for (let i = 0; i < series.length; i++) {
16022
16119
  let x2;
16023
16120
  let y;
@@ -16143,6 +16240,7 @@ class BoxCandleStick extends Bar {
16143
16240
  i,
16144
16241
  pathFrom: (_a2 = this._prevBoxHalf(realIndex, j, pi)) != null ? _a2 : paths.pathFrom,
16145
16242
  fadeReveal,
16243
+ noLabel: pi > 0,
16146
16244
  pathTo,
16147
16245
  strokeWidth,
16148
16246
  elSeries,
@@ -16164,7 +16262,7 @@ class BoxCandleStick extends Bar {
16164
16262
  }
16165
16263
  );
16166
16264
  if (boxPointsOpts && boxPointsOpts.show !== false) {
16167
- const pts = (_a = w.candleData.seriesBoxPoints[realIndex]) == null ? void 0 : _a[j];
16265
+ const pts = (_b = w.candleData.seriesBoxPoints[realIndex]) == null ? void 0 : _b[j];
16168
16266
  if (pts && pts.length) {
16169
16267
  const logVal = (v) => (
16170
16268
  /** @type {any} */
@@ -16175,14 +16273,14 @@ class BoxCandleStick extends Bar {
16175
16273
  );
16176
16274
  let center, halfExtent, alongFn;
16177
16275
  if (this.isHorizontal) {
16178
- const yRatio = this.invertedYRatio;
16276
+ const yRatio = this.invertedYRatio * (this.isReversed ? -1 : 1);
16179
16277
  const bh = barHeight != null ? barHeight : 0;
16180
16278
  const z = zeroW != null ? zeroW : 0;
16181
16279
  center = paths.barYPosition + bh / 2;
16182
16280
  halfExtent = bh / 2;
16183
16281
  alongFn = (v) => z + logVal(v) / yRatio;
16184
16282
  } else {
16185
- const yRatio = this.yRatio[translationsIndex];
16283
+ const yRatio = this.yRatio[translationsIndex] * (this.isReversed ? -1 : 1);
16186
16284
  const bw = barWidth != null ? barWidth : 0;
16187
16285
  const z = zeroH != null ? zeroH : 0;
16188
16286
  center = paths.barXPosition + bw / 2;
@@ -16190,8 +16288,8 @@ class BoxCandleStick extends Bar {
16190
16288
  alongFn = (v) => z - logVal(v) / yRatio;
16191
16289
  }
16192
16290
  const groups = buildJitterGroups({
16193
- w,
16194
16291
  points: pts,
16292
+ extent: jx,
16195
16293
  seedA: realIndex,
16196
16294
  seedB: j,
16197
16295
  center,
@@ -16220,15 +16318,13 @@ class BoxCandleStick extends Bar {
16220
16318
  w.globals.seriesXvalues[realIndex] = xArrj;
16221
16319
  w.globals.seriesYvalues[realIndex] = yArrj;
16222
16320
  if (w.globals.previousPaths.length > 0 && !fadeReveal) {
16223
- const newKeys = [];
16224
- for (let j = 0; j < series[i].length; j++) {
16225
- newKeys.push(datumKey(w, realIndex, j));
16226
- }
16227
16321
  renderBarExitGhosts({
16228
16322
  w,
16229
16323
  elSeries,
16230
16324
  record: this._prevRecord(realIndex),
16231
- newKeys,
16325
+ newKeys: this._keys(realIndex).filter(
16326
+ (_, j) => series[i][j] != null
16327
+ ),
16232
16328
  isHorizontal: this.isHorizontal,
16233
16329
  speed: w.config.chart.animations.dynamicAnimation.speed
16234
16330
  });
@@ -16247,7 +16343,7 @@ class BoxCandleStick extends Bar {
16247
16343
  strokeWidth,
16248
16344
  cullBounds = null
16249
16345
  }) {
16250
- var _a, _b, _c, _d;
16346
+ var _a, _b, _c;
16251
16347
  const w = this.w;
16252
16348
  const graphics = new Graphics(this.w);
16253
16349
  const i = indexes.i;
@@ -16258,7 +16354,7 @@ class BoxCandleStick extends Bar {
16258
16354
  const getColor = (color2) => Array.isArray(color2) ? color2[realIndex] : color2;
16259
16355
  const colorPos = getColor(candleColors.upward);
16260
16356
  const colorNeg = getColor(candleColors.downward);
16261
- const yRatio = this.yRatio[indexes.translationsIndex];
16357
+ const yRatio = this.yRatio[indexes.translationsIndex] * (this.isReversed ? -1 : 1);
16262
16358
  const ohlc = this.getOHLCValue(realIndex, j);
16263
16359
  let l1 = zeroH;
16264
16360
  let l2 = zeroH;
@@ -16275,9 +16371,11 @@ class BoxCandleStick extends Bar {
16275
16371
  x2 = pos.x;
16276
16372
  barXPosition = pos.barXPosition;
16277
16373
  }
16278
- if (typeof /** @type {any} */
16279
- ((_a = this.series[i]) == null ? void 0 : _a[j]) === "undefined" || /** @type {any} */
16280
- ((_b = this.series[i]) == null ? void 0 : _b[j]) === null) {
16374
+ const hole = (
16375
+ /** @type {any} */
16376
+ ((_a = this.series[i]) == null ? void 0 : _a[j]) == null
16377
+ );
16378
+ if (hole) {
16281
16379
  y1 = zeroH;
16282
16380
  y2 = zeroH;
16283
16381
  } else {
@@ -16287,7 +16385,7 @@ class BoxCandleStick extends Bar {
16287
16385
  l2 = zeroH - ohlc.l / yRatio;
16288
16386
  m = zeroH - ohlc.m / yRatio;
16289
16387
  }
16290
- if (cullBounds && (barXPosition + barWidth < cullBounds.lo || barXPosition > cullBounds.hi) && !this._wasOnScreen(realIndex, j)) {
16388
+ if (hole || cullBounds && (barXPosition + barWidth < cullBounds.lo || barXPosition > cullBounds.hi) && !this._wasOnScreen(realIndex, j)) {
16291
16389
  return {
16292
16390
  pathTo: null,
16293
16391
  pathFrom: null,
@@ -16317,7 +16415,7 @@ class BoxCandleStick extends Bar {
16317
16415
  ];
16318
16416
  }
16319
16417
  let pathFrom = null;
16320
- const morphFrom = (_d = (_c = this.ctx) == null ? void 0 : _c.morphTypeChange) == null ? void 0 : _d.getInitialPathFor(realIndex, j);
16418
+ const morphFrom = (_c = (_b = this.ctx) == null ? void 0 : _b.morphTypeChange) == null ? void 0 : _c.getInitialPathFor(realIndex, j);
16321
16419
  if (morphFrom) {
16322
16420
  pathFrom = morphFrom;
16323
16421
  } else if (w.globals.previousPaths.length > 0) {
@@ -16356,7 +16454,7 @@ class BoxCandleStick extends Bar {
16356
16454
  zeroW,
16357
16455
  strokeWidth
16358
16456
  }) {
16359
- var _a, _b, _c, _d;
16457
+ var _a, _b, _c;
16360
16458
  const w = this.w;
16361
16459
  const graphics = new Graphics(this.w);
16362
16460
  const i = indexes.i;
@@ -16365,7 +16463,7 @@ class BoxCandleStick extends Bar {
16365
16463
  const { colors: candleColors } = w.config.plotOptions.candlestick;
16366
16464
  const { colors: boxColors } = this.boxOptions;
16367
16465
  const getColor = (color2) => Array.isArray(color2) ? color2[realIndex] : color2;
16368
- const yRatio = this.invertedYRatio;
16466
+ const yRatio = this.invertedYRatio * (this.isReversed ? -1 : 1);
16369
16467
  const ohlc = this.getOHLCValue(realIndex, j);
16370
16468
  let color = ohlc.o < ohlc.c ? [getColor(candleColors.upward)] : [getColor(candleColors.downward)];
16371
16469
  if (this.isBoxPlot) {
@@ -16377,9 +16475,11 @@ class BoxCandleStick extends Bar {
16377
16475
  let x2 = Math.max(ohlc.o, ohlc.c);
16378
16476
  let m = ohlc.m;
16379
16477
  const barYPosition = y + barHeight * this.visibleI;
16380
- if (typeof /** @type {any} */
16381
- ((_a = this.series[i]) == null ? void 0 : _a[j]) === "undefined" || /** @type {any} */
16382
- ((_b = this.series[i]) == null ? void 0 : _b[j]) === null) {
16478
+ const hole = (
16479
+ /** @type {any} */
16480
+ ((_a = this.series[i]) == null ? void 0 : _a[j]) == null
16481
+ );
16482
+ if (hole) {
16383
16483
  x1 = zeroW;
16384
16484
  x2 = zeroW;
16385
16485
  } else {
@@ -16394,7 +16494,7 @@ class BoxCandleStick extends Bar {
16394
16494
  graphics.move(m, barYPosition) + graphics.line(m, barYPosition + barHeight) + graphics.line(x2, barYPosition + barHeight) + graphics.line(x2, barYPosition + barHeight / 2) + graphics.line(l2, barYPosition + barHeight / 2) + graphics.line(l2, barYPosition + barHeight - barHeight / 4) + graphics.line(l2, barYPosition + barHeight / 4) + graphics.line(l2, barYPosition + barHeight / 2) + graphics.line(x2, barYPosition + barHeight / 2) + graphics.line(x2, barYPosition) + graphics.line(m, barYPosition) + "z"
16395
16495
  ];
16396
16496
  let pathFrom = null;
16397
- const morphFrom = (_d = (_c = this.ctx) == null ? void 0 : _c.morphTypeChange) == null ? void 0 : _d.getInitialPathFor(realIndex, j);
16497
+ const morphFrom = (_c = (_b = this.ctx) == null ? void 0 : _b.morphTypeChange) == null ? void 0 : _c.getInitialPathFor(realIndex, j);
16398
16498
  if (morphFrom) {
16399
16499
  pathFrom = morphFrom;
16400
16500
  } else if (w.globals.previousPaths.length > 0) {
@@ -16419,7 +16519,8 @@ class BoxCandleStick extends Bar {
16419
16519
  0
16420
16520
  ),
16421
16521
  barYPosition,
16422
- color
16522
+ color,
16523
+ culled: hole
16423
16524
  };
16424
16525
  }
16425
16526
  /**
@@ -16596,13 +16697,9 @@ class TreemapHelpers {
16596
16697
  elDataLabelsWrap = graphics.group({
16597
16698
  class: "apexcharts-data-labels"
16598
16699
  });
16599
- const offX = resolveDataLabelOffset(dataLabelsConfig.offsetX, w, i, j);
16600
- const offY = resolveDataLabelOffset(dataLabelsConfig.offsetY, w, i, j);
16601
- const dataLabelsX = x2 + offX;
16602
- const dataLabelsY = y + parseFloat(dataLabelsConfig.style.fontSize) / 3 + offY;
16603
16700
  dataLabels.plotDataLabelsText({
16604
- x: dataLabelsX,
16605
- y: dataLabelsY,
16701
+ x: x2,
16702
+ y: y + parseFloat(dataLabelsConfig.style.fontSize) / 3,
16606
16703
  text,
16607
16704
  i,
16608
16705
  j,
@@ -17066,18 +17163,16 @@ class Helpers4 {
17066
17163
  this.lineCtx = lineCtx;
17067
17164
  }
17068
17165
  /**
17069
- * @param {number} i
17166
+ * @param {number} i index into `series`, the rows this draw call renders
17070
17167
  * @param {any[]} series
17168
+ * @param {number} realIndex index into the config / fill options
17071
17169
  */
17072
- sameValueSeriesFix(i, series) {
17170
+ sameValueSeriesFix(i, series, realIndex) {
17073
17171
  const w = this.w;
17074
- if (w.config.fill.type === "gradient" || w.config.fill.type[i] === "gradient") {
17075
- const coreUtils = new CoreUtils(this.lineCtx.w);
17076
- if (coreUtils.seriesHaveSameValues(i)) {
17077
- const gSeries = series[i].slice();
17078
- gSeries[gSeries.length - 1] = gSeries[gSeries.length - 1] + 1e-6;
17079
- series[i] = gSeries;
17080
- }
17172
+ const s = series[i];
17173
+ if ((w.config.fill.type === "gradient" || w.config.fill.type[realIndex] === "gradient") && s.every((v) => v === s[0])) {
17174
+ series[i] = s.slice();
17175
+ series[i][s.length - 1] += 1e-6;
17081
17176
  }
17082
17177
  return series;
17083
17178
  }
@@ -17518,13 +17613,27 @@ class Line {
17518
17613
  this.yRatio = coreUtils.getLogYRatios(this.yRatio);
17519
17614
  this.prevSeriesY = [];
17520
17615
  this.prevSeriesYByX = /* @__PURE__ */ new Map();
17616
+ this._stackXs = null;
17617
+ if (w.config.chart.stacked && w.axisFlags.isXNumeric) {
17618
+ const xs = series.map(
17619
+ (_, i) => w.globals.comboCharts ? (
17620
+ /** @type {any} */
17621
+ seriesIndex[i]
17622
+ ) : i
17623
+ ).filter((ri) => !this._hidden(ri)).map((ri) => w.seriesData.seriesX[ri] || []);
17624
+ if (xs.some(
17625
+ (a) => a.length !== xs[0].length || a.some((v, k2) => v !== xs[0][k2])
17626
+ )) {
17627
+ this._stackXs = [...new Set(xs.flat())].sort((a, b) => a - b);
17628
+ }
17629
+ }
17521
17630
  const allSeries = [];
17522
17631
  for (let i = 0; i < series.length; i++) {
17523
- series = this.lineHelpers.sameValueSeriesFix(i, series);
17524
17632
  const realIndex = w.globals.comboCharts ? (
17525
17633
  /** @type {any} */
17526
17634
  seriesIndex[i]
17527
17635
  ) : i;
17636
+ series = this.lineHelpers.sameValueSeriesFix(i, series, realIndex);
17528
17637
  const translationsIndex = this.yRatio.length > 1 ? realIndex : 0;
17529
17638
  const flat = this._collapsedBaselineRow(series, i, realIndex);
17530
17639
  this._shapeOnly = !!flat;
@@ -17708,9 +17817,7 @@ class Line {
17708
17817
  const gl = w.globals;
17709
17818
  if (w.config.chart.stacked || this.pointsChart) return null;
17710
17819
  if (!Array.isArray(series[i]) || series[i].length !== 0) return null;
17711
- if (gl.collapsedSeriesIndices.indexOf(realIndex) === -1 && gl.ancillaryCollapsedSeriesIndices.indexOf(realIndex) === -1) {
17712
- return null;
17713
- }
17820
+ if (!this._hidden(realIndex)) return null;
17714
17821
  const n = w.axisFlags.isXNumeric ? (w.seriesData.seriesX[realIndex] || []).length : gl.dataPoints;
17715
17822
  if (!n) return null;
17716
17823
  const lo = Utils.isNumber(gl.minYArr[realIndex]) ? gl.minYArr[realIndex] : gl.minY;
@@ -17839,6 +17946,11 @@ class Line {
17839
17946
  if (key === void 0 || key === null) return void 0;
17840
17947
  return this.prevSeriesYByX.get(key);
17841
17948
  }
17949
+ /** @param {number} ri */
17950
+ _hidden(ri) {
17951
+ const g = this.w.globals;
17952
+ return g.collapsedSeriesIndices.indexOf(ri) > -1 || g.ancillaryCollapsedSeriesIndices.indexOf(ri) > -1;
17953
+ }
17842
17954
  /**
17843
17955
  * Fold a drawn series into the running stack top, so the next series can find
17844
17956
  * its baseline by x (#4886).
@@ -17854,19 +17966,18 @@ class Line {
17854
17966
  * correct if that representation ever changes.
17855
17967
  * @param {number} realIndex
17856
17968
  * @param {any[]} yArrj
17969
+ * @param {any[]} [row] the drawn row, if not the series' own (a part)
17857
17970
  */
17858
- _recordStackTops(realIndex, yArrj) {
17971
+ _recordStackTops(realIndex, yArrj, row = this.w.seriesData.series[realIndex]) {
17859
17972
  const w = this.w;
17860
17973
  if (!w.config.chart.stacked) return;
17861
17974
  if (!Array.isArray(yArrj)) return;
17862
- if (w.globals.collapsedSeriesIndices.indexOf(realIndex) !== -1 || w.globals.ancillaryCollapsedSeriesIndices.indexOf(realIndex) !== -1) {
17863
- return;
17864
- }
17975
+ if (this._hidden(realIndex)) return;
17865
17976
  for (let j = 0; j < yArrj.length; j++) {
17866
17977
  const key = this._stackKey(realIndex, j);
17867
17978
  if (key === void 0 || key === null) continue;
17868
17979
  const y = yArrj[j];
17869
- if (!Utils.isNumber(y)) continue;
17980
+ if (!Utils.isNumber(y) || (row == null ? void 0 : row[j]) == null) continue;
17870
17981
  this.prevSeriesYByX.set(key, y);
17871
17982
  }
17872
17983
  }
@@ -17899,7 +18010,8 @@ class Line {
17899
18010
  w.globals.seriesYvalues[realIndex] = paths.yArrj;
17900
18011
  const forecast = w.config.forecastDataPoints;
17901
18012
  if (forecast.count > 0 && type !== "rangeArea") {
17902
- const forecastCutoff = w.globals.seriesXvalues[realIndex][w.globals.seriesXvalues[realIndex].length - forecast.count - 1];
18013
+ const ci = paths.xArrj.length - forecast.count - 1;
18014
+ const forecastCutoff = w.axisFlags.isXNumeric ? (w.seriesData.seriesX[realIndex][ci] - w.globals.minX) / this.xRatio : w.globals.padHorizontal + this.categoryAxisCorrection + ci * this.xDivision;
17903
18015
  const elForecastMask = graphics.drawRect(
17904
18016
  forecastCutoff,
17905
18017
  0,
@@ -17986,7 +18098,7 @@ class Line {
17986
18098
  scrollMorph: !!streamScroll,
17987
18099
  stroke: "none",
17988
18100
  strokeWidth: 0,
17989
- strokeLineCap: null,
18101
+ strokeLinecap: null,
17990
18102
  fill: pathFill
17991
18103
  }));
17992
18104
  this.elSeries.add(renderedPath);
@@ -18028,7 +18140,7 @@ class Line {
18028
18140
  scrollMorph: !!streamScroll,
18029
18141
  stroke: lineFill,
18030
18142
  strokeWidth: this.strokeWidth,
18031
- strokeLineCap: w.config.stroke.lineCap,
18143
+ strokeLinecap: w.config.stroke.lineCap,
18032
18144
  fill: type === "rangeArea" ? pathFill : "none"
18033
18145
  });
18034
18146
  const renderedPath = emit.renderPaths(linePathCommonOpts);
@@ -18082,7 +18194,7 @@ class Line {
18082
18194
  isRangeStart,
18083
18195
  seriesRangeEnd
18084
18196
  }) {
18085
- var _a, _b;
18197
+ var _a, _b, _c;
18086
18198
  const w = this.w;
18087
18199
  const graphics = new Graphics(this.w);
18088
18200
  const yRatio = this.yRatio;
@@ -18134,15 +18246,30 @@ class Line {
18134
18246
  });
18135
18247
  if (fast) return fast;
18136
18248
  }
18249
+ const ks = stackSeries ? this._stackXs : null;
18250
+ let kp = 0;
18251
+ const midsAt = [];
18137
18252
  for (let j = 0; j < iterations; j++) {
18138
18253
  if (series[i].length === 0) break;
18139
18254
  const isNull = typeof series[i][j + 1] === "undefined" || series[i][j + 1] === null;
18140
18255
  if (w.axisFlags.isXNumeric) {
18141
- let sX = w.seriesData.seriesX[realIndex][j + 1];
18142
- if (typeof w.seriesData.seriesX[realIndex][j + 1] === "undefined") {
18143
- sX = w.seriesData.seriesX[realIndex][iterations - 1];
18256
+ const sxs = w.seriesData.seriesX[realIndex];
18257
+ let sX = sxs[j + 1];
18258
+ if (typeof sX === "undefined") {
18259
+ sX = sxs[iterations - 1];
18144
18260
  }
18145
18261
  x2 = (sX - w.globals.minX) / this.xRatio;
18262
+ if (ks) {
18263
+ const m = [];
18264
+ while (ks[kp] <= sxs[j]) kp++;
18265
+ while (ks[kp] < sX) {
18266
+ m.push([
18267
+ (ks[kp] - w.globals.minX) / this.xRatio,
18268
+ (_c = this.prevSeriesYByX.get(ks[kp++])) != null ? _c : this.zeroY
18269
+ ]);
18270
+ }
18271
+ if (m.length) midsAt[j + 1] = m;
18272
+ }
18146
18273
  } else {
18147
18274
  x2 = x2 + this.xDivision;
18148
18275
  }
@@ -18152,9 +18279,7 @@ class Line {
18152
18279
  var _a2;
18153
18280
  for (let pii = pi; pii >= 0; pii--) {
18154
18281
  const ri = (_a2 = seriesIndex == null ? void 0 : seriesIndex[pii]) != null ? _a2 : pii;
18155
- if (w.globals.collapsedSeriesIndices.indexOf(ri) === -1 && w.globals.ancillaryCollapsedSeriesIndices.indexOf(ri) === -1) {
18156
- return pii;
18157
- }
18282
+ if (!this._hidden(ri)) return pii;
18158
18283
  }
18159
18284
  return -1;
18160
18285
  };
@@ -18210,6 +18335,7 @@ class Line {
18210
18335
  j,
18211
18336
  x: x2,
18212
18337
  y,
18338
+ midsAt,
18213
18339
  y2,
18214
18340
  xArrj,
18215
18341
  yArrj,
@@ -18450,7 +18576,7 @@ class Line {
18450
18576
  numericXY: nxs ? { xs: nxs, ys: nys, areaCloseY: bottomY } : void 0
18451
18577
  };
18452
18578
  }
18453
- /** @param {{type: any, series: any, i: any, j: any, x: any, y: any, xArrj: any, yArrj: any, y2: any, y2Arrj: any, pX: any, pY: any, pathState: any, segmentStartX: any, linePath: any, areaPath: any, linePaths: any, areaPaths: any, curve: any, isRangeStart: any}} opts */
18579
+ /** @param {{type: any, series: any, i: any, j: any, x: any, y: any, midsAt: any[][], xArrj: any, yArrj: any, y2: any, y2Arrj: any, pX: any, pY: any, pathState: any, segmentStartX: any, linePath: any, areaPath: any, linePaths: any, areaPaths: any, curve: any, isRangeStart: any}} opts */
18454
18580
  _createPaths({
18455
18581
  type,
18456
18582
  series,
@@ -18458,6 +18584,7 @@ class Line {
18458
18584
  j,
18459
18585
  x: x2,
18460
18586
  y,
18587
+ midsAt,
18461
18588
  xArrj,
18462
18589
  yArrj,
18463
18590
  y2,
@@ -18477,6 +18604,8 @@ class Line {
18477
18604
  const areaBottomY = this.areaBottomY;
18478
18605
  const rangeArea = type === "rangeArea";
18479
18606
  const isLowerRangeAreaPath = type === "rangeArea" && isRangeStart;
18607
+ const mids = midsAt[j + 1];
18608
+ const via = (f) => mids ? [...mids, [x2, y]].map(([bx, by], k2, a) => f(...k2 ? a[k2 - 1] : [pX, pY], bx, by)).join("") : f(pX, pY, x2, y);
18480
18609
  switch (curve) {
18481
18610
  case "monotoneCubic": {
18482
18611
  const yAj = isRangeStart ? yArrj : y2Arrj;
@@ -18522,8 +18651,19 @@ class Line {
18522
18651
  }
18523
18652
  // falls through
18524
18653
  case 2: {
18525
- const _xAj = isRangeStart ? xArrj : xArrj.slice().reverse();
18526
- const _yAj = isRangeStart ? yAj : yAj.slice().reverse();
18654
+ let _xAj = isRangeStart ? xArrj : xArrj.slice().reverse();
18655
+ let _yAj = isRangeStart ? yAj : yAj.slice().reverse();
18656
+ if (midsAt.length && !rangeArea) {
18657
+ const P = [];
18658
+ _xAj.forEach((v, k2) => {
18659
+ if (_yAj[k2] !== null && _yAj[k2 - 1] != null && midsAt[k2]) {
18660
+ P.push(...midsAt[k2]);
18661
+ }
18662
+ P.push([v, _yAj[k2]]);
18663
+ });
18664
+ _xAj = P.map((p) => p[0]);
18665
+ _yAj = P.map((p) => p[1]);
18666
+ }
18527
18667
  const smoothInputs = getSmoothInputs(_xAj, _yAj);
18528
18668
  const points = smoothInputs.length > 1 ? spline.points(smoothInputs) : smoothInputs;
18529
18669
  let smoothInputsLower = [];
@@ -18582,7 +18722,10 @@ class Line {
18582
18722
  break;
18583
18723
  }
18584
18724
  case "smooth": {
18585
- const length = (x2 - pX) * 0.35;
18725
+ const toPoint = (ax, ay, bx, by) => {
18726
+ const l = (bx - ax) * 0.35;
18727
+ return graphics.curve(ax + l, ay, bx - l, by, bx, by);
18728
+ };
18586
18729
  if (series[i][j] === null) {
18587
18730
  pathState = 0;
18588
18731
  } else {
@@ -18602,7 +18745,7 @@ class Line {
18602
18745
  }
18603
18746
  pathState = 1;
18604
18747
  if (j < series[i].length - 2) {
18605
- const p = graphics.curve(pX + length, pY, x2 - length, y, x2, y);
18748
+ const p = via(toPoint);
18606
18749
  linePath += p;
18607
18750
  areaPath += p;
18608
18751
  break;
@@ -18620,7 +18763,7 @@ class Line {
18620
18763
  areaPaths.push(areaPath);
18621
18764
  pathState = -1;
18622
18765
  } else {
18623
- const p = graphics.curve(pX + length, pY, x2 - length, y, x2, y);
18766
+ const p = via(toPoint);
18624
18767
  linePath += p;
18625
18768
  areaPath += p;
18626
18769
  if (j >= series[i].length - 2) {
@@ -18641,9 +18784,9 @@ class Line {
18641
18784
  break;
18642
18785
  }
18643
18786
  default: {
18644
- const pathToPoint = (curve2, x3, y3) => {
18787
+ const pathToPoint = (_ax, _ay, x3, y3) => {
18645
18788
  let path = "";
18646
- switch (curve2) {
18789
+ switch (curve) {
18647
18790
  case "stepline":
18648
18791
  path = graphics.line(x3, null, "H") + graphics.line(null, y3, "V");
18649
18792
  break;
@@ -18675,7 +18818,7 @@ class Line {
18675
18818
  }
18676
18819
  pathState = 1;
18677
18820
  if (j < series[i].length - 2) {
18678
- const p = pathToPoint(curve, x2, y);
18821
+ const p = via(pathToPoint);
18679
18822
  linePath += p;
18680
18823
  areaPath += p;
18681
18824
  break;
@@ -18693,7 +18836,7 @@ class Line {
18693
18836
  areaPaths.push(areaPath);
18694
18837
  pathState = -1;
18695
18838
  } else {
18696
- const p = pathToPoint(curve, x2, y);
18839
+ const p = via(pathToPoint);
18697
18840
  linePath += p;
18698
18841
  areaPath += p;
18699
18842
  if (j >= series[i].length - 2) {
@@ -20552,7 +20695,7 @@ class Radar {
20552
20695
  }
20553
20696
  s.forEach((dv, j) => {
20554
20697
  const range = Math.abs(this.maxValue - this.minValue);
20555
- dv = dv - this.minValue;
20698
+ dv = Math.max(0, dv - this.minValue);
20556
20699
  if (this.isLog) {
20557
20700
  dv = this.coreUtils.getLogVal(this.logBase, dv, 0);
20558
20701
  }
@@ -20589,7 +20732,7 @@ class Radar {
20589
20732
  shouldClipToGrid: false,
20590
20733
  bindEventsOnPaths: false,
20591
20734
  stroke: w.globals.stroke.colors[i],
20592
- strokeLineCap: w.config.stroke.lineCap
20735
+ strokeLinecap: w.config.stroke.lineCap
20593
20736
  };
20594
20737
  let pathFrom = null;
20595
20738
  if (w.globals.previousPaths.length > 0) {
@@ -20766,6 +20909,7 @@ class Radar {
20766
20909
  drawXAxisTexts() {
20767
20910
  const w = this.w;
20768
20911
  const xaxisLabelsConfig = w.config.xaxis.labels;
20912
+ const lc = xaxisLabelsConfig.style.colors;
20769
20913
  const elXAxisWrap = this.graphics.group({
20770
20914
  class: "apexcharts-xaxis"
20771
20915
  });
@@ -20789,7 +20933,7 @@ class Radar {
20789
20933
  j: i,
20790
20934
  parent: elXAxisWrap,
20791
20935
  className: "apexcharts-xaxis-label",
20792
- color: Array.isArray(xaxisLabelsConfig.style.colors) && xaxisLabelsConfig.style.colors[i] ? xaxisLabelsConfig.style.colors[i] : "#a8a8a8",
20936
+ color: (Array.isArray(lc) ? lc[i] : lc) || "#a8a8a8",
20793
20937
  dataLabelsConfig: __spreadValues({
20794
20938
  textAnchor: textPos.textAnchor,
20795
20939
  dropShadow: { enabled: false }
@@ -21774,14 +21918,14 @@ class RangeBar extends Bar {
21774
21918
  * @param {number} seriesIndex
21775
21919
  */
21776
21920
  draw(series, seriesIndex) {
21777
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
21921
+ var _a, _b, _c, _d, _e, _f;
21778
21922
  const w = this.w;
21779
21923
  const graphics = new Graphics(this.w);
21780
21924
  this.rangeBarOptions = this.w.config.plotOptions.rangeBar;
21781
21925
  this.series = series;
21782
21926
  this.seriesRangeStart = w.rangeData.seriesRangeStart;
21783
21927
  this.seriesRangeEnd = w.rangeData.seriesRangeEnd;
21784
- this.barHelpers.initVariables(series);
21928
+ this.barHelpers.initVariables(series, seriesIndex);
21785
21929
  const ret = graphics.group({
21786
21930
  class: "apexcharts-rangebar-series apexcharts-plot-series"
21787
21931
  });
@@ -21803,6 +21947,9 @@ class RangeBar extends Bar {
21803
21947
  this.visibleI = this.visibleI + 1;
21804
21948
  }
21805
21949
  const translationsIndex = this.setSeriesAxis(realIndex);
21950
+ if (this.isHorizontal && w.labelData.timescaleLabels.length) {
21951
+ this.isReversed = false;
21952
+ }
21806
21953
  const initPositions = this.barHelpers.initialPositions(realIndex);
21807
21954
  const {
21808
21955
  y: initY,
@@ -21812,10 +21959,8 @@ class RangeBar extends Bar {
21812
21959
  zeroH
21813
21960
  // zeroH is the baseline where 0 meets y axis
21814
21961
  } = initPositions;
21815
- let barWidth = (_a = initPositions.barWidth) != null ? _a : 0;
21816
- let barHeight = (_b = initPositions.barHeight) != null ? _b : 0;
21817
- const yDivision = (_c = initPositions.yDivision) != null ? _c : 0;
21818
- const xDivision = (_d = initPositions.xDivision) != null ? _d : 0;
21962
+ const yDivision = (_a = initPositions.yDivision) != null ? _a : 0;
21963
+ const xDivision = (_b = initPositions.xDivision) != null ? _b : 0;
21819
21964
  y = initY;
21820
21965
  x2 = initX;
21821
21966
  const elDataLabelsWrap = graphics.group({
@@ -21825,10 +21970,16 @@ class RangeBar extends Bar {
21825
21970
  const elGoalsMarkers = graphics.group({
21826
21971
  class: "apexcharts-rangebar-goals-markers"
21827
21972
  });
21973
+ const data = (
21974
+ /** @type {any} */
21975
+ w.config.series[realIndex].data
21976
+ );
21828
21977
  for (let j = 0; j < w.globals.dataPoints; j++) {
21829
21978
  const strokeWidth = this.barHelpers.getStrokeWidth(i, j, realIndex);
21830
- const y1 = this.seriesRangeStart[i][j];
21831
- const y2 = this.seriesRangeEnd[i][j];
21979
+ let barWidth = (_c = initPositions.barWidth) != null ? _c : 0;
21980
+ let barHeight = (_d = initPositions.barHeight) != null ? _d : 0;
21981
+ const y1 = this.seriesRangeStart[realIndex][j];
21982
+ const y2 = this.seriesRangeEnd[realIndex][j];
21832
21983
  let paths = (
21833
21984
  /** @type {any} */
21834
21985
  null
@@ -21840,20 +21991,16 @@ class RangeBar extends Bar {
21840
21991
  if (w.config.plotOptions.bar.rangeBarGroupRows) {
21841
21992
  seriesLen = 1;
21842
21993
  }
21843
- if (typeof /** @type {Record<string,any>} */
21844
- ((_e = w.config.series[i].data) == null ? void 0 : _e[j]) === "undefined") {
21994
+ if (typeof (data == null ? void 0 : data[j]) === "undefined") {
21845
21995
  break;
21846
21996
  }
21847
21997
  if (this.isHorizontal) {
21848
21998
  barYPosition = y + barHeight * /** @type {any} */
21849
21999
  this.visibleI;
21850
22000
  const srty = (yDivision - barHeight * seriesLen) / 2;
21851
- if (
21852
- /** @type {Record<string,any>} */
21853
- (_g = (_f = w.config.series[i].data) == null ? void 0 : _f[j]) == null ? void 0 : _g.x
21854
- ) {
22001
+ if (((_e = data[j]) == null ? void 0 : _e.x) != null) {
21855
22002
  const positions = this.detectOverlappingBars({
21856
- i,
22003
+ i: realIndex,
21857
22004
  j,
21858
22005
  barYPosition,
21859
22006
  srty,
@@ -21876,17 +22023,14 @@ class RangeBar extends Bar {
21876
22023
  barWidth = paths.barWidth;
21877
22024
  } else {
21878
22025
  if (w.axisFlags.isXNumeric) {
21879
- x2 = (w.seriesData.seriesX[i][j] - w.globals.minX) / this.xRatio - barWidth / 2;
22026
+ x2 = (w.seriesData.seriesX[realIndex][j] - w.globals.minX) / this.xRatio - barWidth / 2;
21880
22027
  }
21881
22028
  barXPosition = x2 + barWidth * /** @type {any} */
21882
22029
  this.visibleI;
21883
22030
  const srtx = (xDivision - barWidth * seriesLen) / 2;
21884
- if (
21885
- /** @type {Record<string,any>} */
21886
- (_i = (_h = w.config.series[i].data) == null ? void 0 : _h[j]) == null ? void 0 : _i.x
21887
- ) {
22031
+ if (((_f = data[j]) == null ? void 0 : _f.x) != null) {
21888
22032
  const positions = this.detectOverlappingBars({
21889
- i,
22033
+ i: realIndex,
21890
22034
  j,
21891
22035
  barXPosition,
21892
22036
  srtx,
@@ -21905,9 +22049,10 @@ class RangeBar extends Bar {
21905
22049
  xDivision
21906
22050
  }, params));
21907
22051
  barHeight = paths.barHeight;
22052
+ barXPosition = paths.barXPosition;
21908
22053
  }
21909
22054
  const barGoalLine = this.barHelpers.drawGoalLine({
21910
- barXPosition: paths.barXPosition,
22055
+ barXPosition,
21911
22056
  barYPosition,
21912
22057
  goalX: paths.goalX,
21913
22058
  goalY: paths.goalY,
@@ -21952,19 +22097,11 @@ class RangeBar extends Bar {
21952
22097
  });
21953
22098
  }
21954
22099
  if (w.globals.previousPaths.length > 0) {
21955
- const data = (
21956
- /** @type {Record<string,any>} */
21957
- w.config.series[i].data || []
21958
- );
21959
- const newKeys = [];
21960
- for (let j = 0; j < data.length; j++) {
21961
- newKeys.push(datumKey(w, realIndex, j));
21962
- }
21963
22100
  renderBarExitGhosts({
21964
22101
  w,
21965
22102
  elSeries,
21966
22103
  record: this._prevRecord(realIndex),
21967
- newKeys,
22104
+ newKeys: this._keys(realIndex),
21968
22105
  isHorizontal: this.isHorizontal,
21969
22106
  speed: w.config.chart.animations.dynamicAnimation.speed
21970
22107
  });
@@ -22016,11 +22153,11 @@ class RangeBar extends Bar {
22016
22153
  );
22017
22154
  if (overlaps.indexOf(rangeName) > -1) {
22018
22155
  barHeight = initPositions.barHeight / overlaps.length;
22019
- barYPosition = barHeight * this.visibleI + yDivision * (100 - parseInt(this.barOptions.barHeight, 10)) / 100 / 2 + barHeight * (this.visibleI + overlaps.indexOf(rangeName)) + yDivision * rowIndex;
22156
+ barYPosition += barHeight * overlaps.indexOf(rangeName);
22020
22157
  }
22021
22158
  }
22022
22159
  } else {
22023
- if (rowIndex > -1 && !w.labelData.timescaleLabels.length) {
22160
+ if (rowIndex > -1 && !w.axisFlags.isXNumeric) {
22024
22161
  if (w.config.plotOptions.bar.rangeBarGroupRows) {
22025
22162
  barXPosition = srtx + xDivision * rowIndex;
22026
22163
  } else {
@@ -22034,7 +22171,7 @@ class RangeBar extends Bar {
22034
22171
  );
22035
22172
  if (overlaps.indexOf(rangeName) > -1) {
22036
22173
  barWidth = initPositions.barWidth / overlaps.length;
22037
- barXPosition = barWidth * this.visibleI + xDivision * (100 - parseInt(this.barOptions.barWidth, 10)) / 100 / 2 + barWidth * (this.visibleI + overlaps.indexOf(rangeName)) + xDivision * rowIndex;
22174
+ barXPosition += barWidth * overlaps.indexOf(rangeName);
22038
22175
  }
22039
22176
  }
22040
22177
  }
@@ -22057,7 +22194,7 @@ class RangeBar extends Bar {
22057
22194
  var _a, _b;
22058
22195
  const w = this.w;
22059
22196
  const { i, j, realIndex, translationsIndex } = indexes;
22060
- const yRatio = this.yRatio[translationsIndex];
22197
+ const yRatio = this.yRatio[translationsIndex] * (this.isReversed ? -1 : 1);
22061
22198
  const range = this.getRangeValue(realIndex, j);
22062
22199
  let y1 = Math.min(range.start, range.end);
22063
22200
  let y2 = Math.max(range.start, range.end);
@@ -22065,7 +22202,7 @@ class RangeBar extends Bar {
22065
22202
  ((_a = this.series[i]) == null ? void 0 : _a[j]) === "undefined" || /** @type {any} */
22066
22203
  ((_b = this.series[i]) == null ? void 0 : _b[j]) === null);
22067
22204
  if (!hasValue) {
22068
- y1 = zeroH;
22205
+ y1 = y2 = zeroH;
22069
22206
  } else {
22070
22207
  y1 = zeroH - y1 / yRatio;
22071
22208
  y2 = zeroH - y2 / yRatio;
@@ -22126,6 +22263,30 @@ class RangeBar extends Bar {
22126
22263
  barXPosition
22127
22264
  };
22128
22265
  }
22266
+ /**
22267
+ * Timeline datums key by their own row, not by the j-th label: a row can
22268
+ * hold several bars, so labels[j] names some other datum's row.
22269
+ * @param {number} realIndex
22270
+ * @returns {string[]}
22271
+ */
22272
+ _keys(realIndex) {
22273
+ const c = (
22274
+ /** @type {any} */
22275
+ this._keyCache || (this._keyCache = {})
22276
+ );
22277
+ const data = (
22278
+ /** @type {any} */
22279
+ this.w.config.series[realIndex].data
22280
+ );
22281
+ return c[realIndex] || (c[realIndex] = uniquifyKeys(
22282
+ (data || []).map(
22283
+ (d, j) => {
22284
+ var _a;
22285
+ return "c:" + ((_a = d == null ? void 0 : d.x) != null ? _a : j);
22286
+ }
22287
+ )
22288
+ ));
22289
+ }
22129
22290
  /**
22130
22291
  * @param {number} val
22131
22292
  */
@@ -22152,8 +22313,9 @@ class RangeBar extends Bar {
22152
22313
  }) {
22153
22314
  const w = this.w;
22154
22315
  const { realIndex, j } = indexes;
22155
- const x1 = this.preventBarOverflow(zeroW + y1 / this.invertedYRatio);
22156
- const x2 = this.preventBarOverflow(zeroW + y2 / this.invertedYRatio);
22316
+ const ratio = this.invertedYRatio * (this.isReversed ? -1 : 1);
22317
+ const x1 = this.preventBarOverflow(zeroW + y1 / ratio);
22318
+ const x2 = this.preventBarOverflow(zeroW + y2 / ratio);
22157
22319
  const range = this.getRangeValue(realIndex, j);
22158
22320
  const barWidth = Math.abs(x2 - x1);
22159
22321
  const paths = this.barHelpers.getBarpaths({
@@ -22400,26 +22562,33 @@ function drilldownById(w, id) {
22400
22562
  const list = dd && Array.isArray(dd.series) ? dd.series : [];
22401
22563
  return list.find((s) => s && s.id === id);
22402
22564
  }
22403
- function toNode(w, d, i, paletteFromParent, parentKey, seenIds = null, opts = {}) {
22565
+ function segment(name, seen) {
22566
+ var _a;
22567
+ const n = String(name).replace(/\//g, "%2F");
22568
+ const o = ((_a = seen.get(n)) != null ? _a : -1) + 1;
22569
+ seen.set(n, o);
22570
+ return `${o}:${n}`;
22571
+ }
22572
+ function toNode(w, d, i, paletteFromParent, parentKey, seenIds = null, opts = {}, seen = /* @__PURE__ */ new Map()) {
22404
22573
  var _a, _b, _c;
22405
22574
  const isObj = d && typeof d === "object";
22406
22575
  const name = isObj ? (_b = (_a = d.x) != null ? _a : d.name) != null ? _b : "" : "";
22407
- const value = isObj ? Number((_c = d.y) != null ? _c : d.value) : Number(d);
22576
+ const raw = isObj ? (_c = d.y) != null ? _c : d.value : d;
22577
+ const value = raw == null || raw === "" ? NaN : Number(raw);
22408
22578
  const node = {
22409
22579
  name: String(name),
22410
22580
  value: isNaN(value) ? null : value,
22411
22581
  color: isObj && d.color ? d.color : void 0,
22412
- // Identity across data updates: the path of names (indexed so same-named
22413
- // siblings stay distinct). Update animations morph matched keys in place.
22414
- _key: `${parentKey}/${i}:${name}`
22582
+ _key: `${parentKey}/${segment(name, seen)}`
22415
22583
  };
22416
22584
  if (paletteFromParent && !node.color) {
22417
22585
  node.color = paletteFromParent[i % paletteFromParent.length];
22418
22586
  }
22419
22587
  if (opts.keepDatum) node._datum = d;
22588
+ const kids = /* @__PURE__ */ new Map();
22420
22589
  if (isObj && Array.isArray(d.children) && d.children.length) {
22421
22590
  node.children = d.children.map(
22422
- (c, j) => toNode(w, c, j, null, node._key, seenIds, opts)
22591
+ (c, j) => toNode(w, c, j, null, node._key, seenIds, opts, kids)
22423
22592
  );
22424
22593
  } else if (isObj && d.drilldown != null && opts.expandDrilldown !== false) {
22425
22594
  const visited = seenIds || /* @__PURE__ */ new Set();
@@ -22430,7 +22599,7 @@ function toNode(w, d, i, paletteFromParent, parentKey, seenIds = null, opts = {}
22430
22599
  nextSeen.add(d.drilldown);
22431
22600
  const palette = Array.isArray(dd.colors) ? dd.colors : null;
22432
22601
  node.children = dd.data.map(
22433
- (c, j) => toNode(w, c, j, palette, node._key, nextSeen, opts)
22602
+ (c, j) => toNode(w, c, j, palette, node._key, nextSeen, opts, kids)
22434
22603
  );
22435
22604
  }
22436
22605
  }
@@ -22443,10 +22612,12 @@ function buildSeriesRoots(w, series, opts = {}) {
22443
22612
  series || w.config.series
22444
22613
  );
22445
22614
  if (!Array.isArray(cfgSeries)) return [];
22615
+ const seen = /* @__PURE__ */ new Map();
22446
22616
  return cfgSeries.map((s, i) => {
22447
22617
  var _a, _b;
22448
22618
  const data = s && Array.isArray(s.data) ? s.data : [];
22449
- const key = `${i}:${(_a = s == null ? void 0 : s.name) != null ? _a : ""}`;
22619
+ const key = segment((_a = s == null ? void 0 : s.name) != null ? _a : "", seen);
22620
+ const kids = /* @__PURE__ */ new Map();
22450
22621
  const root = {
22451
22622
  name: String((_b = s == null ? void 0 : s.name) != null ? _b : ""),
22452
22623
  value: null,
@@ -22454,7 +22625,7 @@ function buildSeriesRoots(w, series, opts = {}) {
22454
22625
  _key: key,
22455
22626
  _seriesIndex: i,
22456
22627
  children: data.map(
22457
- (d, j) => toNode(w, d, j, null, key, null, opts)
22628
+ (d, j) => toNode(w, d, j, null, key, null, opts, kids)
22458
22629
  )
22459
22630
  };
22460
22631
  return root;
@@ -22620,7 +22791,7 @@ function renderBreadcrumb(w, opts) {
22620
22791
  text.setAttribute("class", "apexcharts-breadcrumb-label");
22621
22792
  text.textContent = String(label);
22622
22793
  btn.appendChild(text);
22623
- btn.addEventListener("click", () => opts.onNavigate(i, crumb));
22794
+ btn.addEventListener("click", (e) => opts.onNavigate(i, crumb, e));
22624
22795
  nav.appendChild(btn);
22625
22796
  });
22626
22797
  elWrap.appendChild(nav);
@@ -22728,7 +22899,7 @@ class TreemapChart {
22728
22899
  if (w.config.chart.dropShadow.enabled) {
22729
22900
  const shadow = w.config.chart.dropShadow;
22730
22901
  const filters = new Filters(this.w);
22731
- filters.dropShadow(ret, shadow, i);
22902
+ filters.dropShadow(elSeries, shadow, i);
22732
22903
  }
22733
22904
  const elDataLabelWrap = graphics.group({
22734
22905
  class: "apexcharts-data-labels"
@@ -22822,6 +22993,7 @@ class TreemapChart {
22822
22993
  });
22823
22994
  elRect.node.classList.add("apexcharts-treemap-rect");
22824
22995
  elRect.node.setAttribute("data:key", morphKey(leaf._key));
22996
+ let tileTween = null;
22825
22997
  let fromRect = {
22826
22998
  x: x1 + (x2 - x1) / 2,
22827
22999
  y: y1 + (y2 - y1) / 2,
@@ -22847,7 +23019,7 @@ class TreemapChart {
22847
23019
  if (w.globals.resized) {
22848
23020
  w.globals.animationEnded = true;
22849
23021
  } else {
22850
- this.animateTreemap(
23022
+ tileTween = this.animateTreemap(
22851
23023
  elRect,
22852
23024
  fromRect,
22853
23025
  toRect,
@@ -22858,7 +23030,6 @@ class TreemapChart {
22858
23030
  );
22859
23031
  }
22860
23032
  }
22861
- let tileTween = null;
22862
23033
  let labelFrom = null;
22863
23034
  let prevLook = null;
22864
23035
  if (w.globals.dataChanged) {
@@ -23240,7 +23411,7 @@ class TreemapChart {
23240
23411
  const elGroup = graphics.group({
23241
23412
  class: "apexcharts-treemap-parent",
23242
23413
  "data:depth": depth,
23243
- "data:name": Utils.escapeString(node.name)
23414
+ "data:name": node.name
23244
23415
  });
23245
23416
  const key = morphKey(node._key);
23246
23417
  const morphFrom = this._morphKeyed() ? this.ctx.morphTypeChange.getInitialPathForKey(key) : null;
@@ -23349,7 +23520,7 @@ class TreemapChart {
23349
23520
  if (typeof header.formatter === "function") {
23350
23521
  text = String(
23351
23522
  header.formatter(node.name, {
23352
- value: node.value,
23523
+ value: node._area,
23353
23524
  depth,
23354
23525
  seriesIndex: i,
23355
23526
  node,
@@ -23357,7 +23528,7 @@ class TreemapChart {
23357
23528
  })
23358
23529
  );
23359
23530
  } else if (header.showValue) {
23360
- text = `${text} ${this._formatValue(node.value)}`;
23531
+ text = `${text} ${this._formatValue(node._area, node._si)}`;
23361
23532
  }
23362
23533
  headerText = text;
23363
23534
  const offsetX = Number(header.offsetX) || 0;
@@ -23368,7 +23539,9 @@ class TreemapChart {
23368
23539
  const clipped = graphics.getTextBasedOnMaxWidth({
23369
23540
  text,
23370
23541
  maxWidth,
23371
- fontSize
23542
+ fontSize,
23543
+ fontFamily: chrome.headerFontFamily,
23544
+ fontWeight: chrome.headerFontWeight
23372
23545
  });
23373
23546
  if (clipped) {
23374
23547
  let tx = x1 + pad + offsetX;
@@ -23443,7 +23616,7 @@ class TreemapChart {
23443
23616
  const total = this._drawnTotal();
23444
23617
  const pct = total > 0 ? (node._area / total * 100).toFixed(1) : "0";
23445
23618
  const n = this._countLeaves(node);
23446
- const lead = visibleText && String(visibleText).trim() ? String(visibleText).replace(/\s+/g, " ").trim() : `${node.name}, ${this._formatValue(node._area)}`;
23619
+ const lead = visibleText && String(visibleText).trim() ? String(visibleText).replace(/\s+/g, " ").trim() : `${node.name}, ${this._formatValue(node._area, node._si)}`;
23447
23620
  return `${lead}, ${n} ${n === 1 ? "item" : "items"}, ${pct}% of total`;
23448
23621
  }
23449
23622
  /**
@@ -23462,15 +23635,18 @@ class TreemapChart {
23462
23635
  * @param {string} [visibleText] the header's rendered text, unclipped
23463
23636
  */
23464
23637
  _makeParentAccessible(el, node, chrome, elRect, visibleText) {
23638
+ const a11y = this.w.config.chart.accessibility;
23465
23639
  if (!el || !el.setAttribute) return;
23466
- if (!this._zoomEnabled()) return;
23640
+ if (!a11y.enabled || !a11y.keyboard.enabled || !this._zoomEnabled()) return;
23641
+ const open = this.w.globals.treemapFocusKey === node._key;
23642
+ el.tmKey = node._key;
23467
23643
  el.setAttribute("role", "button");
23468
23644
  el.setAttribute("tabindex", "0");
23469
23645
  el.setAttribute(
23470
23646
  "aria-label",
23471
- `${this._parentLabel(node, visibleText)}. Zoom in`
23647
+ `${this._parentLabel(node, visibleText)}. Zoom ${open ? "out" : "in"}`
23472
23648
  );
23473
- el.setAttribute("aria-expanded", "false");
23649
+ el.setAttribute("aria-expanded", open);
23474
23650
  if (!Environment.isBrowser() || !el.addEventListener) return;
23475
23651
  el.addEventListener("focus", () => {
23476
23652
  elRect.node.setAttribute("stroke", chrome.hoverColor);
@@ -23537,15 +23713,17 @@ class TreemapChart {
23537
23713
  * @returns {boolean}
23538
23714
  */
23539
23715
  _zoomEnabled() {
23716
+ var _a;
23540
23717
  const w = this.w;
23541
23718
  const z = w.config.plotOptions.treemap.zoom;
23542
23719
  if (!z || !z.enabled || !this.showParents) return false;
23543
23720
  const dd = w.config.drilldown;
23544
- if (this.ctx.drilldown && dd && dd.enabled && Array.isArray(dd.series) && dd.series.length) {
23545
- if (!this._warnedZoomConflict) {
23546
- this._warnedZoomConflict = true;
23721
+ const d = this.ctx.drilldown;
23722
+ if (d && dd && dd.enabled && (((_a = dd.series) == null ? void 0 : _a.length) || dd.onDrillDown)) {
23723
+ if (!d.zoomWarned) {
23724
+ d.zoomWarned = true;
23547
23725
  console.warn(
23548
- "ApexCharts treemap: `plotOptions.treemap.zoom` and the drilldown feature both navigate the hierarchy, so zoom is ignored here. Drop `drilldown.series` to zoom a nested treemap instead."
23726
+ "ApexCharts treemap: zoom is ignored while drilldown is active (plotOptions.treemap.zoom vs drilldown series or onDrillDown)."
23549
23727
  );
23550
23728
  }
23551
23729
  return false;
@@ -23555,8 +23733,8 @@ class TreemapChart {
23555
23733
  /**
23556
23734
  * The focused branch for this render, looked up by the key stashed on the
23557
23735
  * last click. Keys are rebuilt identically from the same data, so the focus
23558
- * survives a re-render; a key that no longer resolves (the data changed under
23559
- * it) simply falls back to the whole tree.
23736
+ * survives a re-render; a key that no longer resolves, or a branch left with
23737
+ * nothing to draw (the data changed under it), falls back to the whole tree.
23560
23738
  * @param {any[]} drawn
23561
23739
  * @returns {any}
23562
23740
  */
@@ -23573,7 +23751,11 @@ class TreemapChart {
23573
23751
  if (node.children) node.children.forEach(walk);
23574
23752
  };
23575
23753
  drawn.forEach(walk);
23576
- return found && found.children && found.children.length ? found : null;
23754
+ if (found && found.children && found.children.length && this._subtreeArea(found) > 0) {
23755
+ return found;
23756
+ }
23757
+ this.w.globals.treemapFocusKey = null;
23758
+ return null;
23577
23759
  }
23578
23760
  /**
23579
23761
  * @param {any} node
@@ -23586,28 +23768,7 @@ class TreemapChart {
23586
23768
  const w = this.w;
23587
23769
  if (!node || !node.children || !node.children.length) return;
23588
23770
  const next = w.globals.treemapFocusKey === node._key ? null : node._key;
23589
- const done = this._refocus(next);
23590
- if (!restoreFocus || !done || typeof done.then !== "function") return;
23591
- done.then(() => {
23592
- if (!Environment.isBrowser()) return;
23593
- const crumb = (
23594
- /** @type {any} */
23595
- w.dom.baseEl.querySelector(
23596
- ".apexcharts-breadcrumb .apexcharts-breadcrumb-item"
23597
- )
23598
- );
23599
- if (crumb && crumb.focus) {
23600
- crumb.focus();
23601
- return;
23602
- }
23603
- const header = (
23604
- /** @type {any} */
23605
- w.dom.baseEl.querySelector(
23606
- ".apexcharts-treemap-parent-header[tabindex]"
23607
- )
23608
- );
23609
- if (header && header.focus) header.focus();
23610
- });
23771
+ this._refocus(next, restoreFocus);
23611
23772
  }
23612
23773
  /**
23613
23774
  * Re-render focused on another branch (null: the whole tree).
@@ -23618,22 +23779,34 @@ class TreemapChart {
23618
23779
  * left, which replayed the mount animation (every tile growing from
23619
23780
  * nothing) or snapped, while the containers, headers and labels jumped.
23620
23781
  * @param {string | null} next
23621
- * @returns {any} the update's promise
23782
+ * @param {boolean} [restoreFocus] see _zoomTo
23622
23783
  */
23623
- _refocus(next) {
23624
- var _a;
23784
+ _refocus(next, restoreFocus) {
23625
23785
  const w = this.w;
23626
23786
  const gl = w.globals;
23787
+ const from = gl.treemapFocusKey;
23627
23788
  const anim = w.config.chart.animations;
23628
23789
  const animate = !!(anim.enabled && anim.dynamicAnimation.enabled);
23629
- gl.treemapZoom = animate && Environment.isBrowser() ? { from: (_a = gl.treemapFocusKey) != null ? _a : null, to: next } : null;
23790
+ gl.treemapZoom = animate && Environment.isBrowser() ? { from: from != null ? from : null, to: next } : null;
23630
23791
  gl.treemapFocusKey = next;
23631
23792
  this._hideParentTooltip();
23632
23793
  gl.shouldAnimate = animate;
23633
23794
  gl.resized = true;
23634
23795
  gl.dataChanged = true;
23635
23796
  if (gl.treemapZoom) this.ctx.series.getPreviousPaths();
23636
- return this.ctx.update();
23797
+ const done = this.ctx.update();
23798
+ if (restoreFocus) {
23799
+ done.then(() => {
23800
+ const b = w.dom.baseEl;
23801
+ const heads = (
23802
+ /** @type {any[]} */
23803
+ Array.from(
23804
+ b.querySelectorAll(".apexcharts-treemap-parent-header[tabindex]")
23805
+ )
23806
+ );
23807
+ (b.querySelector(".apexcharts-breadcrumb-item") || heads.find((h) => h.tmKey === from) || heads[0] || b).focus();
23808
+ });
23809
+ }
23637
23810
  }
23638
23811
  /**
23639
23812
  * A zoom reframes one tree, so it moves like a camera: one map takes the
@@ -23945,8 +24118,9 @@ class TreemapChart {
23945
24118
  crumbs: [{ label: "All", data: null }].concat(
23946
24119
  chain.map((n) => ({ label: n.name, data: n }))
23947
24120
  ),
23948
- onNavigate: (_i, crumb) => {
23949
- this._refocus(crumb.data ? crumb.data._key : null);
24121
+ // A keyboard click (detail 0) keeps focus in the chart.
24122
+ onNavigate: (_i, crumb, e) => {
24123
+ this._refocus(crumb.data ? crumb.data._key : null, !e.detail);
23950
24124
  }
23951
24125
  });
23952
24126
  if (!nav) return;
@@ -23995,7 +24169,7 @@ class TreemapChart {
23995
24169
  const t = this._tip();
23996
24170
  if (!t) return;
23997
24171
  const total = this._drawnTotal();
23998
- const parentVal = node._parent ? node._parent._area : total;
24172
+ const parentVal = node._parent ? this._subtreeArea(node._parent) : total;
23999
24173
  const pctTotal = total > 0 ? (node._area / total * 100).toFixed(1) : "0.0";
24000
24174
  const pctParent = parentVal > 0 ? (node._area / parentVal * 100).toFixed(1) : pctTotal;
24001
24175
  const cfg = this.w.config.plotOptions.treemap.parents;
@@ -24016,10 +24190,9 @@ class TreemapChart {
24016
24190
  } else {
24017
24191
  const marker = this._parentChrome(node.depth || 0).headerBg;
24018
24192
  const groupBg = w.config.tooltip.fillSeriesColor ? `background-color:${marker};` : "";
24019
- html = `<div class="apexcharts-tooltip-series-group apexcharts-active" style="display:flex;${groupBg}"><div class="apexcharts-tooltip-text"><div class="apexcharts-tooltip-y-group"><span class="apexcharts-tooltip-text-y-label">${Utils.escapeString(
24020
- node.name
24021
- )}: </span><span class="apexcharts-tooltip-text-y-value">${this._formatValue(
24022
- node._area
24193
+ html = `<div class="apexcharts-tooltip-series-group apexcharts-active" style="display:flex;${groupBg}"><div class="apexcharts-tooltip-text"><div class="apexcharts-tooltip-y-group"><span class="apexcharts-tooltip-text-y-label">${String(node.name).replace(/&/g, "&amp;").replace(/</g, "&lt;")}: </span><span class="apexcharts-tooltip-text-y-value">${this._formatValue(
24194
+ node._area,
24195
+ node._si
24023
24196
  )}</span></div><div class="apexcharts-tooltip-y-group"><span class="apexcharts-tooltip-text-y-label">${leafCount} items, </span><span class="apexcharts-tooltip-text-y-value">${pctParent}% of parent, ${pctTotal}% of total</span></div></div></div>`;
24024
24197
  }
24025
24198
  t.innerHTML = html;
@@ -24115,17 +24288,21 @@ class TreemapChart {
24115
24288
  }
24116
24289
  /**
24117
24290
  * Format an aggregate the way the chart formats its own y values, so a
24118
- * parent's total reads like the tiles it contains.
24291
+ * parent's total reads like the tiles it contains. A branch is no data
24292
+ * point, so dataPointIndex is -1.
24119
24293
  * @param {number} v
24294
+ * @param {number} [si] the branch's series index
24120
24295
  * @returns {string}
24121
24296
  */
24122
- _formatValue(v) {
24297
+ _formatValue(v, si) {
24123
24298
  var _a, _b, _c, _d, _e;
24124
24299
  const w = this.w;
24125
24300
  const fmt = ((_b = (_a = w.config.tooltip) == null ? void 0 : _a.y) == null ? void 0 : _b.formatter) || ((_e = (_d = (_c = w.config.yaxis) == null ? void 0 : _c[0]) == null ? void 0 : _d.labels) == null ? void 0 : _e.formatter);
24126
24301
  if (typeof fmt === "function") {
24127
24302
  try {
24128
- return String(fmt(v, { seriesIndex: 0, dataPointIndex: 0, w }));
24303
+ return String(
24304
+ fmt(v, { seriesIndex: si || 0, dataPointIndex: -1, w })
24305
+ );
24129
24306
  } catch (_) {
24130
24307
  }
24131
24308
  }
@@ -24206,7 +24383,7 @@ class TreemapChart {
24206
24383
  */
24207
24384
  rotateToFitLabel(elText, fontSize, text, x1, y1, x2, y2) {
24208
24385
  const graphics = new Graphics(this.w);
24209
- const textRect = graphics.getTextRects(text, String(fontSize));
24386
+ const textRect = this._labelRect(graphics, text, fontSize);
24210
24387
  if (textRect.width + this.w.config.stroke.width + 5 > x2 - x1 && textRect.width <= y2 - y1) {
24211
24388
  const labelRotatingCenter = graphics.rotateAroundCenter(elText.node);
24212
24389
  elText.node.setAttribute(
@@ -24215,6 +24392,24 @@ class TreemapChart {
24215
24392
  );
24216
24393
  }
24217
24394
  }
24395
+ /**
24396
+ * A tile label's box, measured at the family and weight it is drawn at
24397
+ * (bold is wider than the default regular).
24398
+ * @param {Graphics} graphics
24399
+ * @param {string} text
24400
+ * @param {string | number} fontSize
24401
+ */
24402
+ _labelRect(graphics, text, fontSize) {
24403
+ const st = this.w.config.dataLabels.style;
24404
+ return graphics.getTextRects(
24405
+ text,
24406
+ String(fontSize),
24407
+ st.fontFamily,
24408
+ "",
24409
+ true,
24410
+ st.fontWeight
24411
+ );
24412
+ }
24218
24413
  // This is an alternative label formatting method that uses a
24219
24414
  // consistent font size, and trims the edge of long labels
24220
24415
  /**
@@ -24227,13 +24422,13 @@ class TreemapChart {
24227
24422
  */
24228
24423
  truncateLabels(text, fontSize, x1, y1, x2, y2) {
24229
24424
  const graphics = new Graphics(this.w);
24230
- const textRect = graphics.getTextRects(text, String(fontSize));
24425
+ const textRect = this._labelRect(graphics, text, fontSize);
24231
24426
  const labelMaxWidth = textRect.width + this.w.config.stroke.width + 5 > x2 - x1 && y2 - y1 > x2 - x1 ? y2 - y1 : x2 - x1;
24232
- const truncatedText = graphics.getTextBasedOnMaxWidth({
24427
+ const truncatedText = graphics.getTextBasedOnMaxWidth(__spreadProps(__spreadValues({}, this.w.config.dataLabels.style), {
24233
24428
  text,
24234
24429
  maxWidth: labelMaxWidth,
24235
24430
  fontSize
24236
- });
24431
+ }));
24237
24432
  if (text.length !== truncatedText.length && labelMaxWidth / fontSize < 5) {
24238
24433
  return "";
24239
24434
  } else {