apexcharts 8.2.0 → 8.3.1

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 (256) hide show
  1. package/README.md +7 -7
  2. package/dist/apexcharts.common.js +2 -2
  3. package/dist/apexcharts.core.js +19793 -19713
  4. package/dist/apexcharts.core.min.js +2 -2
  5. package/dist/apexcharts.css +38 -8
  6. package/dist/apexcharts.esm.js +1882 -1625
  7. package/dist/apexcharts.full.js +22044 -21634
  8. package/dist/apexcharts.full.min.js +2 -2
  9. package/dist/apexcharts.js +21414 -21124
  10. package/dist/apexcharts.min.js +2 -2
  11. package/dist/apexcharts.ssr.common.js +2 -2
  12. package/dist/apexcharts.ssr.esm.js +21413 -21123
  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 +478 -406
  17. package/dist/bar.js +2 -2
  18. package/dist/boxPlot.common.js +2 -2
  19. package/dist/boxPlot.esm.js +409 -334
  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 +409 -334
  24. package/dist/candlestick.js +2 -2
  25. package/dist/column.common.js +2 -2
  26. package/dist/column.esm.js +478 -406
  27. package/dist/core.common.js +2 -2
  28. package/dist/core.esm.js +19793 -19713
  29. package/dist/donut.common.js +2 -2
  30. package/dist/donut.esm.js +3 -9
  31. package/dist/dumbbell.common.js +2 -2
  32. package/dist/dumbbell.esm.js +478 -406
  33. package/dist/features/all.common.js +2 -2
  34. package/dist/features/all.esm.js +442 -324
  35. package/dist/features/annotations.common.js +2 -2
  36. package/dist/features/annotations.esm.js +65 -48
  37. package/dist/features/annotations.js +2 -2
  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 +2 -2
  48. package/dist/features/exports.esm.js +10 -4
  49. package/dist/features/exports.js +2 -2
  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 +64 -44
  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 +2 -2
  78. package/dist/features/morph.esm.js +9 -5
  79. package/dist/features/morph.js +2 -2
  80. package/dist/features/perspectives.common.js +2 -2
  81. package/dist/features/perspectives.esm.js +4 -1
  82. package/dist/features/perspectives.js +2 -2
  83. package/dist/features/raincloud.common.js +2 -2
  84. package/dist/features/raincloud.esm.js +26 -27
  85. package/dist/features/raincloud.js +2 -2
  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 +2 -2
  90. package/dist/features/stats.esm.js +52 -59
  91. package/dist/features/stats.js +2 -2
  92. package/dist/features/storyboard.common.js +2 -2
  93. package/dist/features/storyboard.esm.js +4 -1
  94. package/dist/features/storyboard.js +2 -2
  95. package/dist/features/streamgraph.common.js +2 -2
  96. package/dist/features/streamgraph.esm.js +48 -14
  97. package/dist/features/streamgraph.js +2 -2
  98. package/dist/features/toolbar.common.js +2 -2
  99. package/dist/features/toolbar.esm.js +148 -18
  100. package/dist/features/toolbar.js +2 -2
  101. package/dist/features/trellis.common.js +2 -2
  102. package/dist/features/trellis.esm.js +150 -63
  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 +2 -2
  108. package/dist/features/weave.esm.js +13 -12
  109. package/dist/features/weave.js +2 -2
  110. package/dist/full.common.js +2 -2
  111. package/dist/full.esm.js +1068 -842
  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 +529 -464
  117. package/dist/icicle.common.js +2 -2
  118. package/dist/icicle.esm.js +80 -46
  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 +2 -2
  129. package/dist/pie.esm.js +3 -9
  130. package/dist/pie.js +2 -2
  131. package/dist/polarArea.common.js +2 -2
  132. package/dist/polarArea.esm.js +3 -9
  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 +2 -2
  137. package/dist/radialBar.esm.js +5 -12
  138. package/dist/radialBar.js +2 -2
  139. package/dist/raincloud.common.js +2 -2
  140. package/dist/raincloud.esm.js +97 -52
  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 +478 -406
  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 +138 -53
  149. package/dist/sunburst.common.js +2 -2
  150. package/dist/sunburst.esm.js +116 -94
  151. package/dist/sunburst.js +2 -2
  152. package/dist/treemap.common.js +2 -2
  153. package/dist/treemap.esm.js +138 -104
  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 +477 -405
  166. package/package.json +1 -1
  167. package/src/apexcharts.js +40 -59
  168. package/src/assets/apexcharts.css +38 -8
  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 +68 -47
  173. package/src/charts/Line.js +118 -42
  174. package/src/charts/Pie.js +2 -8
  175. package/src/charts/Radar.js +5 -7
  176. package/src/charts/Radial.js +2 -6
  177. package/src/charts/RangeBar.js +47 -43
  178. package/src/charts/Sunburst.js +101 -98
  179. package/src/charts/Treemap.js +150 -88
  180. package/src/charts/Unit.js +368 -250
  181. package/src/charts/Violin.js +48 -30
  182. package/src/charts/common/Breadcrumb.js +2 -2
  183. package/src/charts/common/Hierarchy.js +32 -11
  184. package/src/charts/common/Jitter.js +32 -7
  185. package/src/charts/common/Stats.js +30 -23
  186. package/src/charts/common/bar/DataLabels.js +76 -81
  187. package/src/charts/common/bar/Helpers.js +43 -7
  188. package/src/charts/common/line/Helpers.js +12 -15
  189. package/src/charts/common/partition/NodeTooltip.js +29 -7
  190. package/src/charts/common/partition/Partition.js +33 -1
  191. package/src/charts/common/treemap/Helpers.js +3 -11
  192. package/src/charts/common/treemap/Nested.js +2 -3
  193. package/src/features/raincloud.js +16 -10
  194. package/src/features/stats.js +67 -62
  195. package/src/locales/en.json +2 -1
  196. package/src/locales/ro.json +3 -2
  197. package/src/modules/Animations.js +102 -95
  198. package/src/modules/AxisMapping.js +47 -12
  199. package/src/modules/Core.js +4 -0
  200. package/src/modules/CoreUtils.js +18 -42
  201. package/src/modules/Data.js +23 -24
  202. package/src/modules/DataLabels.js +6 -6
  203. package/src/modules/Exports.js +12 -5
  204. package/src/modules/Fill.js +17 -8
  205. package/src/modules/Filters.js +50 -50
  206. package/src/modules/Graphics.js +69 -51
  207. package/src/modules/Markers.js +3 -1
  208. package/src/modules/MorphTypeChange.js +13 -7
  209. package/src/modules/Range.js +44 -29
  210. package/src/modules/RendererController.js +17 -3
  211. package/src/modules/Scales.js +32 -9
  212. package/src/modules/Series.js +41 -19
  213. package/src/modules/Theme.js +1 -1
  214. package/src/modules/Toolbar.js +3 -2
  215. package/src/modules/UnitMarkRegistry.js +0 -5
  216. package/src/modules/ZoomPanSelection.js +123 -2
  217. package/src/modules/accessibility/KeyboardNavigation.js +114 -186
  218. package/src/modules/animations/Easing.js +2 -1
  219. package/src/modules/animations/LengthTransition.js +22 -2
  220. package/src/modules/annotations/Helpers.js +68 -52
  221. package/src/modules/axes/Grid.js +21 -7
  222. package/src/modules/axes/YAxis.js +8 -9
  223. package/src/modules/dimensions/Dimensions.js +9 -3
  224. package/src/modules/dimensions/Grid.js +2 -2
  225. package/src/modules/dimensions/XAxis.js +2 -5
  226. package/src/modules/drilldown/Breadcrumb.js +5 -2
  227. package/src/modules/helpers/Destroy.js +1 -1
  228. package/src/modules/helpers/UpdateHelpers.js +33 -15
  229. package/src/modules/highlightFilter/HighlightFilter.js +8 -9
  230. package/src/modules/highlightFilter/TreemapPart.js +2 -2
  231. package/src/modules/legend/HeatmapGradientLegend.js +76 -45
  232. package/src/modules/legend/Helpers.js +8 -1
  233. package/src/modules/legend/Legend.js +11 -12
  234. package/src/modules/license/LicenseEnforcer.js +5 -0
  235. package/src/modules/settings/Defaults.js +28 -56
  236. package/src/modules/settings/Globals.js +5 -0
  237. package/src/modules/settings/Options.js +7 -7
  238. package/src/modules/settings/TypeAliases.js +33 -16
  239. package/src/modules/streamgraph/StreamLabels.js +1 -0
  240. package/src/modules/tooltip/Labels.js +73 -76
  241. package/src/modules/tooltip/Marker.js +25 -21
  242. package/src/modules/tooltip/Position.js +88 -51
  243. package/src/modules/tooltip/Tooltip.js +242 -255
  244. package/src/modules/tooltip/Utils.js +71 -130
  245. package/src/modules/tooltip/constants.js +5 -5
  246. package/src/modules/trellis/Trellis.js +6 -0
  247. package/src/modules/trellis/TrellisChrome.js +18 -7
  248. package/src/modules/trellis/TrellisSync.js +2 -0
  249. package/src/modules/trellis/TrellisTooltip.js +2 -11
  250. package/src/modules/weave/WeaveHost.js +18 -12
  251. package/src/renderers/canvas/CanvasGraphics.js +1 -0
  252. package/src/ssr/DOMShim.js +10 -0
  253. package/src/svg/SVGFilter.js +26 -17
  254. package/src/types/internal.d.ts +9 -3
  255. package/src/utils/Utils.js +0 -14
  256. package/types/apexcharts.d.ts +33 -12
@@ -38,10 +38,12 @@ import {
38
38
  import {
39
39
  bandScale,
40
40
  farEdge,
41
+ focusByKey,
41
42
  focusChain,
42
43
  parseSize,
43
44
  placeTree,
44
45
  resolveFocus,
46
+ setZoomCursor,
45
47
  sortTree,
46
48
  validateStrict,
47
49
  } from './common/partition/Partition'
@@ -131,6 +133,10 @@ export default class IcicleChart {
131
133
  this._roots = buildHierarchy(this.w)
132
134
  if (!this._roots.length) return g
133
135
  this._roots.forEach((r) => fillValues(r))
136
+ // Colour before sorting, so a branch keeps its authored palette slot (the
137
+ // one its legend marker shows) whatever `sort` does to its position.
138
+ this._nodesAll = []
139
+ this._colorNodes()
134
140
  sortTree(this._roots, this.cfg.sort)
135
141
  if (this.cfg.partition === 'strict') {
136
142
  validateStrict(this._roots, {
@@ -139,8 +145,6 @@ export default class IcicleChart {
139
145
  })
140
146
  }
141
147
 
142
- this._nodesAll = []
143
- this._colorNodes()
144
148
  this.total = this._roots.reduce((s, r) => s + Math.max(0, r.value), 0) || 1
145
149
  this._tooltip.total = this.total
146
150
 
@@ -149,7 +153,12 @@ export default class IcicleChart {
149
153
  g.add(this._cellsG)
150
154
  g.add(this._labelsG)
151
155
 
152
- this._focus = null
156
+ // The focus outlives this instance by key (_relayout clears a stale one).
157
+ this._focus = focusByKey(
158
+ w.globals.icicleFocusKey,
159
+ this._nodesAll,
160
+ this._roots,
161
+ )
153
162
  this._relayout(this._focus)
154
163
 
155
164
  // Same gating as the sunburst and the pie family: a wipe intro on first
@@ -194,7 +203,7 @@ export default class IcicleChart {
194
203
  while (
195
204
  level.length === 1 &&
196
205
  level[0].children &&
197
- level[0].children.length > 1
206
+ level[0].children.length
198
207
  ) {
199
208
  trunk.push(level[0])
200
209
  level = level[0].children
@@ -233,6 +242,7 @@ export default class IcicleChart {
233
242
  * @param {any} focus
234
243
  */
235
244
  _relayout(focus) {
245
+ this.w.globals.icicleFocusKey = focus && focus._key
236
246
  const extent = this._valueExtent()
237
247
  const maxDepth = this.cfg.maxDepth
238
248
  // `maxDepth` counts LEVELS; the walk wants a depth index.
@@ -286,9 +296,19 @@ export default class IcicleChart {
286
296
  })
287
297
 
288
298
  this._nodesAll.forEach((n) => {
299
+ n._sub = false
289
300
  if (!n._show) return
290
301
  n._d0 = scale.near(n._vDepth)
291
302
  n._d1 = farEdge(n, scale, this._focusMaxDepth, this.cfg.leaf, used)
303
+ // Under half a pixel along the value axis a cell shows nothing a reader
304
+ // can see or point at, and on flame-graph data most cells are that thin:
305
+ // no element, listeners or tween for it at rest. It keeps its box, so a
306
+ // zoom or update moves it into or out of that sliver like any other cell
307
+ // (_applyLayout), and a layout that widens it draws it again.
308
+ if (n._t1 - n._t0 < 0.5) {
309
+ n._show = false
310
+ n._sub = true
311
+ }
292
312
  })
293
313
  }
294
314
 
@@ -378,45 +398,51 @@ export default class IcicleChart {
378
398
  // (`dynamicAnimation.speed`) like an update, NOT on `animations.speed`,
379
399
  // which paces the first render. Reading the intro's clock made a click take
380
400
  // 800ms by default, which feels like lag rather than motion.
381
- const dur = !anims.enabled
382
- ? 0
383
- : mode === 'none'
401
+ const dyn = anims.dynamicAnimation
402
+ const dur =
403
+ !anims.enabled || mode === 'none'
384
404
  ? 0
385
- : mode === 'update' || mode === 'zoom'
386
- ? anims.dynamicAnimation.speed || 350
387
- : anims.speed || 500
405
+ : mode === 'intro'
406
+ ? (anims.speed ?? 500)
407
+ : dyn.enabled
408
+ ? (dyn.speed ?? 350)
409
+ : 0
388
410
 
389
411
  // Supersede any in-flight zoom: stale frames from the previous pass check
390
412
  // this and stop.
391
413
  const gen = ++this._zoomGen
392
414
 
393
415
  // Geometry of the PREVIOUS render (stashed on the persistent chart ctx —
394
- // this module is re-instantiated on every data update).
416
+ // this module is re-instantiated on every data update). A zoom reads it too,
417
+ // for the cells too thin to have been drawn (`_sub`): their slot is there.
395
418
  const prev =
396
- mode === 'update' ? /** @type {any} */ (this.ctx)._iciclePrevGeoms : null
419
+ dur > 0 && mode !== 'intro'
420
+ ? /** @type {any} */ (this.ctx)._iciclePrevGeoms
421
+ : null
397
422
 
398
423
  this._nodesAll.forEach((node) => {
424
+ // Where the cell is on screen: its live box, else last pass's box (`s`
425
+ // marks a sub-pixel slot that had no element).
426
+ const was =
427
+ node._cur || (prev && prev.get(node._key) && prev.get(node._key)())
399
428
  if (node._show) {
400
429
  const to = this._box(node)
401
430
  if (!node._el) node._el = this._createCellEl(node)
402
431
  // Per-layout, not per-element: a zoom changes which branches are cut.
403
432
  node._el.node.setAttribute('data:clipped', String(!!node._clipped))
404
- this._setCursor(node)
433
+ setZoomCursor(this, node)
405
434
 
406
435
  if (mode === 'intro' && dur > 0) {
407
436
  this._wipeCell(node, to, dur, gen)
408
437
  return
409
438
  }
410
439
 
411
- let from
440
+ // `_cur` is the cell's LIVE box (updated each frame), so an interrupted
441
+ // zoom continues from where it actually is; a cell that survived a data
442
+ // update, or was a sliver, tweens from its previous box.
443
+ let from = was
412
444
  let isNew = false
413
- if (node._cur) {
414
- // `_cur` is the cell's LIVE box (updated each frame), so an
415
- // interrupted zoom continues from where it actually is.
416
- from = node._cur
417
- } else if (prev && prev.get(node._key)) {
418
- from = prev.get(node._key) // survived a data update: tween in place
419
- } else {
445
+ if (!from) {
420
446
  // A new cell grows out of the middle of the slot it is taking.
421
447
  from = {
422
448
  x: to.x + to.w / 2,
@@ -427,6 +453,11 @@ export default class IcicleChart {
427
453
  isNew = true
428
454
  }
429
455
  this._animateCell(node, from, to, dur, false, isNew, gen)
456
+ } else if (node._sub && was && !was.s) {
457
+ // On screen until now and a sliver from here: ride into that sliver,
458
+ // as an uncut cell would, and only then drop the element.
459
+ if (!node._el) node._el = this._createCellEl(node)
460
+ this._animateCell(node, was, this._box(node), dur, true, false, gen)
430
461
  } else if (node._el && node._cur) {
431
462
  const c = node._cur
432
463
  const collapsed = {
@@ -439,10 +470,13 @@ export default class IcicleChart {
439
470
  }
440
471
  })
441
472
 
442
- // Stash what is now on screen so the NEXT data update can tween from it.
473
+ // Stash what is on screen so the NEXT data update can tween from it: read
474
+ // live, so an update landing mid-tween starts where the cell actually is.
443
475
  const geoms = new Map()
444
476
  this._nodesAll.forEach((n) => {
445
- if (n._show) geoms.set(n._key, this._box(n))
477
+ const b = this._box(n)
478
+ if (n._sub) b.s = 1
479
+ if (n._show || n._sub) geoms.set(n._key, () => n._cur || b)
446
480
  })
447
481
  ;/** @type {any} */ (this.ctx)._iciclePrevGeoms = geoms
448
482
 
@@ -553,7 +587,8 @@ export default class IcicleChart {
553
587
 
554
588
  el.node.style.display = ''
555
589
  const startOp = hide ? Number(el.attr('opacity')) || 1 : fadeIn ? 0 : 1
556
- const endOp = hide ? 0 : 1
590
+ // A cell thinning into a sliver stays opaque, as it would if it were drawn.
591
+ const endOp = hide && !node._sub ? 0 : 1
557
592
  el.attr({ opacity: startOp })
558
593
 
559
594
  el.animate(dur)
@@ -624,11 +659,14 @@ export default class IcicleChart {
624
659
  if (node._clipped) this._renderMoreMark(node)
625
660
  })
626
661
 
662
+ // Gen-checked: a superseded zoom's fade must not reveal labels over cells
663
+ // the newer zoom is still moving.
664
+ const gen = this._zoomGen
665
+ labelsG.attr({ opacity: dur > 0 ? 0 : 1 })
627
666
  if (dur > 0) {
628
- labelsG.attr({ opacity: 0 })
629
- labelsG.animate(250, dur).attr({ opacity: 1 })
630
- } else {
631
- labelsG.attr({ opacity: 1 })
667
+ labelsG.animate(250, dur).during((/** @type {number} */ p) => {
668
+ if (this._zoomGen === gen) labelsG.attr({ opacity: p })
669
+ })
632
670
  }
633
671
  }
634
672
 
@@ -642,7 +680,6 @@ export default class IcicleChart {
642
680
  * @param {any} node
643
681
  */
644
682
  _renderLabel(node) {
645
- if (!Environment.isBrowser()) return
646
683
  const dl = this.cfg.dataLabels
647
684
  const style = dl.style
648
685
  const box = this._box(node)
@@ -669,7 +706,8 @@ export default class IcicleChart {
669
706
  const room = along - 8
670
707
  let label = node.name
671
708
  if (dl.showValue) {
672
- const full = `${node.name}: ${node.value}`
709
+ // Trimmed like the node tooltip, so a rolled-up 0.1 + 0.2 reads 0.3.
710
+ const full = `${node.name}: ${+node.value.toPrecision(12)}`
673
711
  if (this._fits(full, room, fontPx)) label = full
674
712
  }
675
713
  const text = this._truncate(label, room, fontPx)
@@ -726,7 +764,6 @@ export default class IcicleChart {
726
764
  * @param {any} node
727
765
  */
728
766
  _renderMoreMark(node) {
729
- if (!Environment.isBrowser()) return
730
767
  const box = this._box(node)
731
768
  const along = this._vertical ? box.w : box.h
732
769
  if (along < 18) return
@@ -790,22 +827,6 @@ export default class IcicleChart {
790
827
 
791
828
  // ----------------------------------------------------------------- zoom
792
829
 
793
- /**
794
- * A cell offers the pointer only while clicking it would change the view.
795
- * A leaf under the current focus, or the single root of a one-root tree,
796
- * resolves to the focus the reader is already on, and a pointer there
797
- * promises a zoom that cannot happen. Asked on every layout, because a zoom
798
- * changes the answer for every cell.
799
- * @param {any} node
800
- */
801
- _setCursor(node) {
802
- if (!Environment.isBrowser() || this.cfg.zoomOnClick === false) return
803
- node._el.node.style.cursor = resolveFocus(node, this._focus, this._roots)
804
- .changed
805
- ? 'pointer'
806
- : 'default'
807
- }
808
-
809
830
  /**
810
831
  * Focus a node (zoom in), or zoom out one level when the current focus is
811
832
  * clicked.
@@ -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) {
package/src/charts/Pie.js CHANGED
@@ -1278,17 +1278,11 @@ class Pie {
1278
1278
  }
1279
1279
 
1280
1280
  /**
1281
- * How far a clicked slice slides out, in px. 0 when the pull-out is off, when
1282
- * drilldown owns the click, and always for polarArea: there the radius
1283
- * encodes the value, so moving a slice outward would read as a bigger number.
1281
+ * How far a clicked slice slides out, in px (see Filters.sliceExpandOffset).
1284
1282
  * @returns {number}
1285
1283
  */
1286
1284
  getExpandOffset() {
1287
- const pie = this.w.config.plotOptions.pie
1288
- if (!pie.expandOnClick || this.chartType === 'polarArea') return 0
1289
- if (Filters.drilldownBlocksSliceOffset(this.w)) return 0
1290
- const offset = Number(pie.expandOffset)
1291
- return Number.isFinite(offset) && offset > 0 ? offset : 0
1285
+ return Filters.sliceExpandOffset(this.w)
1292
1286
  }
1293
1287
 
1294
1288
  /**
@@ -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 },
@@ -8,6 +8,7 @@ import Series from '../modules/Series'
8
8
  import { resolveClaimed } from '../modules/weave/Claims'
9
9
  import { BrowserAPIs } from '../ssr/BrowserAPIs'
10
10
  import { Environment } from '../utils/Environment'
11
+ import { resolveEasing } from '../modules/animations/Easing'
11
12
 
12
13
  /**
13
14
  * ApexCharts Radial Class for drawing Circle / Semi Circle Charts.
@@ -1055,15 +1056,10 @@ class Radial extends Pie {
1055
1056
  Number(cfg.animationSpeed) ||
1056
1057
  (isInitialMount ? anim.speed : anim.dynamicAnimation?.speed) ||
1057
1058
  800
1058
- const c1 = 1.70158
1059
- const c3 = c1 + 1
1060
1059
  return {
1061
1060
  speed,
1062
1061
  mount: isInitialMount,
1063
- ease: isInitialMount
1064
- ? (/** @type {number} */ t) =>
1065
- 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2)
1066
- : (/** @type {number} */ t) => 1 - Math.pow(1 - t, 3),
1062
+ ease: resolveEasing(isInitialMount ? 'easeOutBack' : 'easeOutCubic'),
1067
1063
  }
1068
1064
  }
1069
1065