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
@@ -111,17 +111,35 @@ class Line {
111
111
  // We call draw() for each series group
112
112
  this.prevSeriesY = []
113
113
  this.prevSeriesYByX = new Map()
114
+ // Ragged stacked x: the sorted union of the shown series' x, so each edge
115
+ // can pass through the stack at an x it lacks (see _iterateOverDataPoints)
116
+ /** @type {any[] | null} */
117
+ this._stackXs = null
118
+ if (w.config.chart.stacked && w.axisFlags.isXNumeric) {
119
+ const xs = series
120
+ .map((_, i) =>
121
+ w.globals.comboCharts ? /** @type {any} */ (seriesIndex)[i] : i,
122
+ )
123
+ .filter((ri) => !this._hidden(ri))
124
+ .map((ri) => w.seriesData.seriesX[ri] || [])
125
+ if (
126
+ xs.some(
127
+ (a) => a.length !== xs[0].length || a.some((v, k) => v !== xs[0][k]),
128
+ )
129
+ ) {
130
+ this._stackXs = [...new Set(xs.flat())].sort((a, b) => a - b)
131
+ }
132
+ }
114
133
 
115
134
  // push all series in an array, so we can draw in reverse order
116
135
  // (for stacked charts)
117
136
  const allSeries = []
118
137
 
119
138
  for (let i = 0; i < series.length; i++) {
120
- series = this.lineHelpers.sameValueSeriesFix(i, series)
121
-
122
139
  const realIndex = w.globals.comboCharts
123
140
  ? /** @type {any} */ (seriesIndex)[i]
124
141
  : i
142
+ series = this.lineHelpers.sameValueSeriesFix(i, series, realIndex)
125
143
  const translationsIndex = this.yRatio.length > 1 ? realIndex : 0
126
144
 
127
145
  // A series hidden from the legend is drawn flat on the baseline instead
@@ -386,12 +404,7 @@ class Line {
386
404
  // (LengthTransition.shrinkCollapsingMarkers).
387
405
  if (w.config.chart.stacked || this.pointsChart) return null
388
406
  if (!Array.isArray(series[i]) || series[i].length !== 0) return null
389
- if (
390
- gl.collapsedSeriesIndices.indexOf(realIndex) === -1 &&
391
- gl.ancillaryCollapsedSeriesIndices.indexOf(realIndex) === -1
392
- ) {
393
- return null
394
- }
407
+ if (!this._hidden(realIndex)) return null
395
408
  const n = w.axisFlags.isXNumeric
396
409
  ? (w.seriesData.seriesX[realIndex] || []).length
397
410
  : gl.dataPoints
@@ -573,6 +586,15 @@ class Line {
573
586
  return this.prevSeriesYByX.get(key)
574
587
  }
575
588
 
589
+ /** @param {number} ri */
590
+ _hidden(ri) {
591
+ const g = this.w.globals
592
+ return (
593
+ g.collapsedSeriesIndices.indexOf(ri) > -1 ||
594
+ g.ancillaryCollapsedSeriesIndices.indexOf(ri) > -1
595
+ )
596
+ }
597
+
576
598
  /**
577
599
  * Fold a drawn series into the running stack top, so the next series can find
578
600
  * its baseline by x (#4886).
@@ -588,19 +610,19 @@ class Line {
588
610
  * correct if that representation ever changes.
589
611
  * @param {number} realIndex
590
612
  * @param {any[]} yArrj
613
+ * @param {any[]} [row] the drawn row, if not the series' own (a part)
591
614
  */
592
- _recordStackTops(realIndex, yArrj) {
615
+ _recordStackTops(
616
+ realIndex,
617
+ yArrj,
618
+ row = this.w.seriesData.series[realIndex],
619
+ ) {
593
620
  const w = this.w
594
621
  // Only stacked series read the map back (stackTopAt), and the walk costs a
595
622
  // Map write per point: 4.7ms per update on a 50k line that is not stacked.
596
623
  if (!w.config.chart.stacked) return
597
624
  if (!Array.isArray(yArrj)) return
598
- if (
599
- w.globals.collapsedSeriesIndices.indexOf(realIndex) !== -1 ||
600
- w.globals.ancillaryCollapsedSeriesIndices.indexOf(realIndex) !== -1
601
- ) {
602
- return
603
- }
625
+ if (this._hidden(realIndex)) return
604
626
 
605
627
  for (let j = 0; j < yArrj.length; j++) {
606
628
  const key = this._stackKey(realIndex, j)
@@ -608,9 +630,10 @@ class Line {
608
630
  // A null y is a gap in this series, not a new top: leave whatever the
609
631
  // series below contributed. The ordinal path used to hand the null
610
632
  // straight to the next series as its baseline, where it coerced to 0 and
611
- // put that point at the top of the plot.
633
+ // put that point at the top of the plot. Decided from the datum: the
634
+ // straight and step curves park a null at getY(minY), a real number.
612
635
  const y = yArrj[j]
613
- if (!Utils.isNumber(y)) continue
636
+ if (!Utils.isNumber(y) || row?.[j] == null) continue
614
637
  this.prevSeriesYByX.set(key, y)
615
638
  }
616
639
  }
@@ -665,10 +688,14 @@ class Line {
665
688
 
666
689
  const forecast = w.config.forecastDataPoints
667
690
  if (forecast.count > 0 && type !== 'rangeArea') {
668
- const forecastCutoff =
669
- w.globals.seriesXvalues[realIndex][
670
- w.globals.seriesXvalues[realIndex].length - forecast.count - 1
671
- ]
691
+ // From the axis, not seriesXvalues: that holds null for a null value,
692
+ // which put the cutoff at 0 and dashed the whole series.
693
+ const ci = paths.xArrj.length - forecast.count - 1
694
+ const forecastCutoff = w.axisFlags.isXNumeric
695
+ ? (w.seriesData.seriesX[realIndex][ci] - w.globals.minX) / this.xRatio
696
+ : w.globals.padHorizontal +
697
+ this.categoryAxisCorrection +
698
+ ci * this.xDivision
672
699
  const elForecastMask = graphics.drawRect(
673
700
  forecastCutoff,
674
701
  0,
@@ -815,7 +842,7 @@ class Line {
815
842
  scrollMorph: !!streamScroll,
816
843
  stroke: 'none',
817
844
  strokeWidth: 0,
818
- strokeLineCap: null,
845
+ strokeLinecap: null,
819
846
  fill: pathFill,
820
847
  })
821
848
  this.elSeries.add(renderedPath)
@@ -866,7 +893,7 @@ class Line {
866
893
  scrollMorph: !!streamScroll,
867
894
  stroke: lineFill,
868
895
  strokeWidth: this.strokeWidth,
869
- strokeLineCap: w.config.stroke.lineCap,
896
+ strokeLinecap: w.config.stroke.lineCap,
870
897
  fill: type === 'rangeArea' ? pathFill : 'none',
871
898
  }
872
899
  const renderedPath = emit.renderPaths(linePathCommonOpts)
@@ -1018,6 +1045,15 @@ class Line {
1018
1045
  if (fast) return fast
1019
1046
  }
1020
1047
 
1048
+ // Between two of its points a ragged stacked series contributes 0 at any
1049
+ // x it lacks, so its edge passes through the stack top there (the axis
1050
+ // when nothing below has that x), or the layers cross. midsAt[j] holds
1051
+ // those vertices before point j.
1052
+ const ks = stackSeries ? this._stackXs : null
1053
+ let kp = 0
1054
+ /** @type {any[][]} */
1055
+ const midsAt = []
1056
+
1021
1057
  for (let j = 0; j < iterations; j++) {
1022
1058
  if (series[i].length === 0) break
1023
1059
 
@@ -1025,12 +1061,24 @@ class Line {
1025
1061
  typeof series[i][j + 1] === 'undefined' || series[i][j + 1] === null
1026
1062
 
1027
1063
  if (w.axisFlags.isXNumeric) {
1028
- let sX = w.seriesData.seriesX[realIndex][j + 1]
1029
- if (typeof w.seriesData.seriesX[realIndex][j + 1] === 'undefined') {
1064
+ const sxs = w.seriesData.seriesX[realIndex]
1065
+ let sX = sxs[j + 1]
1066
+ if (typeof sX === 'undefined') {
1030
1067
  /* fix #374 */
1031
- sX = w.seriesData.seriesX[realIndex][iterations - 1]
1068
+ sX = sxs[iterations - 1]
1032
1069
  }
1033
1070
  x = (sX - w.globals.minX) / this.xRatio
1071
+ if (ks) {
1072
+ const m = []
1073
+ while (ks[kp] <= sxs[j]) kp++
1074
+ while (ks[kp] < sX) {
1075
+ m.push([
1076
+ (ks[kp] - w.globals.minX) / this.xRatio,
1077
+ this.prevSeriesYByX.get(ks[kp++]) ?? this.zeroY,
1078
+ ])
1079
+ }
1080
+ if (m.length) midsAt[j + 1] = m
1081
+ }
1034
1082
  } else {
1035
1083
  x = x + this.xDivision
1036
1084
  }
@@ -1078,12 +1126,7 @@ class Line {
1078
1126
  const prevIndex = (pi) => {
1079
1127
  for (let pii = pi; pii >= 0; pii--) {
1080
1128
  const ri = seriesIndex?.[pii] ?? pii
1081
- if (
1082
- w.globals.collapsedSeriesIndices.indexOf(ri) === -1 &&
1083
- w.globals.ancillaryCollapsedSeriesIndices.indexOf(ri) === -1
1084
- ) {
1085
- return pii
1086
- }
1129
+ if (!this._hidden(ri)) return pii
1087
1130
  }
1088
1131
  return -1
1089
1132
  }
@@ -1163,6 +1206,7 @@ class Line {
1163
1206
  j,
1164
1207
  x,
1165
1208
  y,
1209
+ midsAt,
1166
1210
  y2,
1167
1211
  xArrj,
1168
1212
  yArrj,
@@ -1469,7 +1513,7 @@ class Line {
1469
1513
  }
1470
1514
  }
1471
1515
 
1472
- /** @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 */
1516
+ /** @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 */
1473
1517
  _createPaths({
1474
1518
  type,
1475
1519
  series,
@@ -1477,6 +1521,7 @@ class Line {
1477
1521
  j,
1478
1522
  x,
1479
1523
  y,
1524
+ midsAt,
1480
1525
  xArrj,
1481
1526
  yArrj,
1482
1527
  y2,
@@ -1496,6 +1541,15 @@ class Line {
1496
1541
  const areaBottomY = this.areaBottomY
1497
1542
  const rangeArea = type === 'rangeArea'
1498
1543
  const isLowerRangeAreaPath = type === 'rangeArea' && isRangeStart
1544
+ const mids = midsAt[j + 1]
1545
+ // one segment per vertex, through any stack tops in between
1546
+ /** @param {(...p: number[]) => string} f */
1547
+ const via = (f) =>
1548
+ mids
1549
+ ? [...mids, [x, y]]
1550
+ .map(([bx, by], k, a) => f(...(k ? a[k - 1] : [pX, pY]), bx, by))
1551
+ .join('')
1552
+ : f(pX, pY, x, y)
1499
1553
 
1500
1554
  switch (curve) {
1501
1555
  case 'monotoneCubic': {
@@ -1577,8 +1631,20 @@ class Line {
1577
1631
  case 2: {
1578
1632
  // Interpolate the full series with nulls excluded then extract the
1579
1633
  // null delimited segments with interpolated points included.
1580
- const _xAj = isRangeStart ? xArrj : xArrj.slice().reverse()
1581
- const _yAj = isRangeStart ? yAj : yAj.slice().reverse()
1634
+ let _xAj = isRangeStart ? xArrj : xArrj.slice().reverse()
1635
+ let _yAj = isRangeStart ? yAj : yAj.slice().reverse()
1636
+ if (midsAt.length && !rangeArea) {
1637
+ // fit through the stack tops between points too (see via)
1638
+ /** @type {any[]} */ const P = []
1639
+ _xAj.forEach((/** @type {any} */ v, /** @type {number} */ k) => {
1640
+ if (_yAj[k] !== null && _yAj[k - 1] != null && midsAt[k]) {
1641
+ P.push(...midsAt[k])
1642
+ }
1643
+ P.push([v, _yAj[k]])
1644
+ })
1645
+ _xAj = P.map((p) => p[0])
1646
+ _yAj = P.map((p) => p[1])
1647
+ }
1582
1648
 
1583
1649
  const smoothInputs = getSmoothInputs(_xAj, _yAj)
1584
1650
  const points =
@@ -1664,7 +1730,16 @@ class Line {
1664
1730
  break
1665
1731
  }
1666
1732
  case 'smooth': {
1667
- const length = (x - pX) * 0.35
1733
+ /**
1734
+ * @param {number} ax
1735
+ * @param {number} ay
1736
+ * @param {number} bx
1737
+ * @param {number} by
1738
+ */
1739
+ const toPoint = (ax, ay, bx, by) => {
1740
+ const l = (bx - ax) * 0.35
1741
+ return graphics.curve(ax + l, ay, bx - l, by, bx, by)
1742
+ }
1668
1743
  if (series[i][j] === null) {
1669
1744
  pathState = 0
1670
1745
  } else {
@@ -1692,7 +1767,7 @@ class Line {
1692
1767
  }
1693
1768
  pathState = 1
1694
1769
  if (j < series[i].length - 2) {
1695
- const p = graphics.curve(pX + length, pY, x - length, y, x, y)
1770
+ const p = via(toPoint)
1696
1771
  linePath += p
1697
1772
  areaPath += p
1698
1773
  break
@@ -1715,7 +1790,7 @@ class Line {
1715
1790
  areaPaths.push(areaPath)
1716
1791
  pathState = -1
1717
1792
  } else {
1718
- const p = graphics.curve(pX + length, pY, x - length, y, x, y)
1793
+ const p = via(toPoint)
1719
1794
  linePath += p
1720
1795
  areaPath += p
1721
1796
  if (j >= series[i].length - 2) {
@@ -1744,11 +1819,12 @@ class Line {
1744
1819
  }
1745
1820
  default: {
1746
1821
  /**
1747
- * @param {string} curve
1822
+ * @param {number} _ax
1823
+ * @param {number} _ay
1748
1824
  * @param {number} x
1749
1825
  * @param {number} y
1750
1826
  */
1751
- const pathToPoint = (curve, x, y) => {
1827
+ const pathToPoint = (_ax, _ay, x, y) => {
1752
1828
  /** @type {string} */ let path = ''
1753
1829
  switch (curve) {
1754
1830
  case 'stepline':
@@ -1790,7 +1866,7 @@ class Line {
1790
1866
  }
1791
1867
  pathState = 1
1792
1868
  if (j < series[i].length - 2) {
1793
- const p = pathToPoint(curve, x, y)
1869
+ const p = via(pathToPoint)
1794
1870
  linePath += p
1795
1871
  areaPath += p
1796
1872
  break
@@ -1813,7 +1889,7 @@ class Line {
1813
1889
  areaPaths.push(areaPath)
1814
1890
  pathState = -1
1815
1891
  } else {
1816
- const p = pathToPoint(curve, x, y)
1892
+ const p = via(pathToPoint)
1817
1893
  linePath += p
1818
1894
  areaPath += p
1819
1895
  if (j >= series[i].length - 2) {
@@ -206,7 +206,8 @@ class Radar {
206
206
  */
207
207
  s.forEach((/** @type {any} */ dv, /** @type {any} */ j) => {
208
208
  const range = Math.abs(this.maxValue - this.minValue)
209
- dv = dv - this.minValue
209
+ // below yaxis.min sits at the centre, not on the opposite spoke
210
+ dv = Math.max(0, dv - this.minValue)
210
211
 
211
212
  if (this.isLog) {
212
213
  dv = this.coreUtils.getLogVal(this.logBase, dv, 0)
@@ -253,7 +254,7 @@ class Radar {
253
254
  shouldClipToGrid: false,
254
255
  bindEventsOnPaths: false,
255
256
  stroke: w.globals.stroke.colors[i],
256
- strokeLineCap: w.config.stroke.lineCap,
257
+ strokeLinecap: w.config.stroke.lineCap,
257
258
  }
258
259
 
259
260
  let pathFrom = null
@@ -514,6 +515,7 @@ class Radar {
514
515
  const w = this.w
515
516
 
516
517
  const xaxisLabelsConfig = w.config.xaxis.labels
518
+ const lc = xaxisLabelsConfig.style.colors
517
519
  const elXAxisWrap = this.graphics.group({
518
520
  class: 'apexcharts-xaxis',
519
521
  })
@@ -551,11 +553,7 @@ class Radar {
551
553
  j: i,
552
554
  parent: elXAxisWrap,
553
555
  className: 'apexcharts-xaxis-label',
554
- color:
555
- Array.isArray(xaxisLabelsConfig.style.colors) &&
556
- xaxisLabelsConfig.style.colors[i]
557
- ? xaxisLabelsConfig.style.colors[i]
558
- : '#a8a8a8',
556
+ color: (Array.isArray(lc) ? lc[i] : lc) || '#a8a8a8',
559
557
  dataLabelsConfig: {
560
558
  textAnchor: textPos.textAnchor,
561
559
  dropShadow: { enabled: false },
@@ -4,8 +4,8 @@ import Graphics from '../modules/Graphics'
4
4
  import Series from '../modules/Series'
5
5
  import Utils from '../utils/Utils'
6
6
  import {
7
- datumKey,
8
7
  renderBarExitGhosts,
8
+ uniquifyKeys,
9
9
  } from '../modules/animations/LengthTransition'
10
10
 
11
11
  /**
@@ -29,7 +29,7 @@ class RangeBar extends Bar {
29
29
  this.seriesRangeStart = w.rangeData.seriesRangeStart
30
30
  this.seriesRangeEnd = w.rangeData.seriesRangeEnd
31
31
 
32
- this.barHelpers.initVariables(series)
32
+ this.barHelpers.initVariables(series, seriesIndex)
33
33
 
34
34
  const ret = graphics.group({
35
35
  class: 'apexcharts-rangebar-series apexcharts-plot-series',
@@ -58,6 +58,10 @@ class RangeBar extends Bar {
58
58
  }
59
59
 
60
60
  const translationsIndex = this.setSeriesAxis(realIndex)
61
+ // a time axis's labels never reverse, so its bars may not either
62
+ if (this.isHorizontal && w.labelData.timescaleLabels.length) {
63
+ this.isReversed = false
64
+ }
61
65
 
62
66
  const initPositions = this.barHelpers.initialPositions(realIndex)
63
67
  const {
@@ -66,8 +70,6 @@ class RangeBar extends Bar {
66
70
  x: initX,
67
71
  zeroH, // zeroH is the baseline where 0 meets y axis
68
72
  } = initPositions
69
- let barWidth = initPositions.barWidth ?? 0
70
- let barHeight = initPositions.barHeight ?? 0
71
73
  const yDivision = initPositions.yDivision ?? 0
72
74
  const xDivision = initPositions.xDivision ?? 0
73
75
 
@@ -84,11 +86,16 @@ class RangeBar extends Bar {
84
86
  class: 'apexcharts-rangebar-goals-markers',
85
87
  })
86
88
 
89
+ const data = /** @type {any} */ (w.config.series[realIndex]).data
90
+
87
91
  for (let j = 0; j < w.globals.dataPoints; j++) {
88
92
  const strokeWidth = this.barHelpers.getStrokeWidth(i, j, realIndex)
93
+ // per datum: an overlap row shrinks only its own bars
94
+ let barWidth = initPositions.barWidth ?? 0
95
+ let barHeight = initPositions.barHeight ?? 0
89
96
 
90
- const y1 = this.seriesRangeStart[i][j]
91
- const y2 = this.seriesRangeEnd[i][j]
97
+ const y1 = this.seriesRangeStart[realIndex][j]
98
+ const y2 = this.seriesRangeEnd[realIndex][j]
92
99
 
93
100
  let paths = /** @type {any} */ (null)
94
101
  let barXPosition = null
@@ -100,10 +107,7 @@ class RangeBar extends Bar {
100
107
  seriesLen = 1
101
108
  }
102
109
 
103
- if (
104
- typeof /** @type {Record<string,any>} */ (w.config.series[i]).data?.[j] ===
105
- 'undefined'
106
- ) {
110
+ if (typeof data?.[j] === 'undefined') {
107
111
  // no data exists for further indexes, hence we need to get out the innr loop.
108
112
  // As we are iterating over total datapoints, there is a possiblity the series might not have data for j index
109
113
  break
@@ -114,9 +118,9 @@ class RangeBar extends Bar {
114
118
 
115
119
  const srty = (yDivision - barHeight * seriesLen) / 2
116
120
 
117
- if (/** @type {Record<string,any>} */ (w.config.series[i]).data?.[j]?.x) {
121
+ if (data[j]?.x != null) {
118
122
  const positions = this.detectOverlappingBars({
119
- i,
123
+ i: realIndex,
120
124
  j,
121
125
  barYPosition,
122
126
  srty,
@@ -144,7 +148,8 @@ class RangeBar extends Bar {
144
148
  } else {
145
149
  if (w.axisFlags.isXNumeric) {
146
150
  x =
147
- (w.seriesData.seriesX[i][j] - w.globals.minX) / this.xRatio -
151
+ (w.seriesData.seriesX[realIndex][j] - w.globals.minX) /
152
+ this.xRatio -
148
153
  barWidth / 2
149
154
  }
150
155
 
@@ -152,9 +157,9 @@ class RangeBar extends Bar {
152
157
 
153
158
  const srtx = (xDivision - barWidth * seriesLen) / 2
154
159
 
155
- if (/** @type {Record<string,any>} */ (w.config.series[i]).data?.[j]?.x) {
160
+ if (data[j]?.x != null) {
156
161
  const positions = this.detectOverlappingBars({
157
- i,
162
+ i: realIndex,
158
163
  j,
159
164
  barXPosition,
160
165
  srtx,
@@ -177,10 +182,11 @@ class RangeBar extends Bar {
177
182
  })
178
183
 
179
184
  barHeight = paths.barHeight
185
+ barXPosition = paths.barXPosition
180
186
  }
181
187
 
182
188
  const barGoalLine = this.barHelpers.drawGoalLine({
183
- barXPosition: paths.barXPosition,
189
+ barXPosition,
184
190
  barYPosition,
185
191
  goalX: paths.goalX,
186
192
  goalY: paths.goalY,
@@ -236,16 +242,11 @@ class RangeBar extends Bar {
236
242
  // overrides draw() and never made this call, so a series hidden from the
237
243
  // legend (no datums left) dropped every bar on the click.
238
244
  if (w.globals.previousPaths.length > 0) {
239
- const data = /** @type {Record<string,any>} */ (w.config.series[i]).data || []
240
- const newKeys = []
241
- for (let j = 0; j < data.length; j++) {
242
- newKeys.push(datumKey(w, realIndex, j))
243
- }
244
245
  renderBarExitGhosts({
245
246
  w,
246
247
  elSeries,
247
248
  record: this._prevRecord(realIndex),
248
- newKeys,
249
+ newKeys: this._keys(realIndex),
249
250
  isHorizontal: this.isHorizontal,
250
251
  speed: w.config.chart.animations.dynamicAnimation.speed,
251
252
  })
@@ -308,18 +309,11 @@ class RangeBar extends Bar {
308
309
 
309
310
  if (overlaps.indexOf(rangeName) > -1) {
310
311
  barHeight = initPositions.barHeight / overlaps.length
311
-
312
- barYPosition =
313
- barHeight * this.visibleI +
314
- (yDivision * (100 - parseInt(this.barOptions.barHeight, 10))) /
315
- 100 /
316
- 2 +
317
- barHeight * (this.visibleI + overlaps.indexOf(rangeName)) +
318
- yDivision * rowIndex
312
+ barYPosition += barHeight * overlaps.indexOf(rangeName)
319
313
  }
320
314
  }
321
315
  } else {
322
- if (rowIndex > -1 && !w.labelData.timescaleLabels.length) {
316
+ if (rowIndex > -1 && !w.axisFlags.isXNumeric) {
323
317
  if (w.config.plotOptions.bar.rangeBarGroupRows) {
324
318
  barXPosition = srtx + xDivision * rowIndex
325
319
  } else {
@@ -335,14 +329,7 @@ class RangeBar extends Bar {
335
329
 
336
330
  if (overlaps.indexOf(rangeName) > -1) {
337
331
  barWidth = initPositions.barWidth / overlaps.length
338
-
339
- barXPosition =
340
- barWidth * this.visibleI +
341
- (xDivision * (100 - parseInt(this.barOptions.barWidth, 10))) /
342
- 100 /
343
- 2 +
344
- barWidth * (this.visibleI + overlaps.indexOf(rangeName)) +
345
- xDivision * rowIndex
332
+ barXPosition += barWidth * overlaps.indexOf(rangeName)
346
333
  }
347
334
  }
348
335
  }
@@ -368,7 +355,7 @@ class RangeBar extends Bar {
368
355
 
369
356
  const { i, j, realIndex, translationsIndex } = indexes
370
357
 
371
- const yRatio = this.yRatio[translationsIndex]
358
+ const yRatio = this.yRatio[translationsIndex] * (this.isReversed ? -1 : 1)
372
359
 
373
360
  const range = this.getRangeValue(realIndex, j)
374
361
 
@@ -381,7 +368,7 @@ class RangeBar extends Bar {
381
368
  )
382
369
 
383
370
  if (!hasValue) {
384
- y1 = zeroH
371
+ y1 = y2 = zeroH
385
372
  } else {
386
373
  y1 = zeroH - y1 / yRatio
387
374
  y2 = zeroH - y2 / yRatio
@@ -448,6 +435,22 @@ class RangeBar extends Bar {
448
435
  }
449
436
  }
450
437
 
438
+ /**
439
+ * Timeline datums key by their own row, not by the j-th label: a row can
440
+ * hold several bars, so labels[j] names some other datum's row.
441
+ * @param {number} realIndex
442
+ * @returns {string[]}
443
+ */
444
+ _keys(realIndex) {
445
+ const c = (/** @type {any} */ (this)._keyCache ||= {})
446
+ const data = /** @type {any} */ (this.w.config.series[realIndex]).data
447
+ return (c[realIndex] ||= uniquifyKeys(
448
+ (data || []).map(
449
+ (/** @type {any} */ d, /** @type {number} */ j) => 'c:' + (d?.x ?? j),
450
+ ),
451
+ ))
452
+ }
453
+
451
454
  /**
452
455
  * @param {number} val
453
456
  */
@@ -479,8 +482,9 @@ class RangeBar extends Bar {
479
482
 
480
483
  const { realIndex, j } = indexes
481
484
 
482
- const x1 = this.preventBarOverflow(zeroW + y1 / this.invertedYRatio)
483
- const x2 = this.preventBarOverflow(zeroW + y2 / this.invertedYRatio)
485
+ const ratio = this.invertedYRatio * (this.isReversed ? -1 : 1)
486
+ const x1 = this.preventBarOverflow(zeroW + y1 / ratio)
487
+ const x2 = this.preventBarOverflow(zeroW + y2 / ratio)
484
488
 
485
489
  const range = this.getRangeValue(realIndex, j)
486
490