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
@@ -2,7 +2,6 @@
2
2
  import Graphics from '../../../modules/Graphics'
3
3
  import DataLabels from '../../../modules/DataLabels'
4
4
  import { resolveDataLabelOffset } from '../../../modules/helpers/DataLabelOffset'
5
- import { datumKey } from '../../../modules/animations/LengthTransition'
6
5
 
7
6
  export default class BarDataLabels {
8
7
  /**
@@ -42,6 +41,7 @@ export default class BarDataLabels {
42
41
  barYPosition,
43
42
  visibleSeries,
44
43
  hl,
44
+ noLabel,
45
45
  } = opts
46
46
  const w = this.w
47
47
  const graphics = new Graphics(this.barCtx.w)
@@ -224,19 +224,21 @@ export default class BarDataLabels {
224
224
  }
225
225
  }
226
226
 
227
- dataLabels = this.drawCalculatedDataLabels({
228
- x: dataLabelsPos.dataLabelsX,
229
- y: dataLabelsPos.dataLabelsY,
230
- neg: params.neg,
231
- val,
232
- text,
233
- i: realIndex,
234
- j,
235
- barWidth: params.barWidth,
236
- barHeight: params.barHeight,
237
- textRects,
238
- dataLabelsConfig,
239
- })
227
+ dataLabels = noLabel
228
+ ? null
229
+ : this.drawCalculatedDataLabels({
230
+ x: dataLabelsPos.dataLabelsX,
231
+ y: dataLabelsPos.dataLabelsY,
232
+ neg: params.neg,
233
+ val,
234
+ text,
235
+ i: realIndex,
236
+ j,
237
+ barWidth: params.barWidth,
238
+ barHeight: params.barHeight,
239
+ textRects,
240
+ dataLabelsConfig,
241
+ })
240
242
 
241
243
  if (
242
244
  w.config.chart.stacked &&
@@ -327,8 +329,8 @@ export default class BarDataLabels {
327
329
  }
328
330
 
329
331
  /**
330
- * The running stack at this column's x (BarStacked `tops`, columns only) on
331
- * a numeric axis, where columns stack by x rather than by index.
332
+ * The running stack at this bar's x (BarStacked `tops`) on a numeric axis,
333
+ * where bars stack by x rather than by index.
332
334
  * @param {number} realIndex @param {number} j
333
335
  */
334
336
  xStackTop(realIndex, j) {
@@ -341,6 +343,22 @@ export default class BarDataLabels {
341
343
  )
342
344
  }
343
345
 
346
+ /**
347
+ * The stacked total's text box, measured in the total's own font.
348
+ * @param {number} realIndex @param {number} j
349
+ */
350
+ totalRects(realIndex, j) {
351
+ const s = this.barCtx.barOptions.dataLabels.total.style
352
+ return new Graphics(this.w).getTextRects(
353
+ this.getStackedTotalDataLabel({ realIndex, j }),
354
+ s.fontSize,
355
+ s.fontFamily,
356
+ undefined,
357
+ true,
358
+ s.fontWeight,
359
+ )
360
+ }
361
+
344
362
  /** @param {{realIndex: any, j: any}} opts */
345
363
  getStackedTotalDataLabel({ realIndex, j }) {
346
364
  const w = this.w
@@ -364,7 +382,6 @@ export default class BarDataLabels {
364
382
  calculateColumnsDataLabelsPosition(opts) {
365
383
  const w = this.w
366
384
  let {
367
- i,
368
385
  j,
369
386
  realIndex,
370
387
  y,
@@ -374,7 +391,6 @@ export default class BarDataLabels {
374
391
  textRects,
375
392
  dataLabelsX,
376
393
  dataLabelsY,
377
- dataLabelsConfig,
378
394
  barDataLabelsConfig,
379
395
  barTotalDataLabelsConfig,
380
396
  strokeWidth,
@@ -392,7 +408,7 @@ export default class BarDataLabels {
392
408
  w.config.plotOptions.bar.dataLabels.orientation === 'vertical'
393
409
 
394
410
  const { zeroEncounters } = this.barCtx.barHelpers.getZeroValueEncounters({
395
- i,
411
+ i: realIndex,
396
412
  j,
397
413
  })
398
414
 
@@ -423,7 +439,7 @@ export default class BarDataLabels {
423
439
  dataLabelsX + textRects.height / 2 - strokeWidth / 2 - offsetDLX
424
440
  }
425
441
 
426
- const valIsNegative = opts.neg ?? w.seriesData.series[i][j] < 0
442
+ const valIsNegative = opts.neg ?? w.seriesData.series[realIndex][j] < 0
427
443
 
428
444
  let newY = y
429
445
  if (this.barCtx.isReversed) {
@@ -505,28 +521,17 @@ export default class BarDataLabels {
505
521
  if (this.hlt) lowestPrevY = this.hlt.edge
506
522
 
507
523
  if (this.drawsStackedTotal(realIndex) && barTotalDataLabelsConfig.enabled) {
508
- const ADDITIONAL_OFFY = 18
509
-
510
- const graphics = new Graphics(this.barCtx.w)
511
- const totalLabeltextRects = graphics.getTextRects(
512
- this.getStackedTotalDataLabel({ realIndex, j }),
513
- dataLabelsConfig.fontSize,
514
- )
524
+ // The baseline sits clear of the stack end by a share of the text
525
+ // height, so a large total neither sinks into its own stack nor floats
526
+ // off it (a fixed 18px suited 11px text only).
527
+ const h = this.totalRects(realIndex, j).height
515
528
 
516
529
  if (valIsNegative) {
517
530
  totalDataLabelsY =
518
- lowestPrevY -
519
- totalLabeltextRects.height / 2 -
520
- offY -
521
- barTotalDataLabelsConfig.offsetY +
522
- ADDITIONAL_OFFY
531
+ lowestPrevY + h * 0.77 - offY - barTotalDataLabelsConfig.offsetY
523
532
  } else {
524
533
  totalDataLabelsY =
525
- lowestPrevY +
526
- totalLabeltextRects.height +
527
- offY +
528
- barTotalDataLabelsConfig.offsetY -
529
- ADDITIONAL_OFFY
534
+ lowestPrevY - h * 0.3 + offY + barTotalDataLabelsConfig.offsetY
530
535
  }
531
536
 
532
537
  // width divided into equal parts
@@ -575,7 +580,6 @@ export default class BarDataLabels {
575
580
  const w = this.w
576
581
  let {
577
582
  x,
578
- i,
579
583
  j,
580
584
  realIndex,
581
585
  bcy,
@@ -593,7 +597,7 @@ export default class BarDataLabels {
593
597
 
594
598
  const dataPointsDividedHeight = w.layout.gridHeight / w.globals.dataPoints
595
599
  const { zeroEncounters } = this.barCtx.barHelpers.getZeroValueEncounters({
596
- i,
600
+ i: realIndex,
597
601
  j,
598
602
  })
599
603
 
@@ -632,7 +636,7 @@ export default class BarDataLabels {
632
636
  let totalDataLabelsY
633
637
  let totalDataLabelsAnchor = 'start'
634
638
 
635
- const valIsNegative = opts.neg ?? w.seriesData.series[i][j] < 0
639
+ const valIsNegative = opts.neg ?? w.seriesData.series[realIndex][j] < 0
636
640
 
637
641
  let newX = x
638
642
  if (this.barCtx.isReversed) {
@@ -678,7 +682,13 @@ export default class BarDataLabels {
678
682
  let lowestPrevX = newX
679
683
  // This series' own group only — see the matching note in the column path.
680
684
  const totalGroupCtx = this.getTotalGroupContext(realIndex)
681
- const stacks = /** @type {any} */ (this.barCtx).stacks || []
685
+ const top = this.xStackTop(realIndex, j)
686
+ const stacks = top ? [] : /** @type {any} */ (this.barCtx).stacks || []
687
+ if (top) {
688
+ lowestPrevX = valIsNegative
689
+ ? Math.min(newX, top[4])
690
+ : Math.max(newX, top[5])
691
+ }
682
692
  stacks.forEach((/** @type {any} */ g, /** @type {number} */ gi) => {
683
693
  if (totalGroupCtx && gi !== totalGroupCtx.groupIndex) return
684
694
  g.prevX.forEach((/** @type {any} */ arr) => {
@@ -692,11 +702,7 @@ export default class BarDataLabels {
692
702
  if (this.hlt) lowestPrevX = this.hlt.edge
693
703
 
694
704
  if (this.drawsStackedTotal(realIndex) && barTotalDataLabelsConfig.enabled) {
695
- const graphics = new Graphics(this.barCtx.w)
696
- const totalLabeltextRects = graphics.getTextRects(
697
- this.getStackedTotalDataLabel({ realIndex, j }),
698
- dataLabelsConfig.fontSize,
699
- )
705
+ const totalLabeltextRects = this.totalRects(realIndex, j)
700
706
  if (valIsNegative) {
701
707
  totalDataLabelsX =
702
708
  lowestPrevX - strokeWidth - offX - barTotalDataLabelsConfig.offsetX
@@ -817,12 +823,13 @@ export default class BarDataLabels {
817
823
  // way down while every other slice keeps its number.
818
824
  const isSeriesCollapsing =
819
825
  (w.globals.collapsingSeriesIndices || []).indexOf(i) > -1
826
+ const dlKey = `${i}::${this.barCtx._keys(i)[j]}`
820
827
 
821
828
  if (isSeriesCollapsing) {
822
829
  // Its series has already been zero-filled, so `val` is 0 (or blank) even
823
830
  // though the bar on screen is still at its old height. Label it with what
824
831
  // it was until it has finished shrinking away.
825
- const prev = w.globals.prevDataLabels?.get(`${i}::${datumKey(w, i, j)}`)
832
+ const prev = w.globals.prevDataLabels?.get(dlKey)
826
833
  if (prev && isFinite(prev.val)) {
827
834
  val = prev.val
828
835
  text = undefined
@@ -840,10 +847,7 @@ export default class BarDataLabels {
840
847
  // frame across a data update. Only scalar (non-range) values count up.
841
848
  const dlCfg = w.config.dataLabels
842
849
  if (dlCfg.animate?.enabled || dlCfg.countUp?.enabled) {
843
- elDataLabelsWrap.node.setAttribute(
844
- 'data:dlKey',
845
- `${i}::${datumKey(w, i, j)}`,
846
- )
850
+ elDataLabelsWrap.node.setAttribute('data:dlKey', dlKey)
847
851
  elDataLabelsWrap.node.setAttribute('data:dlJ', String(j))
848
852
  if (typeof val === 'number' && isFinite(val)) {
849
853
  elDataLabelsWrap.node.setAttribute('data:dlVal', String(val))
@@ -865,34 +869,26 @@ export default class BarDataLabels {
865
869
  text = ''
866
870
  }
867
871
 
868
- const valIsNegative = neg ?? w.seriesData.series[i][j] < 0
869
- const position = w.config.plotOptions.bar.dataLabels.position
872
+ // A vertical label's anchor is resolved per label. Writing it into the
873
+ // shared config re-anchored every later label, line labels included.
874
+ let anchor = dataLabelsConfig.textAnchor
870
875
  if (w.config.plotOptions.bar.dataLabels.orientation === 'vertical') {
871
- if (position === 'top') {
872
- if (valIsNegative) dataLabelsConfig.textAnchor = 'end'
873
- else dataLabelsConfig.textAnchor = 'start'
874
- }
875
- if (position === 'center') {
876
- dataLabelsConfig.textAnchor = 'middle'
877
- }
878
- if (position === 'bottom') {
879
- if (valIsNegative) dataLabelsConfig.textAnchor = 'end'
880
- else dataLabelsConfig.textAnchor = 'start'
881
- }
876
+ anchor =
877
+ w.config.plotOptions.bar.dataLabels.position === 'center'
878
+ ? 'middle'
879
+ : (neg ?? w.seriesData.series[i][j] < 0)
880
+ ? 'end'
881
+ : 'start'
882
882
  }
883
883
 
884
+ // hide the datalabel if it cannot fit into the rect (measured in the
885
+ // drawn font, weight included)
884
886
  if (
885
887
  this.barCtx.isRangeBar &&
886
- this.barCtx.barOptions.dataLabels.hideOverflowingLabels
888
+ this.barCtx.barOptions.dataLabels.hideOverflowingLabels &&
889
+ barWidth < textRects.width
887
890
  ) {
888
- // hide the datalabel if it cannot fit into the rect
889
- const txRect = graphics.getTextRects(
890
- text,
891
- parseFloat(dataLabelsConfig.style.fontSize).toString(),
892
- )
893
- if (barWidth < txRect.width) {
894
- text = ''
895
- }
891
+ text = ''
896
892
  }
897
893
 
898
894
  if (
@@ -918,14 +914,13 @@ export default class BarDataLabels {
918
914
 
919
915
  const modifiedDataLabelsConfig = {
920
916
  ...dataLabelsConfig,
917
+ textAnchor: anchor,
921
918
  }
922
- if (this.barCtx.isHorizontal) {
923
- if (val < 0) {
924
- if (dataLabelsConfig.textAnchor === 'start') {
925
- modifiedDataLabelsConfig.textAnchor = 'end'
926
- } else if (dataLabelsConfig.textAnchor === 'end') {
927
- modifiedDataLabelsConfig.textAnchor = 'start'
928
- }
919
+ if (this.barCtx.isHorizontal && val < 0) {
920
+ if (anchor === 'start') {
921
+ modifiedDataLabelsConfig.textAnchor = 'end'
922
+ } else if (anchor === 'end') {
923
+ modifiedDataLabelsConfig.textAnchor = 'start'
929
924
  }
930
925
  }
931
926
 
@@ -1000,7 +995,7 @@ export default class BarDataLabels {
1000
995
  const { groupIndex } = this.barCtx.barHelpers.getGroupIndex(realIndex)
1001
996
  totalDataLabelText.node.setAttribute(
1002
997
  'data:dlTotalKey',
1003
- `${groupIndex}::${datumKey(this.w, realIndex, j)}`,
998
+ `${groupIndex}::${this.barCtx._keys(realIndex)[j]}`,
1004
999
  )
1005
1000
  totalDataLabelText.node.setAttribute(
1006
1001
  'data:dlTotalSeries',
@@ -2,6 +2,7 @@
2
2
  import Graphics from '../../../modules/Graphics'
3
3
  import Series from '../../../modules/Series'
4
4
  import Fill from '../../../modules/Fill'
5
+ import CoreUtils from '../../../modules/CoreUtils'
5
6
  import Utils from '../../../utils/Utils'
6
7
 
7
8
  /**
@@ -33,9 +34,11 @@ export default class Helpers {
33
34
 
34
35
  /**
35
36
  * @param {any[]} series
37
+ * @param {any} [seriesIndex] a combo's real indices of `series`
36
38
  */
37
- initVariables(series) {
39
+ initVariables(series, seriesIndex) {
38
40
  const w = this.w
41
+ this.seriesIndex = seriesIndex
39
42
  this.barCtx.series = series
40
43
  this.barCtx.totalItems = 0
41
44
  this.barCtx.seriesLen = 0
@@ -62,6 +65,18 @@ export default class Helpers {
62
65
  }
63
66
  }
64
67
 
68
+ // A horizontal bar on a numeric axis sits in the band labelled with its
69
+ // own x (Range.setXRange). Where every series has the bands' x at the
70
+ // same position, the band is the index, as on a category axis.
71
+ const labels = w.labelData.labels
72
+ this.rows =
73
+ w.globals.isBarHorizontal &&
74
+ w.axisFlags.isXNumeric &&
75
+ !this.barCtx.isRangeBar &&
76
+ w.seriesData.seriesX.some((s) => s?.some((x, j) => x !== labels[j]))
77
+ ? new Map(labels.map((x, r) => [x, r]))
78
+ : null
79
+
65
80
  this.arrBorderRadius = this.createBorderRadiusArr(w.seriesData.series)
66
81
 
67
82
  if (Utils.isSafari()) {
@@ -138,17 +153,21 @@ export default class Helpers {
138
153
  * Collapsed series count too, exactly as they did for `minXDiff`. Skipping
139
154
  * them would widen every bar the moment someone hid the tightest-spaced
140
155
  * series from the legend, so bar geometry would depend on legend state.
156
+ * In a combo only this renderer's own series count: a line's x values say
157
+ * nothing about how wide a column may be.
141
158
  *
142
159
  * @returns {number}
143
160
  */
144
161
  _unionMinXGap() {
145
162
  const w = this.w
146
163
  const seriesX = w.seriesData.seriesX || []
164
+ const own = this.seriesIndex
147
165
 
148
166
  /** @type {any[][]} */
149
167
  const arrays = []
150
168
  for (let i = 0; i < seriesX.length; i++) {
151
169
  const xs = seriesX[i]
170
+ if (own && own.indexOf(i) < 0) continue
152
171
  if (Array.isArray(xs) && xs.length > 0) {
153
172
  arrays.push(
154
173
  xs.some((v, n) => v < xs[n - 1])
@@ -196,6 +215,15 @@ export default class Helpers {
196
215
  return isFinite(min) ? min : 0
197
216
  }
198
217
 
218
+ /**
219
+ * The band a horizontal bar is drawn in: its x's band when the series do
220
+ * not line up by index (see initVariables), else its index.
221
+ * @param {number} realIndex @param {number} j
222
+ */
223
+ barRow(realIndex, j) {
224
+ return this.rows?.get(this.w.seriesData.seriesX[realIndex]?.[j]) ?? j
225
+ }
226
+
199
227
  /**
200
228
  * @param {number} realIndex
201
229
  */
@@ -374,7 +402,7 @@ export default class Helpers {
374
402
  // fill for this bar alone, so each row gets its own gradient rather than
375
403
  // one chart-wide one pointing whichever way the first row happened to go.
376
404
  const connectorFill = this.getDumbbellConnectorFill(i, j)
377
- const datumFill = connectorFill || w.config.series[i].data[j]?.fill
405
+ const datumFill = connectorFill || w.config.series[realIndex].data[j]?.fill
378
406
 
379
407
  // A named connector colour is a plain join instead of that gradient. Its
380
408
  // opacity rides with it and is NOT applied otherwise, so a range bar drawn
@@ -569,7 +597,8 @@ export default class Helpers {
569
597
  !this.w.config.chart.stacked || w.config.plotOptions.bar.borderRadius <= 0
570
598
 
571
599
  const numSeries = series.length
572
- const numColumns = series[0]?.length | 0
600
+ // the longest series: a short first one left later points unassigned
601
+ const numColumns = Math.max(0, ...series.map((s) => s?.length | 0))
573
602
  const output = Array.from({ length: numSeries }, () =>
574
603
  Array(numColumns).fill(alwaysApplyRadius ? 'top' : 'none')
575
604
  )
@@ -829,10 +858,13 @@ export default class Helpers {
829
858
  }
830
859
 
831
860
  if (w.config.chart.stacked) {
861
+ // A point past the end of a short series is undefined, which reads as
862
+ // neither sign, so the layer above restarted at the axis. It stacks as
863
+ // a null, as the padded series would.
832
864
  const _ctx = this.barCtx.groupCtx
833
865
  _ctx.yArrj.push(y2 - strokeCenter * direction)
834
866
  _ctx.yArrjF.push(Math.abs(y1 - y2 + r.strokeWidth * direction))
835
- _ctx.yArrjVal.push(this.barCtx.series[i][j])
867
+ _ctx.yArrjVal.push(this.barCtx.series[i][j] ?? null)
836
868
  }
837
869
 
838
870
  return {
@@ -1123,7 +1155,7 @@ export default class Helpers {
1123
1155
  const _ctx = this.barCtx.groupCtx
1124
1156
  _ctx.xArrj.push(x2 + strokeCenter * direction)
1125
1157
  _ctx.xArrjF.push(Math.abs(x1 - x2 - r.strokeWidth * direction))
1126
- _ctx.xArrjVal.push(this.barCtx.series[i][j])
1158
+ _ctx.xArrjVal.push(this.barCtx.series[i][j] ?? null)
1127
1159
  }
1128
1160
  return {
1129
1161
  pathTo,
@@ -1187,6 +1219,10 @@ export default class Helpers {
1187
1219
  * @param {Record<string, any>} attrs
1188
1220
  */
1189
1221
  const pushGoal = (value, attrs) => {
1222
+ // the bars are drawn in log space on a logarithmic axis, so is the goal
1223
+ if (!w.globals.invalidLogScale) {
1224
+ value = new CoreUtils(w).getLogValAtSeriesIndex(value, i)
1225
+ }
1190
1226
  goals.push({
1191
1227
  [type]:
1192
1228
  type === 'x'
@@ -1543,11 +1579,11 @@ export default class Helpers {
1543
1579
  * @param {number} _si
1544
1580
  */
1545
1581
  seriesIndices.forEach((/** @type {any} */ _si) => {
1546
- const val = w.globals.seriesPercent[_si][j]
1582
+ const val = w.seriesData.series[_si][j]
1547
1583
  if (val) {
1548
1584
  nonZeroColumns++
1549
1585
  }
1550
- if (_si < i && val === 0) {
1586
+ if (_si < i && !val) {
1551
1587
  zeroEncounters++
1552
1588
  }
1553
1589
  })
@@ -1,5 +1,4 @@
1
1
  // @ts-check
2
- import CoreUtils from '../../../modules/CoreUtils'
3
2
  import Utils from '../../../utils/Utils'
4
3
 
5
4
  export default class Helpers {
@@ -12,26 +11,24 @@ export default class Helpers {
12
11
  }
13
12
 
14
13
  /**
15
- * @param {number} i
14
+ * @param {number} i index into `series`, the rows this draw call renders
16
15
  * @param {any[]} series
16
+ * @param {number} realIndex index into the config / fill options
17
17
  */
18
- sameValueSeriesFix(i, series) {
18
+ sameValueSeriesFix(i, series, realIndex) {
19
19
  const w = this.w
20
+ const s = series[i]
20
21
 
22
+ // applied only to LINE chart
23
+ // a small adjustment to allow gradient line to draw correctly for all same values
24
+ /* #fix https://github.com/apexcharts/apexcharts.js/issues/358 */
21
25
  if (
22
- w.config.fill.type === 'gradient' ||
23
- w.config.fill.type[i] === 'gradient'
26
+ (w.config.fill.type === 'gradient' ||
27
+ w.config.fill.type[realIndex] === 'gradient') &&
28
+ s.every((/** @type {any} */ v) => v === s[0])
24
29
  ) {
25
- const coreUtils = new CoreUtils(this.lineCtx.w)
26
-
27
- // applied only to LINE chart
28
- // a small adjustment to allow gradient line to draw correctly for all same values
29
- /* #fix https://github.com/apexcharts/apexcharts.js/issues/358 */
30
- if (coreUtils.seriesHaveSameValues(i)) {
31
- const gSeries = series[i].slice()
32
- gSeries[gSeries.length - 1] = gSeries[gSeries.length - 1] + 0.000001
33
- series[i] = gSeries
34
- }
30
+ series[i] = s.slice()
31
+ series[i][s.length - 1] += 0.000001
35
32
  }
36
33
  return series
37
34
  }
@@ -70,6 +70,13 @@ export class NodeTooltip {
70
70
  const groupBg = w.config.tooltip.fillSeriesColor
71
71
  ? `background-color:${node._color};`
72
72
  : ''
73
+ // tooltip.y.formatter when given (a node has no dataPointIndex, so it gets
74
+ // -1 and the node itself), else the value without float noise.
75
+ const ty = w.config.tooltip.y
76
+ const fmt = (Array.isArray(ty) ? ty[0] : ty)?.formatter
77
+ const val = fmt
78
+ ? fmt(node.value, { seriesIndex: 0, dataPointIndex: -1, w, node })
79
+ : +node.value.toPrecision(12)
73
80
 
74
81
  t.innerHTML =
75
82
  `<div class="apexcharts-tooltip-series-group apexcharts-active" style="display:flex;${groupBg}">` +
@@ -77,7 +84,7 @@ export class NodeTooltip {
77
84
  `<div class="apexcharts-tooltip-text">` +
78
85
  `<div class="apexcharts-tooltip-y-group">` +
79
86
  `<span class="apexcharts-tooltip-text-y-label">${node.name}: </span>` +
80
- `<span class="apexcharts-tooltip-text-y-value">${node.value} (${pctParent}% of parent, ${pctTotal}% of total)</span>` +
87
+ `<span class="apexcharts-tooltip-text-y-value">${val} (${pctParent}% of parent, ${pctTotal}% of total)</span>` +
81
88
  `</div></div></div>`
82
89
  t.classList.add('apexcharts-active')
83
90
  t.style.opacity = '1'
@@ -23,6 +23,7 @@
23
23
  *
24
24
  * @module charts/common/partition/Partition
25
25
  */
26
+ import { Environment } from '../../../utils/Environment.js'
26
27
 
27
28
  /**
28
29
  * Place one node and everything under it into `[t0, t1]`.
@@ -118,7 +119,7 @@ export function placeTree({ roots, nodesAll, focus, t0, t1, cap }) {
118
119
  *
119
120
  * Call it once after the values are filled, not inside the placement recursion,
120
121
  * which re-runs on every zoom. `_key` is assigned at build time from the
121
- * authored index, so sorting never changes a node's identity and an update
122
+ * authored names, so sorting never changes a node's identity and an update
122
123
  * still morphs the right shapes.
123
124
  *
124
125
  * @param {any[]} roots
@@ -259,6 +260,37 @@ export function resolveFocus(node, current, roots) {
259
260
  return { changed: true, focus: next }
260
261
  }
261
262
 
263
+ /**
264
+ * The focus a re-render restores from its stored key (the chart instance is
265
+ * rebuilt every render), under resolveFocus's rules: a key that no longer
266
+ * exists, a branch turned leaf or the lone root is no focus.
267
+ * @param {any} key
268
+ * @param {any[]} nodesAll
269
+ * @param {any[]} roots
270
+ * @returns {any}
271
+ */
272
+ export function focusByKey(key, nodesAll, roots) {
273
+ const f = key && nodesAll.find((n) => n._key === key)
274
+ return f && f.children?.length && !(roots.length === 1 && f === roots[0])
275
+ ? f
276
+ : null
277
+ }
278
+
279
+ /**
280
+ * A node offers the pointer only while clicking it would change the view: a
281
+ * leaf under the focus, or the lone root, resolves to the view the reader is
282
+ * already on. Asked on every layout, because a zoom changes every answer.
283
+ * @param {any} chart an icicle or sunburst instance
284
+ * @param {any} node
285
+ */
286
+ export function setZoomCursor(chart, node) {
287
+ if (!Environment.isBrowser() || chart.cfg.zoomOnClick === false) return
288
+ node._el.node.style.cursor = resolveFocus(node, chart._focus, chart._roots)
289
+ .changed
290
+ ? 'pointer'
291
+ : 'default'
292
+ }
293
+
262
294
  /**
263
295
  * Read a px number or a `'%'` string against a maximum.
264
296
  *
@@ -2,7 +2,6 @@
2
2
  import Utils from '../../../utils/Utils'
3
3
  import Graphics from '../../../modules/Graphics'
4
4
  import DataLabels from '../../../modules/DataLabels'
5
- import { resolveDataLabelOffset } from '../../../modules/helpers/DataLabelOffset'
6
5
 
7
6
  export default class TreemapHelpers {
8
7
  /**
@@ -209,17 +208,10 @@ export default class TreemapHelpers {
209
208
  class: 'apexcharts-data-labels',
210
209
  })
211
210
 
212
- // offsets may be a function evaluated per data point
213
- const offX = resolveDataLabelOffset(dataLabelsConfig.offsetX, w, i, j)
214
- const offY = resolveDataLabelOffset(dataLabelsConfig.offsetY, w, i, j)
215
-
216
- const dataLabelsX = x + offX
217
- const dataLabelsY =
218
- y + parseFloat(dataLabelsConfig.style.fontSize) / 3 + offY
219
-
211
+ // plotDataLabelsText applies offsetX/offsetY itself
220
212
  dataLabels.plotDataLabelsText({
221
- x: dataLabelsX,
222
- y: dataLabelsY,
213
+ x,
214
+ y: y + parseFloat(dataLabelsConfig.style.fontSize) / 3,
223
215
  text,
224
216
  i,
225
217
  j,
@@ -50,7 +50,8 @@
50
50
  "zoomOut": "Zoom Out",
51
51
  "pan": "Panning",
52
52
  "reset": "Reset Zoom",
53
- "measure": "Measure"
53
+ "measure": "Measure",
54
+ "wheelZoomHint": "Use {key} + scroll to zoom"
54
55
  }
55
56
  }
56
57
  }
@@ -49,7 +49,8 @@
49
49
  "zoomIn": "Mărire",
50
50
  "zoomOut": "Micșorare",
51
51
  "pan": "Panoramare",
52
- "reset": "Resetare zoom"
52
+ "reset": "Resetare zoom",
53
+ "measure": "Măsurare"
53
54
  }
54
55
  }
55
- }
56
+ }
@@ -446,6 +446,10 @@ export default class Core {
446
446
  const { config: cnf, globals: gl } = w
447
447
  const { line, boxCandlestick, violin } = renderers
448
448
 
449
+ // A unit chart tweens from the slots of the last render; once another type
450
+ // has drawn over them they are not on screen to tween from.
451
+ if (cnf.chart.type !== 'unit') ctx._unitPrevDots = null
452
+
449
453
  let elGraph = []
450
454
 
451
455
  if (gl.comboCharts) {