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
@@ -5,9 +5,8 @@ import Fill from '../modules/Fill'
5
5
  import Graphics from '../modules/Graphics'
6
6
  import Series from '../modules/Series'
7
7
  import Utils from '../utils/Utils'
8
- import { buildJitterGroups, renderJitter } from './common/Jitter'
8
+ import { buildJitterGroups, jitterExtent, renderJitter } from './common/Jitter'
9
9
  import {
10
- datumKey,
11
10
  lengthTransitionEnabled,
12
11
  renderBarExitGhosts,
13
12
  } from '../modules/animations/LengthTransition'
@@ -55,7 +54,7 @@ class BoxCandleStick extends Bar {
55
54
  if (!keyed || keyed.size === 0 || !row || row.length === 0) return false
56
55
  let survivors = 0
57
56
  for (let j = 0; j < row.length; j++) {
58
- if (keyed.has(datumKey(this.w, realIndex, j))) survivors++
57
+ if (keyed.has(this._keys(realIndex)[j])) survivors++
59
58
  }
60
59
  return survivors / keyed.size < 0.5
61
60
  }
@@ -86,7 +85,7 @@ class BoxCandleStick extends Bar {
86
85
  }
87
86
  this._prevHalves[realIndex] = map
88
87
  }
89
- const halves = map && map.get(datumKey(this.w, realIndex, j))
88
+ const halves = map && map.get(this._keys(realIndex)[j])
90
89
  return halves && halves.length === 2 ? halves[pi] : null
91
90
  }
92
91
 
@@ -105,15 +104,13 @@ class BoxCandleStick extends Bar {
105
104
  this.candlestickOptions = this.w.config.plotOptions.candlestick
106
105
  this.boxOptions = this.w.config.plotOptions.boxPlot
107
106
  this.isHorizontal = w.config.plotOptions.bar.horizontal
108
- this.isOHLC =
109
- this.candlestickOptions && this.candlestickOptions.type === 'ohlc'
110
107
 
111
108
  this.coreUtils = new CoreUtils(this.w)
112
109
  series = this.coreUtils.getLogSeries(series)
113
110
  this.series = series
114
111
  this.yRatio = this.coreUtils.getLogYRatios(this.yRatio)
115
112
 
116
- this.barHelpers.initVariables(series)
113
+ this.barHelpers.initVariables(series, seriesIndex)
117
114
 
118
115
  const ret = graphics.group({
119
116
  class: `apexcharts-${type}-series apexcharts-plot-series`,
@@ -124,6 +121,8 @@ class BoxCandleStick extends Bar {
124
121
  // beside candles), and `i` counts only this type's series, not the
125
122
  // config's: reading either drew a candle as a box, or a box as a candle.
126
123
  this.isBoxPlot = type === 'boxPlot'
124
+ this.isOHLC = !this.isBoxPlot && this.candlestickOptions?.type === 'ohlc'
125
+ const jx = jitterExtent(w.candleData.seriesBoxPoints, w)
127
126
 
128
127
  for (let i = 0; i < series.length; i++) {
129
128
  /** @type {any} */
@@ -264,7 +263,7 @@ class BoxCandleStick extends Bar {
264
263
  yArrj.push(y)
265
264
 
266
265
  // drawVerticalBoxPaths returns culled:true for off-screen bars (it
267
- // skipped the path-string build). Horizontal bars are never culled.
266
+ // skipped the path-string build), and both do for a null datum.
268
267
  if (paths.culled) {
269
268
  continue
270
269
  }
@@ -310,6 +309,7 @@ class BoxCandleStick extends Bar {
310
309
  i,
311
310
  pathFrom: this._prevBoxHalf(realIndex, j, pi) ?? paths.pathFrom,
312
311
  fadeReveal,
312
+ noLabel: pi > 0,
313
313
  pathTo,
314
314
  strokeWidth,
315
315
  elSeries,
@@ -343,14 +343,14 @@ class BoxCandleStick extends Bar {
343
343
  )
344
344
  let center, halfExtent, alongFn
345
345
  if (this.isHorizontal) {
346
- const yRatio = this.invertedYRatio
346
+ const yRatio = this.invertedYRatio * (this.isReversed ? -1 : 1)
347
347
  const bh = barHeight ?? 0
348
348
  const z = zeroW ?? 0
349
349
  center = paths.barYPosition + bh / 2
350
350
  halfExtent = bh / 2
351
351
  alongFn = (/** @type {number} */ v) => z + logVal(v) / yRatio
352
352
  } else {
353
- const yRatio = this.yRatio[translationsIndex]
353
+ const yRatio = this.yRatio[translationsIndex] * (this.isReversed ? -1 : 1)
354
354
  const bw = barWidth ?? 0
355
355
  const z = zeroH ?? 0
356
356
  center = paths.barXPosition + bw / 2
@@ -358,8 +358,8 @@ class BoxCandleStick extends Bar {
358
358
  alongFn = (/** @type {number} */ v) => z - logVal(v) / yRatio
359
359
  }
360
360
  const groups = buildJitterGroups({
361
- w,
362
361
  points: pts,
362
+ extent: jx,
363
363
  seedA: realIndex,
364
364
  seedB: j,
365
365
  center,
@@ -397,18 +397,16 @@ class BoxCandleStick extends Bar {
397
397
  // gone (a series hidden from the legend, rows removed) shrink away under
398
398
  // the survivors instead of vanishing. Keyed by every datum the series
399
399
  // still has, culled ones included: a candle only scrolled off-screen
400
- // has not left, it is just not drawn.
400
+ // has not left, it is just not drawn. One turned null has left.
401
401
  // (Not when the series fades: the fade replaces the whole set at once.)
402
402
  if (w.globals.previousPaths.length > 0 && !fadeReveal) {
403
- const newKeys = []
404
- for (let j = 0; j < series[i].length; j++) {
405
- newKeys.push(datumKey(w, realIndex, j))
406
- }
407
403
  renderBarExitGhosts({
408
404
  w,
409
405
  elSeries,
410
406
  record: this._prevRecord(realIndex),
411
- newKeys,
407
+ newKeys: this._keys(realIndex).filter(
408
+ (_, j) => series[i][j] != null,
409
+ ),
412
410
  isHorizontal: this.isHorizontal,
413
411
  speed: w.config.chart.animations.dynamicAnimation.speed,
414
412
  })
@@ -449,7 +447,7 @@ class BoxCandleStick extends Bar {
449
447
  const colorPos = getColor(candleColors.upward)
450
448
  const colorNeg = getColor(candleColors.downward)
451
449
 
452
- const yRatio = this.yRatio[indexes.translationsIndex]
450
+ const yRatio = this.yRatio[indexes.translationsIndex] * (this.isReversed ? -1 : 1)
453
451
 
454
452
  const ohlc = this.getOHLCValue(realIndex, j)
455
453
  let l1 = zeroH
@@ -478,10 +476,9 @@ class BoxCandleStick extends Bar {
478
476
  barXPosition = pos.barXPosition
479
477
  }
480
478
 
481
- if (
482
- typeof /** @type {any} */ (this.series)[i]?.[j] === 'undefined' ||
483
- /** @type {any} */ (this.series)[i]?.[j] === null
484
- ) {
479
+ // a null or missing datum draws nothing, culled like an off-screen one
480
+ const hole = /** @type {any} */ (this.series)[i]?.[j] == null
481
+ if (hole) {
485
482
  y1 = zeroH
486
483
  y2 = zeroH
487
484
  } else {
@@ -506,10 +503,11 @@ class BoxCandleStick extends Bar {
506
503
  // are bounded by what was visible before, and large datasets skip the
507
504
  // morph for the bulk fade anyway.
508
505
  if (
509
- cullBounds &&
510
- (barXPosition + barWidth < cullBounds.lo ||
511
- barXPosition > cullBounds.hi) &&
512
- !this._wasOnScreen(realIndex, j)
506
+ hole ||
507
+ (cullBounds &&
508
+ (barXPosition + barWidth < cullBounds.lo ||
509
+ barXPosition > cullBounds.hi) &&
510
+ !this._wasOnScreen(realIndex, j))
513
511
  ) {
514
512
  return {
515
513
  pathTo: null,
@@ -646,7 +644,7 @@ class BoxCandleStick extends Bar {
646
644
  const getColor = (color) =>
647
645
  Array.isArray(color) ? color[realIndex] : color
648
646
 
649
- const yRatio = this.invertedYRatio
647
+ const yRatio = this.invertedYRatio * (this.isReversed ? -1 : 1)
650
648
  const ohlc = this.getOHLCValue(realIndex, j)
651
649
 
652
650
  let color =
@@ -669,10 +667,8 @@ class BoxCandleStick extends Bar {
669
667
  // Bar.drawBarPaths.
670
668
  const barYPosition = y + barHeight * this.visibleI
671
669
 
672
- if (
673
- typeof /** @type {any} */ (this.series)[i]?.[j] === 'undefined' ||
674
- /** @type {any} */ (this.series)[i]?.[j] === null
675
- ) {
670
+ const hole = /** @type {any} */ (this.series)[i]?.[j] == null
671
+ if (hole) {
676
672
  x1 = zeroW
677
673
  x2 = zeroW
678
674
  } else {
@@ -743,6 +739,7 @@ class BoxCandleStick extends Bar {
743
739
  ),
744
740
  barYPosition,
745
741
  color,
742
+ culled: hole,
746
743
  }
747
744
  }
748
745
 
@@ -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.
@@ -378,13 +388,15 @@ export default class IcicleChart {
378
388
  // (`dynamicAnimation.speed`) like an update, NOT on `animations.speed`,
379
389
  // which paces the first render. Reading the intro's clock made a click take
380
390
  // 800ms by default, which feels like lag rather than motion.
381
- const dur = !anims.enabled
382
- ? 0
383
- : mode === 'none'
391
+ const dyn = anims.dynamicAnimation
392
+ const dur =
393
+ !anims.enabled || mode === 'none'
384
394
  ? 0
385
- : mode === 'update' || mode === 'zoom'
386
- ? anims.dynamicAnimation.speed || 350
387
- : anims.speed || 500
395
+ : mode === 'intro'
396
+ ? (anims.speed ?? 500)
397
+ : dyn.enabled
398
+ ? (dyn.speed ?? 350)
399
+ : 0
388
400
 
389
401
  // Supersede any in-flight zoom: stale frames from the previous pass check
390
402
  // this and stop.
@@ -401,7 +413,7 @@ export default class IcicleChart {
401
413
  if (!node._el) node._el = this._createCellEl(node)
402
414
  // Per-layout, not per-element: a zoom changes which branches are cut.
403
415
  node._el.node.setAttribute('data:clipped', String(!!node._clipped))
404
- this._setCursor(node)
416
+ setZoomCursor(this, node)
405
417
 
406
418
  if (mode === 'intro' && dur > 0) {
407
419
  this._wipeCell(node, to, dur, gen)
@@ -415,7 +427,7 @@ export default class IcicleChart {
415
427
  // interrupted zoom continues from where it actually is.
416
428
  from = node._cur
417
429
  } else if (prev && prev.get(node._key)) {
418
- from = prev.get(node._key) // survived a data update: tween in place
430
+ from = prev.get(node._key)() // survived a data update: tween in place
419
431
  } else {
420
432
  // A new cell grows out of the middle of the slot it is taking.
421
433
  from = {
@@ -439,10 +451,12 @@ export default class IcicleChart {
439
451
  }
440
452
  })
441
453
 
442
- // Stash what is now on screen so the NEXT data update can tween from it.
454
+ // Stash what is on screen so the NEXT data update can tween from it: read
455
+ // live, so an update landing mid-tween starts where the cell actually is.
443
456
  const geoms = new Map()
444
457
  this._nodesAll.forEach((n) => {
445
- if (n._show) geoms.set(n._key, this._box(n))
458
+ const b = this._box(n)
459
+ if (n._show) geoms.set(n._key, () => n._cur || b)
446
460
  })
447
461
  ;/** @type {any} */ (this.ctx)._iciclePrevGeoms = geoms
448
462
 
@@ -624,11 +638,14 @@ export default class IcicleChart {
624
638
  if (node._clipped) this._renderMoreMark(node)
625
639
  })
626
640
 
641
+ // Gen-checked: a superseded zoom's fade must not reveal labels over cells
642
+ // the newer zoom is still moving.
643
+ const gen = this._zoomGen
644
+ labelsG.attr({ opacity: dur > 0 ? 0 : 1 })
627
645
  if (dur > 0) {
628
- labelsG.attr({ opacity: 0 })
629
- labelsG.animate(250, dur).attr({ opacity: 1 })
630
- } else {
631
- labelsG.attr({ opacity: 1 })
646
+ labelsG.animate(250, dur).during((/** @type {number} */ p) => {
647
+ if (this._zoomGen === gen) labelsG.attr({ opacity: p })
648
+ })
632
649
  }
633
650
  }
634
651
 
@@ -642,7 +659,6 @@ export default class IcicleChart {
642
659
  * @param {any} node
643
660
  */
644
661
  _renderLabel(node) {
645
- if (!Environment.isBrowser()) return
646
662
  const dl = this.cfg.dataLabels
647
663
  const style = dl.style
648
664
  const box = this._box(node)
@@ -669,7 +685,8 @@ export default class IcicleChart {
669
685
  const room = along - 8
670
686
  let label = node.name
671
687
  if (dl.showValue) {
672
- const full = `${node.name}: ${node.value}`
688
+ // Trimmed like the node tooltip, so a rolled-up 0.1 + 0.2 reads 0.3.
689
+ const full = `${node.name}: ${+node.value.toPrecision(12)}`
673
690
  if (this._fits(full, room, fontPx)) label = full
674
691
  }
675
692
  const text = this._truncate(label, room, fontPx)
@@ -726,7 +743,6 @@ export default class IcicleChart {
726
743
  * @param {any} node
727
744
  */
728
745
  _renderMoreMark(node) {
729
- if (!Environment.isBrowser()) return
730
746
  const box = this._box(node)
731
747
  const along = this._vertical ? box.w : box.h
732
748
  if (along < 18) return
@@ -790,22 +806,6 @@ export default class IcicleChart {
790
806
 
791
807
  // ----------------------------------------------------------------- zoom
792
808
 
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
809
  /**
810
810
  * Focus a node (zoom in), or zoom out one level when the current focus is
811
811
  * clicked.