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
@@ -0,0 +1,499 @@
1
+ // @ts-check
2
+ /**
3
+ * Highlight filter on treemaps. A tile keeps its box, faded; its part is the
4
+ * bottom share of the tile, solid, as tall as the part's share of the tile's
5
+ * value. No element is added: the part is drawn inside the tile's own fill, a
6
+ * vertical gradient with a hard stop (solid below the share, faded above),
7
+ * in the tile's own box units. So everything that moves or hit-tests a tile
8
+ * (its tweens, a zoom's camera and ghosts, the pointer, a cross-type morph)
9
+ * carries the part with no work here, and the tile is hovered wherever the
10
+ * pointer is on it, solid or faded.
11
+ *
12
+ * Treemap reaches this through one dispatch per render, after the layout,
13
+ * which returns the painter each tile hands its fill to. Nested parents are
14
+ * frames: they never fade, and know their leaves' parts through
15
+ * `node.highlight` (header and tooltip formatters already receive the node).
16
+ *
17
+ * @module modules/highlightFilter/TreemapPart
18
+ */
19
+
20
+ import Graphics from '../Graphics'
21
+ import { finite, mix, info, isPoint, stripSeries } from './util'
22
+
23
+ const TILE = 't:'
24
+ const CLASS = 'apexcharts-highlight-tile'
25
+ const OVER = 'apexcharts-highlight-overflow'
26
+ // A fill with no colour to cut a share from: a gradient, pattern or image.
27
+ const URL = /^url\(/i
28
+
29
+ /** @typedef {{s: number, f: number, c: string}} TileLook */
30
+
31
+ /**
32
+ * Parse side, before the parts are read: whether this is a nested treemap
33
+ * (its parts sit on its leaves), warning once about parts that cannot be
34
+ * placed there.
35
+ * @param {any} hf @param {string} type
36
+ */
37
+ export function treeParse(hf, type) {
38
+ const gl = hf.w.globals
39
+ if (type !== 'treemap' || !gl.treemapRoots) return false
40
+ const raw = /** @type {any[]} */ (gl.treemapRawSeries || [])
41
+ if (raw.some((s) => Array.isArray(s?.highlightData))) {
42
+ hf._warn(
43
+ 'nested',
44
+ 'on a nested treemap put the part on each leaf as { x, y, highlight }; highlightData is ignored.',
45
+ )
46
+ }
47
+ /** @param {any} d @returns {boolean} */
48
+ const onParent = (d) =>
49
+ isPoint(d) &&
50
+ Array.isArray(d.children) &&
51
+ d.children.length > 0 &&
52
+ ('highlight' in d || d.children.some(onParent))
53
+ if (raw.some((s) => (s?.data || []).some(onParent))) {
54
+ hf._warn(
55
+ 'parent',
56
+ "a parent's highlight is ignored: parents add up their leaves' parts.",
57
+ )
58
+ }
59
+ return true
60
+ }
61
+
62
+ /**
63
+ * set() on a nested treemap: the series as handed in with each leaf's part
64
+ * on the leaf itself, by its index among its series' leaves (depth first,
65
+ * as the chart numbers them). `parts` is one row per series, or a function
66
+ * of the leaf.
67
+ * @param {any} hf @param {any[]} base the raw nested series
68
+ * @param {any} parts
69
+ */
70
+ export function treeSeries(hf, base, parts) {
71
+ const w = hf.w
72
+ return base.map((s, i) => {
73
+ const out = stripSeries(s)
74
+ const row = Array.isArray(parts?.[i]) ? parts[i] : null
75
+ if (typeof parts !== 'function' && !row) return out
76
+ let k = 0
77
+ /** @param {any} d @returns {any} */
78
+ const leaf = (d) => {
79
+ if (isPoint(d) && Array.isArray(d.children) && d.children.length) {
80
+ return { ...d, children: d.children.map(leaf) }
81
+ }
82
+ const j = k++
83
+ const pt = isPoint(d) ? { ...d } : { x: '', y: d }
84
+ pt.highlight =
85
+ typeof parts === 'function'
86
+ ? parts({
87
+ seriesIndex: i,
88
+ dataPointIndex: j,
89
+ seriesName: s.name,
90
+ x: pt.x ?? pt.name,
91
+ value:
92
+ typeof (pt.y ?? pt.value) === 'number'
93
+ ? (pt.y ?? pt.value)
94
+ : null,
95
+ datum: d,
96
+ w,
97
+ })
98
+ : row?.[j]
99
+ return pt
100
+ }
101
+ if (Array.isArray(out.data)) out.data = out.data.map(leaf)
102
+ return out
103
+ })
104
+ }
105
+
106
+ /**
107
+ * Treemap.draw, once, after the layout and the zoom camera, before any
108
+ * parent or tile is drawn. Returns this render's tile painter, or undefined
109
+ * when nothing is highlighted now or was a frame ago.
110
+ * @param {any} hf the HighlightFilter
111
+ * @param {any} tm the Treemap renderer
112
+ */
113
+ export function treemapPass(hf, tm) {
114
+ const w = hf.w
115
+ const gl = w.globals
116
+ const hd = w.highlightData
117
+ if (!hd) return undefined
118
+ hf._beginRender(tm, TILE)
119
+ // An update on the fast path keeps <defs>: the last render's gradients go.
120
+ hf._tmDefs.forEach((/** @type {any} */ n) => n.parentNode?.removeChild(n))
121
+ hf._tmDefs = []
122
+ const tiles = (hf._tiles = new Map())
123
+ const active = hd.active
124
+ const vals = w.seriesData.series
125
+ // Every render, highlighted or not: a nested tree outlives a resize or a
126
+ // zoom, so a roll-up from an earlier pick would stay on it.
127
+ rollUp(tm, active ? hd.parts : null, vals)
128
+ const prevMap = hf._prev()
129
+ if (!active && !prevMap?.size) return undefined
130
+ // The same tiles by series and index: a series hidden from the legend lays
131
+ // out as one tile of nothing under a key of its own, which closes from the
132
+ // tile that stood first in that series.
133
+ /** @type {Map<string, any>} */
134
+ const byIJ = new Map()
135
+ prevMap?.forEach((/** @type {any} */ r) => byIJ.set(r.ij, r))
136
+
137
+ // A zoom's ghosts are what the last render drew: no longer tiles.
138
+ gl.prevTreemapView
139
+ ?.querySelectorAll(`.${CLASS}`)
140
+ .forEach((/** @type {any} */ n) => {
141
+ n.classList.remove(CLASS, OVER)
142
+ n.removeAttribute('data:hl-share')
143
+ })
144
+
145
+ const cfg = hf.cfg
146
+ const fadeTo = active ? (cfg.fadeOpacity ?? 0.2) : 1
147
+ const morph = hf.ctx.morphTypeChange?.isActive() === true
148
+ const dyn = tm.dynamicAnim
149
+ // The renderer's own rule for easing a tile (or a cross-type morph, whose
150
+ // tiles unroll on the morph's clock); the renderer kind plays no part,
151
+ // treemaps are always drawn in SVG.
152
+ const anim = morph || !!(gl.dataChanged && dyn.enabled && gl.shouldAnimate)
153
+ const speed = morph ? hf.ctx.morphTypeChange.getSpeed() : dyn.speed
154
+ const fore = w.config.chart.foreColor
155
+ let warned = false
156
+
157
+ if (active) wrapParentTip(hf, tm)
158
+ // A tile's label is drawn after its tile: it takes its tone from the share
159
+ // drawn under it from the start, and follows it as it moves. It reads as
160
+ // on the solid share once the share's edge has passed the top of its text
161
+ // (a label turned to fit, the top of its run).
162
+ /** @type {any} */
163
+ let bound = null
164
+ const cl = tm.helpers.calculateDataLabels
165
+ tm.helpers.calculateDataLabels = (/** @type {any} */ o) => {
166
+ const g = cl.call(tm.helpers, o)
167
+ const rec = (bound = tiles.get(o.i + '|' + o.j))
168
+ if (g && rec) {
169
+ const ts = texts(g.node)
170
+ rec.lb = ts.filter((t) =>
171
+ /^(#fff|#ffffff|white)$/i.test(t.getAttribute('fill') || ''),
172
+ )
173
+ const t = ts[0]
174
+ const [, y1, , y2] = rec.r
175
+ if (t && y2 > y1) {
176
+ const fs = parseFloat(t.getAttribute('font-size')) || 12
177
+ rec.need = (y2 - parseFloat(t.getAttribute('y')) + 0.9 * fs) / (y2 - y1)
178
+ }
179
+ tone(rec, fore)
180
+ }
181
+ return g
182
+ }
183
+ const rf = tm.rotateToFitLabel
184
+ tm.rotateToFitLabel = (/** @type {any[]} */ ...a) => {
185
+ rf.apply(tm, a)
186
+ const rec = bound
187
+ bound = null
188
+ if (rec?.lb && /rotate/.test(a[0].node.getAttribute('transform') || '')) {
189
+ const run = new Graphics(w).getTextRects(a[2], String(a[1])).width
190
+ rec.need = 0.5 + run / 2 / (a[6] - a[4])
191
+ rec.tone = null
192
+ tone(rec, fore)
193
+ }
194
+ }
195
+
196
+ /**
197
+ * @param {any} el the tile, not yet given its fill
198
+ * @param {number} i @param {number} j
199
+ * @param {string} pathFill its fill as the renderer worked it out
200
+ * @param {any} leaf its layout node
201
+ */
202
+ return (el, i, j, pathFill, leaf) => {
203
+ // A render that is no data change (a mount, a resize) draws each tile
204
+ // where it rests, whatever an older render left; so does an update
205
+ // sent without animation, which captured nothing.
206
+ const key = TILE + leaf._key
207
+ const ij = i + '|' + j
208
+ const whole = vals[i]?.[j]
209
+ const prev = anim
210
+ ? prevMap?.get(key) || (whole ? undefined : byIJ.get(ij))
211
+ : undefined
212
+ if (!active && !prev) return undefined
213
+ if (URL.test(pathFill)) {
214
+ if (active && !warned) {
215
+ warned = true
216
+ hf._warn(
217
+ 'fill',
218
+ 'treemap tiles with a gradient, pattern or image fill are drawn without their parts.',
219
+ )
220
+ }
221
+ return undefined
222
+ }
223
+ const p = active ? hd.parts[i]?.[j] : null
224
+ // A tile of nothing has no share to draw.
225
+ if (!whole && !prev) return undefined
226
+ const share = finite(p) && whole ? p / whole : null
227
+
228
+ /** @type {TileLook} */
229
+ let to = active
230
+ ? {
231
+ s: share == null || share < 0 ? 0 : Math.min(share, 1),
232
+ f: fadeTo,
233
+ c: pathFill,
234
+ }
235
+ : // A clear grows the part back over its tile, the faded rest at 0
236
+ // under it, and lands on the plain tile.
237
+ { s: 1, f: 0, c: pathFill }
238
+ /** @type {TileLook} */
239
+ let from = to
240
+ if (prev) {
241
+ from = { s: prev.s, f: prev.f, c: prev.col }
242
+ // A tile with nothing left (a series hidden from the legend) keeps
243
+ // the look it has while it closes.
244
+ if (!whole && active) to = { ...from }
245
+ } else if (anim) {
246
+ const was = /** @type {any} */ (gl.previousPaths[i])?.[j]
247
+ // A tile on screen until now, plain: the pick starts as that tile
248
+ // (the part covers it, the faded rest at 0), or rises from its base.
249
+ if (morph || was?.rect?.width > 0) {
250
+ from =
251
+ cfg.enter === 'baseline'
252
+ ? { s: 0, f: 1, c: to.c }
253
+ : { s: 1, f: 0, c: to.c }
254
+ if (!morph && was.fill && !URL.test(was.fill)) from.c = was.fill
255
+ }
256
+ }
257
+ const moves = from.s !== to.s || from.f !== to.f || from.c !== to.c
258
+ // A clear with nothing to move is the plain tile.
259
+ if (!active && !moves) return undefined
260
+
261
+ const g = w.dom.Paper.gradient('linear', (/** @type {any} */ add) => {
262
+ for (let k = 0; k < 4; k++) add.stop(0, pathFill, 1)
263
+ })
264
+ // Bottom to top, in the tile's own box: it rides every resize of it.
265
+ g.from(0, 1).to(0, 0)
266
+ hf._tmDefs.push(g.node)
267
+ const stops = Array.from(g.node.childNodes)
268
+ const node = el.node
269
+ if (active) {
270
+ node.setAttribute(
271
+ 'class',
272
+ `${node.getAttribute('class') || ''} ${CLASS}${share != null && share > 1 ? ' ' + OVER : ''}`.trim(),
273
+ )
274
+ node.setAttribute('data:hl-share', share == null ? '' : String(share))
275
+ }
276
+
277
+ /** What this tile draws, for the next update to start from. */
278
+ /** @type {any} */
279
+ const rec = {
280
+ s: to.s,
281
+ f: to.f,
282
+ col: to.c,
283
+ c: !active,
284
+ ij,
285
+ run: false,
286
+ base: pathFill,
287
+ r: leaf.rect,
288
+ lb: null,
289
+ need: 0.5,
290
+ tone: null,
291
+ }
292
+ hf._targets.set(key, rec)
293
+ tiles.set(ij, rec)
294
+ const ease = colourEase(from.c, to.c)
295
+ /** @param {TileLook} L */
296
+ const write = (L) => {
297
+ rec.ls = L.s
298
+ rec.lf = L.f
299
+ rec.lc = L.c
300
+ stops.forEach((/** @type {any} */ n, /** @type {number} */ k) => {
301
+ n.setAttribute('offset', String(k === 0 ? 0 : k === 3 ? 1 : L.s))
302
+ n.setAttribute('stop-color', L.c)
303
+ n.setAttribute('stop-opacity', String(k < 2 ? 1 : L.f))
304
+ })
305
+ tone(rec, fore)
306
+ }
307
+ const land = () => {
308
+ rec.run = false
309
+ write(to)
310
+ if (!active && node.isConnected) {
311
+ // The plain tile: its own fill, and the gradient gone.
312
+ node.setAttribute('fill', pathFill)
313
+ g.node.parentNode?.removeChild(g.node)
314
+ }
315
+ }
316
+ if (anim && moves) {
317
+ rec.run = true
318
+ write(from)
319
+ // An export lands the fade only: the share is geometry and moves on
320
+ // with its tile. A clear has nothing else to show, so it lands.
321
+ /** @type {number | null} */
322
+ let f = null
323
+ let done = false
324
+ const job = {
325
+ finish() {
326
+ hf._live.delete(job)
327
+ if (active) write({ s: rec.ls, f: (f = to.f), c: rec.lc })
328
+ else {
329
+ done = true
330
+ land()
331
+ }
332
+ },
333
+ }
334
+ hf._hold(job)
335
+ // On a runner of its own, started in the same flush as the tile's and
336
+ // on the same curve, so the share and the box move as one.
337
+ g.animate(speed, 0)
338
+ .during(
339
+ (/** @type {number} */ t) =>
340
+ done ||
341
+ write({
342
+ s: mix(from.s, to.s, t),
343
+ f: f ?? mix(from.f, to.f, t),
344
+ c: ease(t),
345
+ }),
346
+ )
347
+ .after(() => {
348
+ hf._live.delete(job)
349
+ done || land()
350
+ })
351
+ } else write(to)
352
+ return g.url()
353
+ }
354
+ }
355
+
356
+ /**
357
+ * Each node's part: a leaf's own, and a parent's the sum of its leaves'
358
+ * (each as far as it agrees in sign with its leaf) against the parent's
359
+ * area, the layout's own sum of the leaves' sizes. Written on every node of
360
+ * the tree before anything is drawn, or cleared when nothing is highlighted.
361
+ * @param {any} tm @param {any[] | null} parts @param {any[]} vals
362
+ */
363
+ function rollUp(tm, parts, vals) {
364
+ /** @param {any} n @returns {any} */
365
+ const walk = (n) => {
366
+ const kids = n.children
367
+ if (!kids || !kids.length) {
368
+ const p = parts?.[n._si]?.[n._di]
369
+ n.highlight = parts
370
+ ? info(finite(p) ? p : null, vals[n._si]?.[n._di])
371
+ : undefined
372
+ return n.highlight
373
+ }
374
+ /** @type {number | null} */
375
+ let v = null
376
+ kids.forEach((/** @type {any} */ c) => {
377
+ const h = walk(c)
378
+ if (h && h.value != null && !(h.value * (h.total || 0) < 0)) {
379
+ v = (v || 0) + Math.abs(h.value)
380
+ }
381
+ })
382
+ if (!parts) return (n.highlight = undefined)
383
+ const total = tm._subtreeArea(n)
384
+ const share = v != null && total ? v / total : null
385
+ n.highlight = {
386
+ value: v,
387
+ total,
388
+ share,
389
+ overflow: share != null && share > 1,
390
+ }
391
+ return n.highlight
392
+ }
393
+ ;(tm.roots || []).forEach(walk)
394
+ }
395
+
396
+ /**
397
+ * A parent's default tooltip row states its leaves' parts against its total,
398
+ * as a tile's row does. A custom formatter is handed `node.highlight`.
399
+ * @param {any} hf @param {any} tm
400
+ */
401
+ function wrapParentTip(hf, tm) {
402
+ const show = tm._showParentTooltip
403
+ tm._showParentTooltip = (/** @type {any} */ e, /** @type {any} */ node) => {
404
+ show.call(tm, e, node)
405
+ const h = node.highlight
406
+ const tt = hf.cfg.tooltip || {}
407
+ if (
408
+ h?.value == null ||
409
+ tt.show === false ||
410
+ typeof hf.w.config.plotOptions.treemap.parents?.tooltip?.formatter ===
411
+ 'function'
412
+ ) {
413
+ return
414
+ }
415
+ const v = tm._tip()?.querySelector('.apexcharts-tooltip-text-y-value')
416
+ if (!v) return
417
+ let rest = `/ ${tm._formatValue(h.total)}`
418
+ if (tt.share && h.total) rest += ` · ${Math.round(h.share * 100)}%`
419
+ v.innerHTML =
420
+ `${tm._formatValue(h.value)} ` +
421
+ `<span class="apexcharts-highlight-total" style="font-weight: 400; opacity: 0.6">${rest}</span>`
422
+ }
423
+ }
424
+
425
+ /**
426
+ * A white label reads on the solid share but not on the faded tint: until
427
+ * the share drawn under it reaches the top of its text, it takes the chart's
428
+ * text colour.
429
+ * @param {any} rec @param {string} fore
430
+ */
431
+ function tone(rec, fore) {
432
+ const on = (rec.ls ?? rec.s) >= rec.need - 1e-9
433
+ if (!rec.lb || rec.tone === on) return
434
+ rec.tone = on
435
+ rec.lb.forEach((/** @type {any} */ t) => {
436
+ if (t._apxFill == null) t._apxFill = t.getAttribute('fill')
437
+ t.setAttribute('fill', on ? t._apxFill : fore)
438
+ })
439
+ }
440
+
441
+ /**
442
+ * Every text element under a node (walked by hand: the server renderer's
443
+ * elements answer no selectors).
444
+ * @param {any} n
445
+ * @returns {any[]}
446
+ */
447
+ function texts(n) {
448
+ /** @type {any[]} */
449
+ const out = []
450
+ ;(function walk(/** @type {any} */ x) {
451
+ if (String(x.tagName || x.nodeName).toLowerCase() === 'text') out.push(x)
452
+ Array.from(x.childNodes || []).forEach(walk)
453
+ })(n)
454
+ return out
455
+ }
456
+
457
+ /**
458
+ * A colour from `a` to `b` at progress t. Colours it cannot read switch on
459
+ * landing.
460
+ * @param {string} a @param {string} b
461
+ * @returns {(t: number) => string}
462
+ */
463
+ function colourEase(a, b) {
464
+ const x = rgba(a)
465
+ const y = rgba(b)
466
+ if (a === b || !x || !y) return (t) => (t >= 1 ? b : a)
467
+ return (t) =>
468
+ t >= 1
469
+ ? b
470
+ : `rgba(${[0, 1, 2].map((k) => Math.round(mix(x[k], y[k], t))).join(',')},${+mix(x[3], y[3], t).toFixed(3)})`
471
+ }
472
+
473
+ /**
474
+ * `#rgb`, `#rrggbb` (with or without alpha) and `rgb()`/`rgba()` as
475
+ * [r, g, b, a], or null.
476
+ * @param {string} c
477
+ * @returns {number[] | null}
478
+ */
479
+ function rgba(c) {
480
+ const s = String(c).trim()
481
+ let m = /^#([\da-f]+)$/i.exec(s)
482
+ if (m) {
483
+ let h = m[1]
484
+ if (h.length < 5) h = h.replace(/./g, '$&$&')
485
+ if (h.length !== 6 && h.length !== 8) return null
486
+ return [0, 2, 4, 6].map((k) =>
487
+ k < h.length ? parseInt(h.slice(k, k + 2), 16) / (k === 6 ? 255 : 1) : 1,
488
+ )
489
+ }
490
+ m = /^rgba?\(([^)]*)\)$/i.exec(s)
491
+ if (!m) return null
492
+ const v = m[1]
493
+ .split(/[\s,/]+/)
494
+ .filter(Boolean)
495
+ .map(parseFloat)
496
+ return v.length >= 3 && v.every(isFinite)
497
+ ? [v[0], v[1], v[2], v[3] ?? 1]
498
+ : null
499
+ }