apexcharts 7.7.0 → 7.9.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 (248) hide show
  1. package/{LICENSE → LICENSE.md} +1 -1
  2. package/README.md +1 -0
  3. package/dist/apexcharts.common.js +2 -2
  4. package/dist/apexcharts.core.js +4414 -722
  5. package/dist/apexcharts.core.min.js +2 -2
  6. package/dist/apexcharts.css +22 -5
  7. package/dist/apexcharts.esm.js +2141 -598
  8. package/dist/apexcharts.js +6568 -1263
  9. package/dist/apexcharts.min.js +2 -2
  10. package/dist/apexcharts.ssr.common.js +2 -2
  11. package/dist/apexcharts.ssr.esm.js +6567 -1262
  12. package/dist/area.common.js +2 -2
  13. package/dist/area.esm.js +297 -194
  14. package/dist/bar.common.js +2 -2
  15. package/dist/bar.esm.js +357 -143
  16. package/dist/bar.js +2 -2
  17. package/dist/boxPlot.common.js +2 -2
  18. package/dist/boxPlot.esm.js +417 -152
  19. package/dist/bubble.common.js +2 -2
  20. package/dist/bubble.esm.js +297 -194
  21. package/dist/candlestick.common.js +2 -2
  22. package/dist/candlestick.esm.js +417 -152
  23. package/dist/candlestick.js +2 -2
  24. package/dist/column.common.js +2 -2
  25. package/dist/column.esm.js +357 -143
  26. package/dist/core.common.js +2 -2
  27. package/dist/core.esm.js +4414 -722
  28. package/dist/donut.common.js +2 -2
  29. package/dist/donut.esm.js +49 -17
  30. package/dist/dumbbell.common.js +2 -2
  31. package/dist/dumbbell.esm.js +357 -143
  32. package/dist/features/all.common.js +2 -2
  33. package/dist/features/all.esm.js +647 -133
  34. package/dist/features/annotations.common.js +2 -2
  35. package/dist/features/annotations.esm.js +2 -2
  36. package/dist/features/annotations.js +2 -2
  37. package/dist/features/context-menu.common.js +2 -2
  38. package/dist/features/context-menu.esm.js +17 -8
  39. package/dist/features/context-menu.js +2 -2
  40. package/dist/features/drilldown.common.js +2 -2
  41. package/dist/features/drilldown.esm.js +3 -1
  42. package/dist/features/drilldown.js +2 -2
  43. package/dist/features/dumbbell.common.js +1 -1
  44. package/dist/features/dumbbell.esm.js +1 -1
  45. package/dist/features/dumbbell.js +1 -1
  46. package/dist/features/exports.common.js +2 -2
  47. package/dist/features/exports.esm.js +12 -6
  48. package/dist/features/exports.js +2 -2
  49. package/dist/features/facet.common.js +1 -1
  50. package/dist/features/facet.esm.js +1 -1
  51. package/dist/features/facet.js +1 -1
  52. package/dist/features/highlight-filter.common.js +5 -0
  53. package/dist/features/highlight-filter.esm.js +4485 -0
  54. package/dist/features/highlight-filter.js +5 -0
  55. package/dist/features/history.common.js +1 -1
  56. package/dist/features/history.esm.js +1 -1
  57. package/dist/features/history.js +1 -1
  58. package/dist/features/ink.common.js +2 -2
  59. package/dist/features/ink.esm.js +6 -4
  60. package/dist/features/ink.js +2 -2
  61. package/dist/features/keyboard.common.js +2 -2
  62. package/dist/features/keyboard.esm.js +482 -54
  63. package/dist/features/keyboard.js +2 -2
  64. package/dist/features/legend.common.js +2 -2
  65. package/dist/features/legend.esm.js +24 -8
  66. package/dist/features/legend.js +2 -2
  67. package/dist/features/link.common.js +1 -1
  68. package/dist/features/link.esm.js +1 -1
  69. package/dist/features/link.js +1 -1
  70. package/dist/features/marks.common.js +1 -1
  71. package/dist/features/marks.esm.js +1 -1
  72. package/dist/features/marks.js +1 -1
  73. package/dist/features/measure.common.js +2 -2
  74. package/dist/features/measure.esm.js +17 -7
  75. package/dist/features/measure.js +2 -2
  76. package/dist/features/morph.common.js +2 -2
  77. package/dist/features/morph.esm.js +74 -25
  78. package/dist/features/morph.js +2 -2
  79. package/dist/features/perspectives.common.js +2 -2
  80. package/dist/features/perspectives.esm.js +3 -1
  81. package/dist/features/perspectives.js +2 -2
  82. package/dist/features/raincloud.common.js +1 -1
  83. package/dist/features/raincloud.esm.js +1 -1
  84. package/dist/features/raincloud.js +1 -1
  85. package/dist/features/renderer-canvas.common.js +2 -2
  86. package/dist/features/renderer-canvas.esm.js +464 -28
  87. package/dist/features/renderer-canvas.js +2 -2
  88. package/dist/features/stats.common.js +1 -1
  89. package/dist/features/stats.esm.js +1 -1
  90. package/dist/features/stats.js +1 -1
  91. package/dist/features/storyboard.common.js +2 -2
  92. package/dist/features/storyboard.esm.js +3 -1
  93. package/dist/features/storyboard.js +2 -2
  94. package/dist/features/streamgraph.common.js +1 -1
  95. package/dist/features/streamgraph.esm.js +1 -1
  96. package/dist/features/streamgraph.js +1 -1
  97. package/dist/features/toolbar.common.js +2 -2
  98. package/dist/features/toolbar.esm.js +69 -48
  99. package/dist/features/toolbar.js +2 -2
  100. package/dist/features/trellis.common.js +2 -2
  101. package/dist/features/trellis.esm.js +131 -46
  102. package/dist/features/trellis.js +2 -2
  103. package/dist/features/waterfall.common.js +1 -1
  104. package/dist/features/waterfall.esm.js +1 -1
  105. package/dist/features/waterfall.js +1 -1
  106. package/dist/features/weave.common.js +1 -1
  107. package/dist/features/weave.esm.js +1 -1
  108. package/dist/features/weave.js +1 -1
  109. package/dist/heatmap.common.js +2 -2
  110. package/dist/heatmap.esm.js +74 -19
  111. package/dist/heatmap.js +2 -2
  112. package/dist/histogram.common.js +2 -2
  113. package/dist/histogram.esm.js +357 -143
  114. package/dist/icicle.common.js +1 -1
  115. package/dist/icicle.esm.js +1 -1
  116. package/dist/icicle.js +1 -1
  117. package/dist/line.common.js +2 -2
  118. package/dist/line.esm.js +297 -194
  119. package/dist/line.js +2 -2
  120. package/dist/locales/eu.json +56 -0
  121. package/dist/locales/gl.json +4 -3
  122. package/dist/pictograms.common.js +1 -1
  123. package/dist/pictograms.esm.js +1 -1
  124. package/dist/pictograms.js +1 -1
  125. package/dist/pie.common.js +2 -2
  126. package/dist/pie.esm.js +49 -17
  127. package/dist/pie.js +2 -2
  128. package/dist/polarArea.common.js +2 -2
  129. package/dist/polarArea.esm.js +49 -17
  130. package/dist/radar.common.js +2 -2
  131. package/dist/radar.esm.js +30 -4
  132. package/dist/radar.js +2 -2
  133. package/dist/radialBar.common.js +2 -2
  134. package/dist/radialBar.esm.js +149 -60
  135. package/dist/radialBar.js +2 -2
  136. package/dist/raincloud.common.js +2 -2
  137. package/dist/raincloud.esm.js +325 -143
  138. package/dist/rangeArea.common.js +2 -2
  139. package/dist/rangeArea.esm.js +297 -194
  140. package/dist/rangeBar.common.js +2 -2
  141. package/dist/rangeBar.esm.js +357 -143
  142. package/dist/scatter.common.js +2 -2
  143. package/dist/scatter.esm.js +297 -194
  144. package/dist/streamgraph.common.js +2 -2
  145. package/dist/streamgraph.esm.js +297 -194
  146. package/dist/sunburst.common.js +1 -1
  147. package/dist/sunburst.esm.js +1 -1
  148. package/dist/sunburst.js +1 -1
  149. package/dist/treemap.common.js +2 -2
  150. package/dist/treemap.esm.js +522 -40
  151. package/dist/treemap.js +2 -2
  152. package/dist/unit-shapes.common.js +1 -1
  153. package/dist/unit-shapes.esm.js +1 -1
  154. package/dist/unit-shapes.js +1 -1
  155. package/dist/unit.common.js +1 -1
  156. package/dist/unit.esm.js +1 -1
  157. package/dist/unit.js +1 -1
  158. package/dist/violin.common.js +2 -2
  159. package/dist/violin.esm.js +325 -143
  160. package/dist/violin.js +2 -2
  161. package/dist/waterfall.common.js +2 -2
  162. package/dist/waterfall.esm.js +357 -143
  163. package/package.json +7 -9
  164. package/src/apexcharts.js +43 -3
  165. package/src/assets/apexcharts.css +22 -5
  166. package/src/charts/Bar.js +268 -116
  167. package/src/charts/BarStacked.js +30 -5
  168. package/src/charts/BoxCandleStick.js +155 -16
  169. package/src/charts/HeatMap.js +77 -24
  170. package/src/charts/Line.js +303 -148
  171. package/src/charts/Pie.js +66 -15
  172. package/src/charts/Radar.js +70 -2
  173. package/src/charts/Radial.js +151 -82
  174. package/src/charts/RangeBar.js +24 -0
  175. package/src/charts/Treemap.js +676 -39
  176. package/src/charts/Violin.js +26 -0
  177. package/src/charts/common/bar/DataLabels.js +39 -16
  178. package/src/charts/common/bar/Helpers.js +134 -112
  179. package/src/charts/common/line/Helpers.js +27 -0
  180. package/src/entries/core.js +7 -0
  181. package/src/features/highlight-filter.js +27 -0
  182. package/src/locales/eu.json +56 -0
  183. package/src/locales/gl.json +4 -3
  184. package/src/modules/Animations.js +86 -6
  185. package/src/modules/Base.js +7 -0
  186. package/src/modules/Core.js +39 -42
  187. package/src/modules/CoreUtils.js +15 -7
  188. package/src/modules/Data.js +132 -17
  189. package/src/modules/DataLabels.js +289 -31
  190. package/src/modules/Exports.js +18 -6
  191. package/src/modules/Graphics.js +44 -23
  192. package/src/modules/Markers.js +11 -2
  193. package/src/modules/MorphTypeChange.js +89 -32
  194. package/src/modules/Range.js +62 -28
  195. package/src/modules/RendererController.js +36 -10
  196. package/src/modules/Series.js +341 -9
  197. package/src/modules/Theme.js +4 -10
  198. package/src/modules/ZoomPanSelection.js +68 -51
  199. package/src/modules/accessibility/KeyboardNavigation.js +674 -99
  200. package/src/modules/animations/AxisTransition.js +100 -9
  201. package/src/modules/animations/CircleTransition.js +479 -0
  202. package/src/modules/animations/DataLabelTransition.js +275 -2
  203. package/src/modules/animations/LayoutTransition.js +472 -0
  204. package/src/modules/animations/LengthTransition.js +122 -0
  205. package/src/modules/annotations/Annotations.js +10 -1
  206. package/src/modules/axes/Grid.js +68 -43
  207. package/src/modules/contextMenu/ContextMenu.js +23 -7
  208. package/src/modules/drilldown/Drilldown.js +3 -0
  209. package/src/modules/helpers/DataLabelOverlap.js +222 -0
  210. package/src/modules/helpers/Destroy.js +2 -0
  211. package/src/modules/helpers/InitCtxVariables.js +15 -0
  212. package/src/modules/helpers/UpdateHelpers.js +95 -3
  213. package/src/modules/highlightFilter/HighlightFilter.js +2858 -0
  214. package/src/modules/highlightFilter/PiePart.js +653 -0
  215. package/src/modules/highlightFilter/RadialPart.js +1337 -0
  216. package/src/modules/highlightFilter/TreemapPart.js +499 -0
  217. package/src/modules/highlightFilter/util.js +306 -0
  218. package/src/modules/ink/InkLayer.js +15 -3
  219. package/src/modules/legend/HeatmapGradientLegend.js +26 -7
  220. package/src/modules/legend/Helpers.js +14 -1
  221. package/src/modules/license/LicenseEnforcer.js +8 -5
  222. package/src/modules/measure/Measure.js +17 -7
  223. package/src/modules/settings/Config.js +322 -2
  224. package/src/modules/settings/Defaults.js +48 -49
  225. package/src/modules/settings/Globals.js +49 -1
  226. package/src/modules/settings/Options.js +44 -0
  227. package/src/modules/settings/TypeAliases.js +83 -0
  228. package/src/modules/tooltip/AxesTooltip.js +5 -1
  229. package/src/modules/tooltip/Intersect.js +663 -197
  230. package/src/modules/tooltip/Labels.js +89 -28
  231. package/src/modules/tooltip/Marker.js +209 -20
  232. package/src/modules/tooltip/Position.js +829 -138
  233. package/src/modules/tooltip/Tooltip.js +493 -73
  234. package/src/modules/tooltip/Utils.js +173 -3
  235. package/src/modules/tooltip/constants.js +20 -0
  236. package/src/modules/tooltip/placement.js +569 -0
  237. package/src/modules/trellis/Trellis.js +14 -2
  238. package/src/modules/trellis/TrellisScales.js +58 -17
  239. package/src/modules/trellis/TrellisSplit.js +19 -3
  240. package/src/modules/trellis/TrellisSync.js +7 -1
  241. package/src/modules/trellis/TrellisTooltip.js +27 -15
  242. package/src/renderers/Renderer.js +2 -0
  243. package/src/renderers/canvas/CanvasCompositor.js +113 -17
  244. package/src/renderers/canvas/CanvasGraphics.js +173 -3
  245. package/src/renderers/canvas/CanvasRenderer.js +275 -14
  246. package/src/types/internal.d.ts +132 -2
  247. package/src/utils/Utils.js +61 -0
  248. package/types/apexcharts.d.ts +365 -16
@@ -237,6 +237,18 @@ export function computeStagger(opts) {
237
237
  }
238
238
  }
239
239
 
240
+ /**
241
+ * The chart instance behind each chart state `w`, recorded by the first
242
+ * Animations built with one (the chart-level instance InitCtxVariables makes
243
+ * in the chart constructor). Most renderers build their Animations from `w`
244
+ * alone, and whichever of them finishes the mount animation is the one that
245
+ * fires `chart.events.animationEnd`, so without this lookup a line, pie or
246
+ * heatmap chart would hand the user `undefined` where the chart belongs.
247
+ * A WeakMap keeps `w` free of a reference back to the chart.
248
+ * @type {WeakMap<object, import('../types/internal').ChartContext>}
249
+ */
250
+ const chartByState = new WeakMap()
251
+
240
252
  /**
241
253
  * ApexCharts Animation Class.
242
254
  *
@@ -251,6 +263,7 @@ export default class Animations {
251
263
  constructor(w, ctx) {
252
264
  this.w = w
253
265
  this.ctx = ctx // kept for animationEnd user callback: chart.events.animationEnd(ctx, …)
266
+ if (ctx && w && !chartByState.has(w)) chartByState.set(w, ctx)
254
267
  }
255
268
 
256
269
  /**
@@ -347,7 +360,8 @@ export default class Animations {
347
360
  */
348
361
  /** @param {any} el @param {any} from @param {any} to @param {any} speed @param {any} fn @param {number} [delay] */
349
362
  animateRect(el, from, to, speed, fn, delay = 0) {
350
- el.attr(from)
363
+ return el
364
+ .attr(from)
351
365
  .animate(speed, delay)
352
366
  .attr(to)
353
367
  .after(() => fn())
@@ -406,10 +420,10 @@ export default class Animations {
406
420
  /**
407
421
  * Opacity-fade reveal (see Graphics.renderPaths `revealViaFade`): hide this
408
422
  * path immediately, then reveal the whole series in a single CSS opacity fade
409
- * once the synchronous draw pass has finished. Used for two cases that both
410
- * want to avoid per-path morphs: the large-dataset bulk render (>
411
- * largeDatasetThreshold) and candlestick/boxPlot data-change updates (where an
412
- * index-based morph would slide candles around on zoom). Every faded path is
423
+ * once the synchronous draw pass has finished. Used by the large-dataset bulk
424
+ * render (> largeDatasetThreshold), where per-path morphs cost too much.
425
+ * (Candlestick/boxPlot data changes used to fade too; they now morph, keyed
426
+ * by datum, see Graphics.renderPaths.) Every faded path is
413
427
  * pushed to delayedElements, but only the first one schedules the reveal — a
414
428
  * lone requestAnimationFrame fires after all paths are in the DOM, so N paths
415
429
  * cost one frame callback instead of N morph timelines. The guard flag is
@@ -421,6 +435,7 @@ export default class Animations {
421
435
  const w = this.w
422
436
  el.node.classList.add('apexcharts-element-hidden')
423
437
  w.globals.delayedElements.push({ el: el.node })
438
+ w.globals.fadeRevealEls.push(el.node)
424
439
 
425
440
  if (!Environment.isBrowser() || !w.globals.shouldAnimate) {
426
441
  // No animation frame to wait on (SSR / animation off) — reveal at once so
@@ -435,6 +450,21 @@ export default class Animations {
435
450
  // chart may have been destroyed before this frame ran (see animateDraw)
436
451
  if (w.globals.isDestroyed) return
437
452
  w.globals.bulkRevealScheduled = false
453
+ const faded = w.globals.fadeRevealEls
454
+ w.globals.fadeRevealEls = []
455
+ const batch = w.globals.morphBatch
456
+ if (batch && batch.pending > 0) {
457
+ // A series that fades can share the render with series that
458
+ // morph (candles that lost their identity beside a line). The
459
+ // animation is not over until those land: reveal only what faded
460
+ // now, and complete when the last morph does.
461
+ faded.forEach((n) => {
462
+ n.classList.remove('apexcharts-element-hidden')
463
+ n.classList.add('apexcharts-hidden-element-shown')
464
+ })
465
+ batch.onDone = () => this.animationCompleted(el)
466
+ return
467
+ }
438
468
  this.animationCompleted(el)
439
469
  })
440
470
  }
@@ -468,7 +498,10 @@ export default class Animations {
468
498
  this.showDelayedElements()
469
499
 
470
500
  if (typeof w.config.chart.events.animationEnd === 'function') {
471
- w.config.chart.events.animationEnd(this.ctx, { el, w })
501
+ w.config.chart.events.animationEnd(this.ctx || chartByState.get(w), {
502
+ el,
503
+ w,
504
+ })
472
505
  }
473
506
  }
474
507
 
@@ -740,6 +773,11 @@ export default class Animations {
740
773
  // _executeChain, so every staggered bar started at 2x its intended offset,
741
774
  // drifting away from the axis/data labels that share its clock. The
742
775
  // synchronous plot(pathFrom) already pins the start shape during the wait.
776
+ // The morphs this render started, so a fade sharing the render can wait
777
+ // for the last of them (see revealBulk).
778
+ const batch = w.globals.morphBatch
779
+ if (batch) batch.pending++
780
+ const landed = Animations.trackSeriesTween(w, realIndex)
743
781
  const runner = el.plot(pathFrom).animate(speed, delay)
744
782
  if (morphEase) {
745
783
  runner.ease(morphEase)
@@ -771,6 +809,48 @@ export default class Animations {
771
809
  }
772
810
 
773
811
  this.showDelayedElements()
812
+
813
+ if (batch) {
814
+ batch.pending--
815
+ if (batch.pending <= 0 && batch.onDone) {
816
+ const done = batch.onDone
817
+ batch.onDone = null
818
+ done()
819
+ }
820
+ }
821
+ landed()
774
822
  })
775
823
  }
824
+
825
+ /**
826
+ * Count one tween of series `realIndex` in this render's batch, and return
827
+ * the call to make when it lands. A legend-hidden series is cleared the
828
+ * moment its LAST tween lands (Series.settleCollapsedShapes): a line that
829
+ * has flattened onto the baseline must not lie there waiting for a timer.
830
+ * @param {import('../types/internal').ChartStateW} w
831
+ * @param {any} realIndex
832
+ * @returns {() => void}
833
+ */
834
+ static trackSeriesTween(w, realIndex) {
835
+ const series = w.globals.morphBatch?.series
836
+ if (!series || !Utils.isNumber(realIndex)) return () => {}
837
+ let s = series.get(realIndex)
838
+ if (!s) {
839
+ s = { pending: 0, onDone: null }
840
+ series.set(realIndex, s)
841
+ }
842
+ const entry = s
843
+ entry.pending++
844
+ let done = false
845
+ return () => {
846
+ if (done) return
847
+ done = true
848
+ entry.pending--
849
+ if (entry.pending <= 0 && entry.onDone) {
850
+ const fn = entry.onDone
851
+ entry.onDone = null
852
+ fn()
853
+ }
854
+ }
855
+ }
776
856
  }
@@ -156,6 +156,13 @@ export default class Base {
156
156
  // carrier = the series index the merged rows were written to
157
157
  // hidden[] = endpoint indices collapsed from the legend
158
158
  dumbbellData: null,
159
+ // Highlight filter parts (features/highlight-filter), built each parse:
160
+ // active = a part is present and the option is on
161
+ // parts = parts[i][j], null where a datum has none
162
+ // ext = the parts again when they may stretch the value axis
163
+ // capture = called by Series when it captures the outgoing frame
164
+ // null when the feature is not loaded.
165
+ highlightData: null,
159
166
  // Streamgraph bands, written by the streamgraph series transform
160
167
  // (features/streamgraph) each parse; null for every other chart type.
161
168
  // names[k] = band k's series name
@@ -3,6 +3,7 @@ import CoreUtils from './CoreUtils'
3
3
  import Crosshairs from './Crosshairs'
4
4
  import Globals from '../modules/settings/Globals'
5
5
  import Graphics from './Graphics'
6
+ import Animations from './Animations'
6
7
  import Range from './Range'
7
8
  import Utils from '../utils/Utils'
8
9
  import TimeScale from './TimeScale'
@@ -10,6 +11,12 @@ import { Environment } from '../utils/Environment.js'
10
11
  import { BrowserAPIs } from '../ssr/BrowserAPIs.js'
11
12
  import { SVGNS } from '../svg/math'
12
13
  import { getChartClass, isCustom } from './ChartFactory'
14
+ import {
15
+ XY_TYPES,
16
+ AXIS_TYPES,
17
+ BUILTIN_TYPES,
18
+ SOLO_TYPES,
19
+ } from './settings/TypeAliases'
13
20
 
14
21
  /**
15
22
  * ApexCharts Core Class responsible for major calculations and creating elements.
@@ -33,36 +40,14 @@ export default class Core {
33
40
  const { globals: gl, config: cnf } = this.w
34
41
 
35
42
  const ct = cnf.chart.type
36
- const xyChartsArrTypes = [
37
- 'line',
38
- 'area',
39
- 'bar',
40
- 'rangeBar',
41
- 'rangeArea',
42
- 'candlestick',
43
- 'boxPlot',
44
- 'violin',
45
- 'scatter',
46
- 'bubble',
47
- ]
48
-
49
- const axisChartsArrTypes = [
50
- ...xyChartsArrTypes,
51
- 'radar',
52
- 'heatmap',
53
- 'treemap',
54
- ]
55
43
 
56
44
  // Marks (#11): a registered custom series type used as the chart type is an
57
45
  // xy/axis chart (it draws in series space and needs the axis/grid/scale
58
- // pipeline). Non-axis built-ins (pie/radialBar/...) are never custom here.
59
- const isCustomType =
60
- !axisChartsArrTypes.includes(ct) &&
61
- !['pie', 'donut', 'polarArea', 'radialBar'].includes(ct) &&
62
- isCustom(ct)
46
+ // pipeline). A built-in name is never custom, whatever the registry says.
47
+ const isCustomType = !BUILTIN_TYPES.includes(ct) && isCustom(ct)
63
48
 
64
- gl.axisCharts = axisChartsArrTypes.includes(ct) || isCustomType
65
- gl.xyCharts = xyChartsArrTypes.includes(ct) || isCustomType
49
+ gl.axisCharts = AXIS_TYPES.includes(ct) || isCustomType
50
+ gl.xyCharts = XY_TYPES.includes(ct) || isCustomType
66
51
 
67
52
  gl.isBarHorizontal =
68
53
  ['bar', 'rangeBar', 'boxPlot', 'violin'].includes(ct) &&
@@ -250,20 +235,7 @@ export default class Core {
250
235
  st_[seriesType].i.push(st)
251
236
 
252
237
  if (seriesType === 'bar') w.globals.columnSeries = seriesTypes.bar
253
- } else if (
254
- [
255
- 'heatmap',
256
- 'treemap',
257
- 'pie',
258
- 'donut',
259
- 'polarArea',
260
- 'radialBar',
261
- 'radar',
262
- 'unit',
263
- 'sunburst',
264
- 'icicle',
265
- ].includes(seriesType)
266
- ) {
238
+ } else if (SOLO_TYPES.includes(seriesType)) {
267
239
  nonComboType = seriesType
268
240
  } else if (isCustom(seriesType)) {
269
241
  // Marks (#11): a registered custom series type.
@@ -311,7 +283,13 @@ export default class Core {
311
283
  // Series marks emitted during draw() below are recorded, not added to the
312
284
  // DOM; they are painted at the end of this method (see the wrap below).
313
285
  const canvasMode = ctx.renderer && ctx.renderer.kind === 'canvas'
314
- if (canvasMode) ctx.renderer.beginSeries()
286
+ if (canvasMode) {
287
+ ctx.renderer.beginSeries()
288
+ // What Bar.renderSeries caches for the painted marks describes this
289
+ // pass alone; a mark painted in several paths grows its extent over
290
+ // the entry, so nothing may be left from an earlier pass.
291
+ w.globals.barCanvasCoords = null
292
+ }
315
293
 
316
294
  const { seriesTypes, customBuckets } = this._classifySeriesByType(ser)
317
295
 
@@ -325,6 +303,13 @@ export default class Core {
325
303
  )
326
304
 
327
305
  if (canvasMode) {
306
+ // The canvas paints the final frame in this pass, so no series
307
+ // animation runs whose end would reveal the SVG chrome held back for
308
+ // it: goal markers (a box plot's outlier dots among them), bar data
309
+ // labels and bar shadows wait in delayedElements, hidden for good.
310
+ // They show now, as they do on SVG when nothing animates.
311
+ new Animations(w).showDelayedElements()
312
+
328
313
  // Paint the recorded series display list into a <foreignObject><canvas>
329
314
  // and wrap it with the real SVG chrome groups (data labels etc.) the
330
315
  // draw() built. Canvas sits at the back of the wrap (behind the chrome);
@@ -651,8 +636,20 @@ export default class Core {
651
636
  // Marks (#11): a registered custom series type as the chart type.
652
637
  const cs = new (getChartClass(type))(ctx.w, ctx, xyRatios)
653
638
  elGraph = cs.draw(this.w.seriesData.series, type)
654
- } else {
639
+ } else if (line) {
655
640
  elGraph = line.draw(this.w.seriesData.series)
641
+ } else {
642
+ // Unreachable: Config.assertKnownChartType rejects a type with no
643
+ // renderer before a chart is ever built, and every name it lets
644
+ // through has a case above or is custom. Guarded anyway because
645
+ // the unguarded version of this line is what #5325 actually threw
646
+ // (`line` is null whenever setupElements decided the chart was
647
+ // not an xy one, and "fall back to a line" cannot be done with a
648
+ // renderer that was never instantiated). Fail with the option name
649
+ // rather than with a property access on null.
650
+ throw new Error(
651
+ `ApexCharts: no renderer for chart.type "${type}".`,
652
+ )
656
653
  }
657
654
  }
658
655
  }
@@ -213,8 +213,10 @@ class CoreUtils {
213
213
  const seriesYAxisReverseMap = []
214
214
  /** @type {any[]} */
215
215
  const unassignedSeriesIndices = []
216
+ // cnf.series, not seriesData.series: the first call (parseDataAxisCharts)
217
+ // runs before seriesData.series is filled, and its map sets default groups.
216
218
  const seriesNameArrayStyle =
217
- this.w.seriesData.series.length > cnf.yaxis.length ||
219
+ cnf.series.length > cnf.yaxis.length ||
218
220
  /**
219
221
  * @param {ApexYAxis} a
220
222
  */
@@ -371,16 +373,22 @@ class CoreUtils {
371
373
  */
372
374
  isSeriesNull(index = null) {
373
375
  let r = []
374
- const series = /** @type {any[]} */ (this.w.config.series)
375
376
  if (index === null) {
376
377
  // non-plot chart types - pie / donut / circle
378
+ const series = /** @type {any[]} */ (this.w.config.series)
377
379
  r = series.filter((/** @type {any} */ d) => d !== null)
378
- } else if (series[index] && Array.isArray(series[index].data)) {
379
- // axis charts - supporting multiple series
380
- r = series[index].data.filter((/** @type {any} */ d) => d !== null)
381
380
  } else {
382
- // pie/donut/polarArea/radialBar called per-index from legend loop
383
- r = series[index] !== null && series[index] !== undefined ? [series[index]] : []
381
+ const seriesAtIndex = this.w.seriesData.series[index]
382
+ if (Array.isArray(seriesAtIndex)) {
383
+ // axis charts - supporting multiple series
384
+ r = seriesAtIndex.filter((/** @type {any} */ d) => d !== null)
385
+ } else {
386
+ // pie/donut/polarArea/radialBar called per-index from legend loop
387
+ r =
388
+ seriesAtIndex !== null && seriesAtIndex !== undefined
389
+ ? [seriesAtIndex]
390
+ : []
391
+ }
384
392
  }
385
393
 
386
394
  return r.length === 0
@@ -41,11 +41,22 @@ function subtreeTotal(d) {
41
41
  export default class Data {
42
42
  /**
43
43
  * @param {import('../types/internal').ChartStateW} w
44
+ * @param {{resetGlobals?: () => any, isMultipleY?: () => any, highlight?: () => any}} [hooks]
44
45
  */
45
- constructor(w, { resetGlobals = () => {}, isMultipleY = () => {} } = {}) {
46
+ constructor(
47
+ w,
48
+ {
49
+ resetGlobals = () => {},
50
+ isMultipleY = () => {},
51
+ highlight = () => null,
52
+ } = {},
53
+ ) {
46
54
  this.w = w
47
55
  this.resetGlobals = resetGlobals
48
56
  this.isMultipleY = isMultipleY
57
+ // The highlight filter feature, or null (see InitCtxVariables).
58
+ this.highlight = highlight
59
+ this._warnedHighlight = false
49
60
 
50
61
  /** @type {any} */
51
62
  this.twoDSeries = []
@@ -232,9 +243,26 @@ export default class Data {
232
243
  const cnf = this.w.config
233
244
  const data = ser[i].data
234
245
 
235
- const isBoxPlot =
236
- cnf.chart.type === 'boxPlot' ||
237
- /** @type {any} */ (cnf.series[i]).type === 'boxPlot'
246
+ // A legend-collapsed series arrives here as `data: []`, and a stacked chart
247
+ // then pads its y with zeros (Series.setNullSeriesToZeroValues). Without
248
+ // x values to go with them every point lands at x = NaN, the stack lookup
249
+ // (Line._stackKey keys by x value) misses, and the keyed morph join reads
250
+ // every datum as an exit plus an enter. The hidden layer then tweens into
251
+ // the plot's bottom-left corner instead of flattening onto the series
252
+ // below it. Borrow the active series' x, as handleFormatXY has done for
253
+ // the {x, y} format since #368, so both formats exit the same way.
254
+ if (data.length === 0 && this._isCollapsedIndex(i)) {
255
+ const activeData = ser[this.activeSeriesIndex]?.data || []
256
+ for (let j = 0; j < activeData.length; j++) {
257
+ const x = Array.isArray(activeData[j]) ? activeData[j][0] : undefined
258
+ this.twoDSeriesX.push(
259
+ cnf.xaxis.type === 'datetime' ? new Date(x).getTime() : x,
260
+ )
261
+ }
262
+ return
263
+ }
264
+
265
+ const isBoxPlot = this._isBoxPlotSeries(i)
238
266
 
239
267
  if (
240
268
  !isBoxPlot &&
@@ -270,13 +298,70 @@ export default class Data {
270
298
  this.twoDSeriesX.push(x)
271
299
  }
272
300
 
273
- if (typeof z !== 'undefined') {
274
- this.threeDSeries.push(z)
275
- this.w.axisFlags.isDataXYZ = true
276
- }
301
+ this.pushZ(z, j)
277
302
  }
278
303
  }
279
304
 
305
+ /**
306
+ * Record one point's `z`, the third dimension a bubble sizes itself by and
307
+ * the tooltip reports as "Size".
308
+ *
309
+ * Two rules, both of which used to be broken (#5323):
310
+ *
311
+ * 1. The slot is positional. `seriesZ[i][j]` is read by data-point index, so
312
+ * a point WITHOUT `z` still owns its slot. Otherwise a series where only
313
+ * some points carry `z` reports the previous point's value for every
314
+ * point after the first gap. Nothing is allocated for a series that
315
+ * carries no `z` at all: the backfill only runs once the first `z` shows
316
+ * up, so an ordinary line chart pays nothing.
317
+ *
318
+ * 2. Only a MEASURABLE value makes the chart three-dimensional. `z: NaN`,
319
+ * `z: ''` and `z: null` are the shapes a missing value arrives in from a
320
+ * database or a CSV, and they used to set `isDataXYZ` just by being
321
+ * present, which grew a stray "Size:" row on charts that have no third
322
+ * dimension. A numeric string goes the other way and is coerced, the way
323
+ * `y` already is, so `z: '99'` sizes a bubble instead of sitting in
324
+ * `seriesZ` as a string that `Range.setZRange` then skips. Anything else
325
+ * is stored as given, since a custom `tooltip.z.formatter` may still want
326
+ * it; it just cannot be what declares the chart 3-D.
327
+ *
328
+ * @param {any} z the point's raw `z`, or undefined when it has none
329
+ * @param {number} j the point's index within the series
330
+ */
331
+ pushZ(z, j) {
332
+ if (typeof z === 'undefined') {
333
+ // Only hold the slot for a series already carrying z (rule 1).
334
+ if (this.threeDSeries.length) this.threeDSeries.push(null)
335
+ return
336
+ }
337
+
338
+ const num = typeof z === 'string' && z.trim() !== '' ? Number(z) : z
339
+ // The same test Range.setZRange applies, so a value that counts as the
340
+ // third dimension here is one the z extent can actually be built from.
341
+ const measurable = Utils.isNumber(num)
342
+
343
+ while (this.threeDSeries.length < j) this.threeDSeries.push(null)
344
+ this.threeDSeries.push(measurable ? num : z)
345
+
346
+ if (measurable) {
347
+ this.w.axisFlags.isDataXYZ = true
348
+ }
349
+ }
350
+
351
+ /**
352
+ * Hidden through the legend, either outright or as an ancillary series whose
353
+ * y axis stays drawn (`yaxis.showAlways`). Both empty the series' data.
354
+ * @param {number} i
355
+ * @returns {boolean}
356
+ */
357
+ _isCollapsedIndex(i) {
358
+ const gl = this.w.globals
359
+ return (
360
+ gl.collapsedSeriesIndices.indexOf(i) > -1 ||
361
+ gl.ancillaryCollapsedSeriesIndices.indexOf(i) > -1
362
+ )
363
+ }
364
+
280
365
  /**
281
366
  * @param {any[]} ser
282
367
  * @param {number} i
@@ -288,7 +373,7 @@ export default class Data {
288
373
  const data = ser[i].data
289
374
 
290
375
  let activeI = i
291
- if (gl.collapsedSeriesIndices.indexOf(i) > -1) {
376
+ if (this._isCollapsedIndex(i)) {
292
377
  // fix #368
293
378
  activeI = this.activeSeriesIndex
294
379
  }
@@ -314,10 +399,7 @@ export default class Data {
314
399
  this.seriesGoals[i].push(null)
315
400
  }
316
401
 
317
- if (typeof point.z !== 'undefined') {
318
- this.threeDSeries.push(point.z)
319
- this.w.axisFlags.isDataXYZ = true
320
- }
402
+ this.pushZ(point.z, j)
321
403
  }
322
404
 
323
405
  // get seriesX
@@ -708,16 +790,27 @@ export default class Data {
708
790
  }
709
791
  }
710
792
 
793
+ /**
794
+ * Is series `i` read as a box plot (o, q1, median, q3, c) rather than as
795
+ * candles (o, h, l, c)? A box or candle series is read as its own type, as
796
+ * BoxCandleStick draws it, so a candlestick series in a 'boxPlot' chart is
797
+ * read as candles. Any other series goes by the chart's type, as before.
798
+ * @param {number} i
799
+ * @returns {boolean}
800
+ */
801
+ _isBoxPlotSeries(i) {
802
+ const own = /** @type {any} */ (this.w.config.series[i])?.type
803
+ if (own === 'boxPlot' || own === 'candlestick') return own === 'boxPlot'
804
+ return this.w.config.chart.type === 'boxPlot'
805
+ }
806
+
711
807
  /**
712
808
  * @param {string} format
713
809
  * @param {any[]} ser
714
810
  * @param {number} i
715
811
  */
716
812
  handleCandleStickBoxDataFormat(format, ser, i) {
717
- const w = this.w
718
- const isBoxPlot =
719
- w.config.chart.type === 'boxPlot' ||
720
- /** @type {Record<string,any>} */ (w.config.series[i]).type === 'boxPlot'
813
+ const isBoxPlot = this._isBoxPlotSeries(i)
721
814
 
722
815
  const serO = []
723
816
  const serH = []
@@ -2135,6 +2228,28 @@ export default class Data {
2135
2228
  }
2136
2229
  }
2137
2230
 
2231
+ // Highlight filter: the feature reads the parts off the parsed rows. When
2232
+ // it is not loaded, a chart handed parts would otherwise just draw without
2233
+ // them, so say once what is missing. Checked per series, never per point.
2234
+ const hf = this.highlight()
2235
+ if (hf) {
2236
+ hf.parse()
2237
+ } else if (
2238
+ !this._warnedHighlight &&
2239
+ (cnf.highlightFilter?.data ||
2240
+ ser.some(
2241
+ (/** @type {any} */ s) =>
2242
+ s &&
2243
+ (s.highlightData ||
2244
+ (s.data?.[0] && typeof s.data[0] === 'object' && 'highlight' in s.data[0])),
2245
+ ))
2246
+ ) {
2247
+ this._warnedHighlight = true
2248
+ console.warn(
2249
+ "ApexCharts: series carry highlight parts but the highlight filter is not loaded. Add import 'apexcharts/features/highlight-filter' (or load dist/features/highlight-filter.js after apexcharts.js).",
2250
+ )
2251
+ }
2252
+
2138
2253
  // Return a snapshot of all parsed state grouped by future w.* slice destinations.
2139
2254
  // Phase 1: callers use named writer stubs (no-ops — mutations above already wrote to gl).
2140
2255
  // Phase 2: writers will assign to typed slices instead of gl.*.