highcharts 12.0.2 → 12.1.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 (331) hide show
  1. package/bower.json +1 -1
  2. package/es-modules/Accessibility/Options/A11yDefaults.js +2 -0
  3. package/es-modules/Core/Color/Color.js +5 -12
  4. package/es-modules/Core/Renderer/HTML/HTMLElement.js +1 -3
  5. package/es-modules/Core/Renderer/SVG/SVGElement.js +3 -1
  6. package/es-modules/Core/Renderer/SVG/SVGLabel.js +8 -11
  7. package/es-modules/Core/Series/DataLabel.js +3 -1
  8. package/es-modules/Core/Series/Series.js +13 -15
  9. package/es-modules/Core/Templating.js +14 -10
  10. package/es-modules/Core/Time.js +6 -3
  11. package/es-modules/Core/Utilities.js +1 -1
  12. package/es-modules/Data/Converters/CSVConverter.js +1 -0
  13. package/es-modules/Data/Converters/DataConverter.js +31 -0
  14. package/es-modules/Data/Converters/GoogleSheetsConverter.js +1 -0
  15. package/es-modules/Data/Converters/HTMLTableConverter.js +1 -0
  16. package/es-modules/Data/Converters/JSONConverter.js +1 -0
  17. package/es-modules/Extensions/Boost/BoostSeries.js +13 -7
  18. package/es-modules/Extensions/DragPanes/AxisResizer.js +1 -1
  19. package/es-modules/Extensions/SeriesLabel/SeriesLabelDefaults.js +7 -2
  20. package/es-modules/Series/Bubble/BubbleSeries.js +24 -0
  21. package/es-modules/Series/Organization/OrganizationSeriesDefaults.js +3 -1
  22. package/es-modules/Series/Timeline/TimelineSeriesDefaults.js +3 -1
  23. package/es-modules/Series/Treegraph/TreegraphSeriesDefaults.js +3 -1
  24. package/es-modules/Series/Treemap/TreemapPoint.js +7 -2
  25. package/es-modules/Series/Treemap/TreemapSeries.js +154 -53
  26. package/es-modules/Series/Treemap/TreemapSeriesDefaults.js +126 -4
  27. package/es-modules/Stock/Indicators/VBP/VBPIndicator.js +1 -0
  28. package/es-modules/Stock/RangeSelector/RangeSelector.js +68 -72
  29. package/es-modules/Stock/RangeSelector/RangeSelectorDefaults.js +10 -4
  30. package/es-modules/masters/indicators/indicators-all.src.js +4 -0
  31. package/es-modules/tsconfig.tsbuildinfo +1 -1
  32. package/highcharts-3d.js +2 -2
  33. package/highcharts-3d.src.js +1 -1
  34. package/highcharts-gantt.js +5 -5
  35. package/highcharts-gantt.src.js +140 -141
  36. package/highcharts-more.js +2 -2
  37. package/highcharts-more.src.js +25 -1
  38. package/highcharts.d.ts +281 -762
  39. package/highcharts.js +3 -3
  40. package/highcharts.src.d.ts +281 -762
  41. package/highcharts.src.js +57 -60
  42. package/highmaps.js +5 -5
  43. package/highmaps.src.js +84 -63
  44. package/highstock.js +5 -5
  45. package/highstock.src.js +140 -141
  46. package/indicators/acceleration-bands.js +2 -2
  47. package/indicators/acceleration-bands.src.js +1 -1
  48. package/indicators/accumulation-distribution.js +2 -2
  49. package/indicators/accumulation-distribution.src.js +1 -1
  50. package/indicators/ao.js +2 -2
  51. package/indicators/ao.src.js +1 -1
  52. package/indicators/apo.js +2 -2
  53. package/indicators/apo.src.js +1 -1
  54. package/indicators/aroon-oscillator.js +2 -2
  55. package/indicators/aroon-oscillator.src.js +1 -1
  56. package/indicators/aroon.js +2 -2
  57. package/indicators/aroon.src.js +1 -1
  58. package/indicators/atr.js +2 -2
  59. package/indicators/atr.src.js +1 -1
  60. package/indicators/bollinger-bands.js +2 -2
  61. package/indicators/bollinger-bands.src.js +1 -1
  62. package/indicators/cci.js +2 -2
  63. package/indicators/cci.src.js +1 -1
  64. package/indicators/chaikin.js +2 -2
  65. package/indicators/chaikin.src.js +1 -1
  66. package/indicators/cmf.js +2 -2
  67. package/indicators/cmf.src.js +1 -1
  68. package/indicators/cmo.js +2 -2
  69. package/indicators/cmo.src.js +1 -1
  70. package/indicators/dema.js +2 -2
  71. package/indicators/dema.src.js +1 -1
  72. package/indicators/disparity-index.js +2 -2
  73. package/indicators/disparity-index.src.js +1 -1
  74. package/indicators/dmi.js +2 -2
  75. package/indicators/dmi.src.js +1 -1
  76. package/indicators/dpo.js +2 -2
  77. package/indicators/dpo.src.js +1 -1
  78. package/indicators/ema.js +1 -1
  79. package/indicators/ichimoku-kinko-hyo.js +2 -2
  80. package/indicators/ichimoku-kinko-hyo.src.js +1 -1
  81. package/indicators/indicators-all.js +2 -2
  82. package/indicators/indicators-all.src.js +6 -1
  83. package/indicators/indicators.js +2 -2
  84. package/indicators/indicators.src.js +1 -1
  85. package/indicators/keltner-channels.js +2 -2
  86. package/indicators/keltner-channels.src.js +1 -1
  87. package/indicators/klinger.js +2 -2
  88. package/indicators/klinger.src.js +1 -1
  89. package/indicators/macd.js +2 -2
  90. package/indicators/macd.src.js +1 -1
  91. package/indicators/mfi.js +2 -2
  92. package/indicators/mfi.src.js +1 -1
  93. package/indicators/momentum.js +2 -2
  94. package/indicators/momentum.src.js +1 -1
  95. package/indicators/natr.js +2 -2
  96. package/indicators/natr.src.js +1 -1
  97. package/indicators/obv.js +2 -2
  98. package/indicators/obv.src.js +1 -1
  99. package/indicators/pivot-points.js +2 -2
  100. package/indicators/pivot-points.src.js +1 -1
  101. package/indicators/ppo.js +2 -2
  102. package/indicators/ppo.src.js +1 -1
  103. package/indicators/price-channel.js +2 -2
  104. package/indicators/price-channel.src.js +1 -1
  105. package/indicators/price-envelopes.js +2 -2
  106. package/indicators/price-envelopes.src.js +1 -1
  107. package/indicators/psar.js +2 -2
  108. package/indicators/psar.src.js +1 -1
  109. package/indicators/regressions.js +2 -2
  110. package/indicators/regressions.src.js +1 -1
  111. package/indicators/roc.js +2 -2
  112. package/indicators/roc.src.js +1 -1
  113. package/indicators/rsi.js +2 -2
  114. package/indicators/rsi.src.js +1 -1
  115. package/indicators/slow-stochastic.js +2 -2
  116. package/indicators/slow-stochastic.src.js +1 -1
  117. package/indicators/stochastic.js +2 -2
  118. package/indicators/stochastic.src.js +1 -1
  119. package/indicators/supertrend.js +2 -2
  120. package/indicators/supertrend.src.js +1 -1
  121. package/indicators/tema.js +2 -2
  122. package/indicators/tema.src.js +1 -1
  123. package/indicators/trendline.js +2 -2
  124. package/indicators/trendline.src.js +1 -1
  125. package/indicators/trix.js +2 -2
  126. package/indicators/trix.src.js +1 -1
  127. package/indicators/volume-by-price.js +2 -2
  128. package/indicators/volume-by-price.src.js +2 -1
  129. package/indicators/vwap.js +2 -2
  130. package/indicators/vwap.src.js +1 -1
  131. package/indicators/williams-r.js +2 -2
  132. package/indicators/williams-r.src.js +1 -1
  133. package/indicators/wma.js +2 -2
  134. package/indicators/wma.src.js +1 -1
  135. package/indicators/zigzag.js +2 -2
  136. package/indicators/zigzag.src.js +1 -1
  137. package/modules/accessibility.js +2 -2
  138. package/modules/accessibility.src.js +3 -1
  139. package/modules/annotations-advanced.js +3 -3
  140. package/modules/annotations-advanced.src.js +4 -4
  141. package/modules/annotations.js +2 -2
  142. package/modules/annotations.src.js +3 -3
  143. package/modules/arc-diagram.js +2 -2
  144. package/modules/arc-diagram.src.js +1 -1
  145. package/modules/arrow-symbols.js +2 -2
  146. package/modules/arrow-symbols.src.js +1 -1
  147. package/modules/boost-canvas.js +2 -2
  148. package/modules/boost-canvas.src.js +14 -11
  149. package/modules/boost.js +2 -2
  150. package/modules/boost.src.js +14 -11
  151. package/modules/broken-axis.js +2 -2
  152. package/modules/broken-axis.src.js +1 -1
  153. package/modules/bullet.js +2 -2
  154. package/modules/bullet.src.js +1 -1
  155. package/modules/coloraxis.js +2 -2
  156. package/modules/coloraxis.src.js +1 -1
  157. package/modules/current-date-indicator.js +2 -2
  158. package/modules/current-date-indicator.src.js +1 -1
  159. package/modules/cylinder.js +2 -2
  160. package/modules/cylinder.src.js +1 -1
  161. package/modules/data-tools.js +2 -2
  162. package/modules/data-tools.src.js +36 -1
  163. package/modules/data.js +2 -2
  164. package/modules/data.src.js +1 -1
  165. package/modules/datagrouping.js +2 -2
  166. package/modules/datagrouping.src.js +1 -1
  167. package/modules/debugger.js +2 -2
  168. package/modules/debugger.src.js +1 -1
  169. package/modules/dependency-wheel.js +2 -2
  170. package/modules/dependency-wheel.src.js +1 -1
  171. package/modules/dotplot.js +2 -2
  172. package/modules/dotplot.src.js +1 -1
  173. package/modules/drag-panes.js +2 -2
  174. package/modules/drag-panes.src.js +2 -2
  175. package/modules/draggable-points.js +2 -2
  176. package/modules/draggable-points.src.js +1 -1
  177. package/modules/drilldown.js +2 -2
  178. package/modules/drilldown.src.js +1 -1
  179. package/modules/dumbbell.js +2 -2
  180. package/modules/dumbbell.src.js +1 -1
  181. package/modules/export-data.js +2 -2
  182. package/modules/export-data.src.js +1 -1
  183. package/modules/exporting.js +2 -2
  184. package/modules/exporting.src.js +1 -1
  185. package/modules/flowmap.js +2 -2
  186. package/modules/flowmap.src.js +1 -1
  187. package/modules/full-screen.js +2 -2
  188. package/modules/full-screen.src.js +1 -1
  189. package/modules/funnel.js +2 -2
  190. package/modules/funnel.src.js +1 -1
  191. package/modules/funnel3d.js +2 -2
  192. package/modules/funnel3d.src.js +1 -1
  193. package/modules/gantt.js +6 -6
  194. package/modules/gantt.src.js +82 -80
  195. package/modules/geoheatmap.js +2 -2
  196. package/modules/geoheatmap.src.js +1 -1
  197. package/modules/grid-axis.js +2 -2
  198. package/modules/grid-axis.src.js +1 -1
  199. package/modules/heatmap.js +3 -3
  200. package/modules/heatmap.src.js +2 -2
  201. package/modules/heikinashi.js +2 -2
  202. package/modules/heikinashi.src.js +1 -1
  203. package/modules/histogram-bellcurve.js +2 -2
  204. package/modules/histogram-bellcurve.src.js +1 -1
  205. package/modules/hollowcandlestick.js +2 -2
  206. package/modules/hollowcandlestick.src.js +1 -1
  207. package/modules/item-series.js +2 -2
  208. package/modules/item-series.src.js +1 -1
  209. package/modules/lollipop.js +2 -2
  210. package/modules/lollipop.src.js +1 -1
  211. package/modules/map.js +4 -4
  212. package/modules/map.src.js +26 -2
  213. package/modules/marker-clusters.js +2 -2
  214. package/modules/marker-clusters.src.js +1 -1
  215. package/modules/mouse-wheel-zoom.js +2 -2
  216. package/modules/mouse-wheel-zoom.src.js +1 -1
  217. package/modules/navigator.js +2 -2
  218. package/modules/navigator.src.js +1 -1
  219. package/modules/networkgraph.js +2 -2
  220. package/modules/networkgraph.src.js +1 -1
  221. package/modules/no-data-to-display.js +2 -2
  222. package/modules/no-data-to-display.src.js +1 -1
  223. package/modules/offline-exporting.js +2 -2
  224. package/modules/offline-exporting.src.js +2 -2
  225. package/modules/organization.js +2 -2
  226. package/modules/organization.src.js +4 -2
  227. package/modules/overlapping-datalabels.js +2 -2
  228. package/modules/overlapping-datalabels.src.js +1 -1
  229. package/modules/parallel-coordinates.js +2 -2
  230. package/modules/parallel-coordinates.src.js +1 -1
  231. package/modules/pareto.js +2 -2
  232. package/modules/pareto.src.js +1 -1
  233. package/modules/pathfinder.js +2 -2
  234. package/modules/pathfinder.src.js +1 -1
  235. package/modules/pattern-fill.js +2 -2
  236. package/modules/pattern-fill.src.js +1 -1
  237. package/modules/pictorial.js +2 -2
  238. package/modules/pictorial.src.js +1 -1
  239. package/modules/pointandfigure.js +2 -2
  240. package/modules/pointandfigure.src.js +1 -1
  241. package/modules/price-indicator.js +2 -2
  242. package/modules/price-indicator.src.js +1 -1
  243. package/modules/pyramid3d.js +2 -2
  244. package/modules/pyramid3d.src.js +1 -1
  245. package/modules/renko.js +2 -2
  246. package/modules/renko.src.js +1 -1
  247. package/modules/sankey.js +2 -2
  248. package/modules/sankey.src.js +1 -1
  249. package/modules/series-label.js +2 -2
  250. package/modules/series-label.src.js +8 -3
  251. package/modules/series-on-point.js +2 -2
  252. package/modules/series-on-point.src.js +1 -1
  253. package/modules/solid-gauge.js +2 -2
  254. package/modules/solid-gauge.src.js +1 -1
  255. package/modules/sonification.js +2 -2
  256. package/modules/sonification.src.js +1 -1
  257. package/modules/static-scale.js +2 -2
  258. package/modules/static-scale.src.js +1 -1
  259. package/modules/stock-tools.js +2 -2
  260. package/modules/stock-tools.src.js +3 -3
  261. package/modules/stock.js +6 -6
  262. package/modules/stock.src.js +82 -80
  263. package/modules/streamgraph.js +2 -2
  264. package/modules/streamgraph.src.js +1 -1
  265. package/modules/sunburst.js +2 -2
  266. package/modules/sunburst.src.js +290 -62
  267. package/modules/textpath.js +2 -2
  268. package/modules/textpath.src.js +1 -1
  269. package/modules/tiledwebmap.js +3 -3
  270. package/modules/tiledwebmap.src.js +1 -1
  271. package/modules/tilemap.js +2 -2
  272. package/modules/tilemap.src.js +1 -1
  273. package/modules/timeline.js +2 -2
  274. package/modules/timeline.src.js +4 -2
  275. package/modules/treegraph.js +2 -2
  276. package/modules/treegraph.src.js +4 -2
  277. package/modules/treegrid.js +2 -2
  278. package/modules/treegrid.src.js +1 -1
  279. package/modules/treemap.js +2 -2
  280. package/modules/treemap.src.js +288 -60
  281. package/modules/variable-pie.js +2 -2
  282. package/modules/variable-pie.src.js +1 -1
  283. package/modules/variwide.js +2 -2
  284. package/modules/variwide.src.js +1 -1
  285. package/modules/vector.js +2 -2
  286. package/modules/vector.src.js +1 -1
  287. package/modules/venn.js +2 -2
  288. package/modules/venn.src.js +1 -1
  289. package/modules/windbarb.js +2 -2
  290. package/modules/windbarb.src.js +1 -1
  291. package/modules/wordcloud.js +2 -2
  292. package/modules/wordcloud.src.js +1 -1
  293. package/modules/xrange.js +2 -2
  294. package/modules/xrange.src.js +1 -1
  295. package/options/treegraph.d.ts +559 -70
  296. package/options/treegraph.src.d.ts +559 -70
  297. package/options/treemap.d.ts +314 -160
  298. package/options/treemap.src.d.ts +314 -160
  299. package/options/vbp.d.ts +1 -1
  300. package/options/vbp.src.d.ts +1 -1
  301. package/package.json +1 -1
  302. package/standalone-navigator.js +3 -3
  303. package/standalone-navigator.src.js +58 -61
  304. package/themes/avocado.js +2 -2
  305. package/themes/avocado.src.js +1 -1
  306. package/themes/brand-dark.js +2 -2
  307. package/themes/brand-dark.src.js +1 -1
  308. package/themes/brand-light.js +2 -2
  309. package/themes/brand-light.src.js +1 -1
  310. package/themes/dark-blue.js +2 -2
  311. package/themes/dark-blue.src.js +1 -1
  312. package/themes/dark-green.js +2 -2
  313. package/themes/dark-green.src.js +1 -1
  314. package/themes/dark-unica.js +2 -2
  315. package/themes/dark-unica.src.js +1 -1
  316. package/themes/gray.js +2 -2
  317. package/themes/gray.src.js +1 -1
  318. package/themes/grid-light.js +2 -2
  319. package/themes/grid-light.src.js +1 -1
  320. package/themes/grid.js +2 -2
  321. package/themes/grid.src.js +1 -1
  322. package/themes/high-contrast-dark.js +2 -2
  323. package/themes/high-contrast-dark.src.js +1 -1
  324. package/themes/high-contrast-light.js +2 -2
  325. package/themes/high-contrast-light.src.js +1 -1
  326. package/themes/sand-signika.js +2 -2
  327. package/themes/sand-signika.src.js +1 -1
  328. package/themes/skies.js +2 -2
  329. package/themes/skies.src.js +1 -1
  330. package/themes/sunset.js +2 -2
  331. package/themes/sunset.src.js +1 -1
@@ -26,7 +26,7 @@ import TreemapUtilities from './TreemapUtilities.js';
26
26
  import TU from '../TreeUtilities.js';
27
27
  const { getColor, getLevelOptions, updateRootId } = TU;
28
28
  import U from '../../Core/Utilities.js';
29
- const { addEvent, correctFloat, crisp, defined, error, extend, fireEvent, isArray, isObject, isString, merge, pick, pushUnique, stableSort } = U;
29
+ const { addEvent, correctFloat, crisp, defined, error, extend, fireEvent, isArray, isObject, isString, merge, pick, pushUnique, splat, stableSort } = U;
30
30
  /* *
31
31
  *
32
32
  * Constants
@@ -183,7 +183,9 @@ class TreemapSeries extends ScatterSeries {
183
183
  x: pX,
184
184
  y: pY,
185
185
  width: pW,
186
- height: pH
186
+ height: pH,
187
+ direction: 0,
188
+ val: 0
187
189
  });
188
190
  if (directionChange) {
189
191
  direction = 1 - direction;
@@ -220,28 +222,93 @@ class TreemapSeries extends ScatterSeries {
220
222
  * Over the alignment method by setting z index.
221
223
  * @private
222
224
  */
223
- alignDataLabel(point, dataLabel, labelOptions) {
224
- const style = labelOptions.style;
225
- // #8160: Prevent the label from exceeding the point's
226
- // boundaries in treemaps by applying ellipsis overflow.
227
- // The issue was happening when datalabel's text contained a
228
- // long sequence of characters without a whitespace.
229
- if (style &&
230
- !defined(style.textOverflow) &&
231
- dataLabel.text &&
232
- dataLabel.getBBox().width > (dataLabel.text.textWidth || 0)) {
233
- dataLabel.css({
234
- textOverflow: 'ellipsis',
235
- // Unit (px) is required when useHTML is true
236
- width: style.width += 'px'
237
- });
238
- }
225
+ alignDataLabel(point,
226
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
227
+ dataLabel,
228
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
229
+ labelOptions) {
239
230
  ColumnSeries.prototype.alignDataLabel.apply(this, arguments);
240
231
  if (point.dataLabel) {
241
232
  // `point.node.zIndex` could be undefined (#6956)
242
233
  point.dataLabel.attr({ zIndex: (point.node.zIndex || 0) + 1 });
243
234
  }
244
235
  }
236
+ applyTreeGrouping() {
237
+ const series = this, parentList = series.parentList || {}, { cluster } = series.options, minimumClusterSize = cluster?.minimumClusterSize || 5;
238
+ if (cluster?.enabled) {
239
+ const parentGroups = {};
240
+ const checkIfHide = (node) => {
241
+ if (node?.point?.shapeArgs) {
242
+ const { width = 0, height = 0 } = node.point.shapeArgs, area = width * height;
243
+ const { pixelWidth = 0, pixelHeight = 0 } = cluster, compareHeight = defined(pixelHeight), thresholdArea = pixelHeight ?
244
+ pixelWidth * pixelHeight :
245
+ pixelWidth * pixelWidth;
246
+ if (width < pixelWidth ||
247
+ height < (compareHeight ? pixelHeight : pixelWidth) ||
248
+ area < thresholdArea) {
249
+ if (!node.isGroup && defined(node.parent)) {
250
+ if (!parentGroups[node.parent]) {
251
+ parentGroups[node.parent] = [];
252
+ }
253
+ parentGroups[node.parent].push(node);
254
+ }
255
+ }
256
+ }
257
+ node?.children.forEach((child) => {
258
+ checkIfHide(child);
259
+ });
260
+ };
261
+ checkIfHide(series.tree);
262
+ for (const parent in parentGroups) {
263
+ if (parentGroups[parent]) {
264
+ if (parentGroups[parent].length > minimumClusterSize) {
265
+ parentGroups[parent].forEach((node) => {
266
+ const index = parentList[parent].indexOf(node.i);
267
+ if (index !== -1) {
268
+ parentList[parent].splice(index, 1);
269
+ const id = `highcharts-grouped-treemap-points-${node.parent || 'root'}`;
270
+ let groupPoint = series.points
271
+ .find((p) => p.id === id);
272
+ if (!groupPoint) {
273
+ const PointClass = series.pointClass, pointIndex = series.points.length;
274
+ groupPoint = new PointClass(series, {
275
+ className: cluster.className,
276
+ color: cluster.color,
277
+ id,
278
+ index: pointIndex,
279
+ isGroup: true,
280
+ value: 0
281
+ });
282
+ extend(groupPoint, {
283
+ formatPrefix: 'cluster'
284
+ });
285
+ series.points.push(groupPoint);
286
+ parentList[parent].push(pointIndex);
287
+ parentList[id] = [];
288
+ }
289
+ const amount = groupPoint.groupedPointsAmount + 1, val = series.points[groupPoint.index]
290
+ .options.value || 0, name = cluster.name ||
291
+ `+ ${amount}`;
292
+ // Update the point directly in points array to
293
+ // prevent wrong instance update
294
+ series.points[groupPoint.index]
295
+ .groupedPointsAmount = amount;
296
+ series.points[groupPoint.index].options.value =
297
+ val + (node.point.value || 0);
298
+ series.points[groupPoint.index].name = name;
299
+ parentList[id].push(node.point.index);
300
+ }
301
+ });
302
+ }
303
+ }
304
+ }
305
+ series.nodeMap = {};
306
+ series.nodeList = [];
307
+ series.parentList = parentList;
308
+ const tree = series.buildTree('', -1, 0, series.parentList);
309
+ series.translate(tree);
310
+ }
311
+ }
245
312
  /**
246
313
  * Recursive function which calculates the area for all children of a
247
314
  * node.
@@ -256,10 +323,14 @@ class TreemapSeries extends ScatterSeries {
256
323
  * The rectangular area of the parent.
257
324
  */
258
325
  calculateChildrenAreas(parent, area) {
259
- const series = this, options = series.options, mapOptionsToLevel = series.mapOptionsToLevel, level = mapOptionsToLevel[parent.level + 1], algorithm = pick((series[(level && level.layoutAlgorithm)] &&
260
- level.layoutAlgorithm), options.layoutAlgorithm), alternate = options.alternateStartingDirection,
326
+ const series = this, options = series.options, mapOptionsToLevel = series.mapOptionsToLevel, level = mapOptionsToLevel[parent.level + 1], algorithm = pick((level?.layoutAlgorithm &&
327
+ series[level?.layoutAlgorithm] &&
328
+ level.layoutAlgorithm), series.options.layoutAlgorithm), alternate = options.alternateStartingDirection,
261
329
  // Collect all children which should be included
262
- children = parent.children.filter((n) => !n.ignore);
330
+ children = parent.children.filter((n) => parent.isGroup || !n.ignore);
331
+ if (!algorithm) {
332
+ return;
333
+ }
263
334
  let childrenValues = [];
264
335
  if (level && level.layoutStartingDirection) {
265
336
  area.direction = level.layoutStartingDirection === 'vertical' ?
@@ -336,15 +407,18 @@ class TreemapSeries extends ScatterSeries {
336
407
  */
337
408
  drawDataLabels() {
338
409
  const series = this, mapOptionsToLevel = series.mapOptionsToLevel, points = series.points.filter(function (n) {
339
- return n.node.visible;
340
- });
410
+ return n.node.visible || defined(n.dataLabel);
411
+ }), padding = splat(series.options.dataLabels || {})[0]?.padding;
341
412
  let options, level;
342
413
  for (const point of points) {
343
414
  level = mapOptionsToLevel[point.node.level];
344
415
  // Set options to new object to avoid problems with scope
345
416
  options = { style: {} };
346
417
  // If not a leaf, then label should be disabled as default
347
- if (!point.node.isLeaf) {
418
+ if (!point.node.isLeaf &&
419
+ !point.node.isGroup ||
420
+ (point.node.isGroup &&
421
+ point.node.level <= series.nodeMap[series.rootNode].level)) {
348
422
  options.enabled = false;
349
423
  }
350
424
  // If options for level exists, include them as well
@@ -352,10 +426,12 @@ class TreemapSeries extends ScatterSeries {
352
426
  options = merge(options, level.dataLabels);
353
427
  series.hasDataLabels = () => true;
354
428
  }
355
- // Set dataLabel width to the width of the point shape.
429
+ // Set dataLabel width to the width of the point shape minus the
430
+ // padding
356
431
  if (point.shapeArgs) {
357
432
  const css = {
358
- width: `${point.shapeArgs.width || 0}px`,
433
+ width: ((point.shapeArgs.width || 0) -
434
+ 2 * (options.padding || padding || 0)) + 'px',
359
435
  lineClamp: Math.floor((point.shapeArgs.height || 0) / 16)
360
436
  };
361
437
  extend(options.style, css);
@@ -364,7 +440,7 @@ class TreemapSeries extends ScatterSeries {
364
440
  // Merge custom options with point options
365
441
  point.dlOptions = merge(options, point.options.dataLabels);
366
442
  }
367
- super.drawDataLabels();
443
+ super.drawDataLabels(points);
368
444
  }
369
445
  /**
370
446
  * Override drawPoints
@@ -435,7 +511,8 @@ class TreemapSeries extends ScatterSeries {
435
511
  */
436
512
  drillToByGroup(point) {
437
513
  let drillId = false;
438
- if (!point.node.isLeaf &&
514
+ if ((!point.node.isLeaf ||
515
+ point.node.isGroup) &&
439
516
  (point.node.level - this.nodeMap[this.rootNode].level) === 1) {
440
517
  drillId = point.id;
441
518
  }
@@ -535,10 +612,11 @@ class TreemapSeries extends ScatterSeries {
535
612
  getTree() {
536
613
  const series = this, allIds = this.data.map(function (d) {
537
614
  return d.id;
538
- }), parentList = series.getListOfParents(this.data, allIds);
615
+ });
616
+ series.parentList = series.getListOfParents(this.data, allIds);
539
617
  series.nodeMap = {};
540
618
  series.nodeList = [];
541
- return series.buildTree('', -1, 0, parentList);
619
+ return series.buildTree('', -1, 0, series.parentList || {});
542
620
  }
543
621
  buildTree(id, index, level, list, parent) {
544
622
  const series = this, children = [], point = series.points[index];
@@ -843,16 +921,23 @@ class TreemapSeries extends ScatterSeries {
843
921
  // Sort the children
844
922
  stableSort(children, (a, b) => ((a.sortIndex || 0) - (b.sortIndex || 0)));
845
923
  // Set the values
846
- const val = pick(point && point.options.value, childrenTotal);
924
+ let val = pick(point && point.options.value, childrenTotal);
847
925
  if (point) {
848
926
  point.value = val;
849
927
  }
928
+ if (point?.isGroup && options.cluster?.reductionFactor) {
929
+ val /= options.cluster.reductionFactor;
930
+ }
931
+ if (tree.parentNode?.point?.isGroup && series.rootNode !== tree.parent) {
932
+ tree.visible = false;
933
+ }
850
934
  extend(tree, {
851
935
  children: children,
852
936
  childrenTotal: childrenTotal,
853
937
  // Ignore this node if point is not visible
854
938
  ignore: !(pick(point && point.visible, true) && (val > 0)),
855
939
  isLeaf: tree.visible && !childrenTotal,
940
+ isGroup: point?.isGroup,
856
941
  levelDynamic: (tree.level - (levelIsConstant ? 0 : nodeRoot.level)),
857
942
  name: pick(point && point.name, ''),
858
943
  sortIndex: pick(point && point.sortIndex, -val),
@@ -872,30 +957,41 @@ class TreemapSeries extends ScatterSeries {
872
957
  stripes(parent, children) {
873
958
  return this.algorithmFill(false, parent, children);
874
959
  }
875
- translate() {
876
- const series = this, options = series.options;
960
+ translate(tree) {
961
+ const series = this, options = series.options, applyGrouping = !tree;
877
962
  let // NOTE: updateRootId modifies series.
878
963
  rootId = updateRootId(series), rootNode, pointValues, seriesArea, val;
879
- // Call prototype function
880
- super.translate();
881
- // @todo Only if series.isDirtyData is true
882
- const tree = series.tree = series.getTree();
964
+ if (!tree && !rootId.startsWith('highcharts-grouped-treemap-points-')) {
965
+ // Group points are removed, but not destroyed during generatePoints
966
+ (this.points || []).forEach((point) => {
967
+ if (point.isGroup) {
968
+ point.destroy();
969
+ }
970
+ });
971
+ // Call prototype function
972
+ super.translate();
973
+ // @todo Only if series.isDirtyData is true
974
+ tree = series.getTree();
975
+ }
976
+ // Ensure `tree` and `series.tree` are synchronized
977
+ series.tree = tree = tree || series.tree;
883
978
  rootNode = series.nodeMap[rootId];
884
- if (rootId !== '' &&
885
- (!rootNode)) {
979
+ if (rootId !== '' && !rootNode) {
886
980
  series.setRootNode('', false);
887
981
  rootId = series.rootNode;
888
982
  rootNode = series.nodeMap[rootId];
889
983
  }
890
- series.mapOptionsToLevel = getLevelOptions({
891
- from: rootNode.level + 1,
892
- levels: options.levels,
893
- to: tree.height,
894
- defaults: {
895
- levelIsConstant: series.options.levelIsConstant,
896
- colorByPoint: options.colorByPoint
897
- }
898
- });
984
+ if (!rootNode.point?.isGroup) {
985
+ series.mapOptionsToLevel = getLevelOptions({
986
+ from: rootNode.level + 1,
987
+ levels: options.levels,
988
+ to: tree.height,
989
+ defaults: {
990
+ levelIsConstant: series.options.levelIsConstant,
991
+ colorByPoint: options.colorByPoint
992
+ }
993
+ });
994
+ }
899
995
  // Parents of the root node is by default visible
900
996
  TreemapUtilities.recursive(series.nodeMap[series.rootNode], (node) => {
901
997
  const p = node.parent;
@@ -939,14 +1035,19 @@ class TreemapSeries extends ScatterSeries {
939
1035
  }
940
1036
  // Update axis extremes according to the root node.
941
1037
  if (options.allowTraversingTree) {
942
- val = rootNode.pointValues;
943
- series.xAxis.setExtremes(val.x, val.x + val.width, false);
944
- series.yAxis.setExtremes(val.y, val.y + val.height, false);
945
- series.xAxis.setScale();
946
- series.yAxis.setScale();
1038
+ if (rootNode.pointValues) {
1039
+ val = rootNode.pointValues;
1040
+ series.xAxis.setExtremes(val.x, val.x + val.width, false);
1041
+ series.yAxis.setExtremes(val.y, val.y + val.height, false);
1042
+ series.xAxis.setScale();
1043
+ series.yAxis.setScale();
1044
+ }
947
1045
  }
948
1046
  // Assign values to points.
949
1047
  series.setPointValues();
1048
+ if (applyGrouping) {
1049
+ series.applyTreeGrouping();
1050
+ }
950
1051
  }
951
1052
  }
952
1053
  /* *
@@ -26,7 +26,7 @@ const { isString } = U;
26
26
  * Treemap
27
27
  *
28
28
  * @extends plotOptions.scatter
29
- * @excluding cluster, connectEnds, connectNulls, dataSorting, dragDrop, jitter, marker
29
+ * @excluding connectEnds, connectNulls, dataSorting, dragDrop, jitter, marker
30
30
  * @product highcharts
31
31
  * @requires modules/treemap
32
32
  * @optionparent plotOptions.treemap
@@ -53,6 +53,8 @@ const TreemapSeriesDefaults = {
53
53
  *
54
54
  * @sample {highcharts} highcharts/plotoptions/treemap-allowtraversingtree/
55
55
  * Enabled
56
+ * @sample {highcharts} highcharts/plotoptions/treemap-grouping-traversing/
57
+ * Traversing to Grouped Points node
56
58
  *
57
59
  * @since 7.0.3
58
60
  * @product highcharts
@@ -175,11 +177,28 @@ const TreemapSeriesDefaults = {
175
177
  return name;
176
178
  },
177
179
  inside: true,
178
- verticalAlign: 'middle'
180
+ padding: 2,
181
+ verticalAlign: 'middle',
182
+ style: {
183
+ textOverflow: 'ellipsis'
184
+ }
179
185
  },
180
186
  tooltip: {
181
187
  headerFormat: '',
182
- pointFormat: '<b>{point.name}</b>: {point.value}<br/>'
188
+ pointFormat: '<b>{point.name}</b>: {point.value}<br/>',
189
+ /**
190
+ * The HTML of the grouped point's nodes in the tooltip. Works only for
191
+ * Treemap series grouping and analogously to
192
+ * [pointFormat](#tooltip.pointFormat).
193
+ *
194
+ * The grouped nodes point tooltip can be also formatted using
195
+ * `tooltip.formatter` callback function and `point.isGroupNode` flag.
196
+ *
197
+ * @type {string}
198
+ * @default '+ {point.groupedPointsAmount} more...'
199
+ * @apioption tooltip.clusterFormat
200
+ */
201
+ clusterFormat: '+ {point.groupedPointsAmount} more...<br/>'
183
202
  },
184
203
  /**
185
204
  * Whether to ignore hidden points when the layout algorithm runs.
@@ -473,7 +492,110 @@ const TreemapSeriesDefaults = {
473
492
  *
474
493
  * @product highcharts
475
494
  */
476
- traverseToLeaf: false
495
+ traverseToLeaf: false,
496
+ /**
497
+ * An option to optimize treemap series rendering by grouping smaller leaf
498
+ * nodes below a certain square area threshold in pixels. If the square area
499
+ * of a point becomes smaller than the specified threshold, determined by
500
+ * the `pixelWidth` and/or `pixelHeight` options, then this point is moved
501
+ * into one group point per series.
502
+ *
503
+ * @sample {highcharts} highcharts/plotoptions/treemap-grouping-simple
504
+ * Simple demo of Treemap grouping
505
+ * @sample {highcharts} highcharts/plotoptions/treemap-grouping-multiple-parents
506
+ * Treemap grouping with multiple parents
507
+ * @sample {highcharts} highcharts/plotoptions/treemap-grouping-advanced
508
+ * Advanced demo of Treemap grouping
509
+ *
510
+ * @since 12.1.0
511
+ *
512
+ * @excluding allowOverlap, animation, dataLabels, drillToCluster, events,
513
+ * layoutAlgorithm, marker, states, zones
514
+ *
515
+ * @product highcharts
516
+ */
517
+ cluster: {
518
+ /**
519
+ * An additional, individual class name for the grouped point's graphic
520
+ * representation.
521
+ *
522
+ * @type string
523
+ * @product highcharts
524
+ */
525
+ className: void 0,
526
+ /**
527
+ * Individual color for the grouped point. By default the color is
528
+ * pulled from the parent color.
529
+ *
530
+ * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject}
531
+ * @product highcharts
532
+ */
533
+ color: void 0,
534
+ /**
535
+ * Enable or disable Treemap grouping.
536
+ *
537
+ * @type {boolean}
538
+ * @since 12.1.0
539
+ * @product highcharts
540
+ */
541
+ enabled: false,
542
+ /**
543
+ * The pixel threshold width of area, which is used in Treemap grouping.
544
+ *
545
+ * @type {number}
546
+ * @since 12.1.0
547
+ * @product highcharts
548
+ */
549
+ pixelWidth: void 0,
550
+ /**
551
+ * The pixel threshold height of area, which is used in Treemap
552
+ * grouping.
553
+ *
554
+ * @type {number}
555
+ * @since 12.1.0
556
+ * @product highcharts
557
+ */
558
+ pixelHeight: void 0,
559
+ /**
560
+ * The name of the point of grouped nodes shown in the tooltip,
561
+ * dataLabels, etc. By default it is set to '+ n', where n is number of
562
+ * grouped points.
563
+ *
564
+ * @type {string}
565
+ * @since 12.1.0
566
+ * @product highcharts
567
+ */
568
+ name: void 0,
569
+ /**
570
+ * A configuration property that specifies the factor by which the value
571
+ * and size of a grouped node are reduced. This can be particularly
572
+ * useful when a grouped node occupies a disproportionately large
573
+ * portion of the graph, ensuring better visual balance and readability.
574
+ *
575
+ * @type {number}
576
+ * @since 12.1.0
577
+ * @product highcharts
578
+ */
579
+ reductionFactor: void 0,
580
+ /**
581
+ * Defines the minimum number of child nodes required to create a group
582
+ * of small nodes.
583
+ *
584
+ * @type {number}
585
+ * @since 12.1.0
586
+ * @product highcharts
587
+ */
588
+ minimumClusterSize: 5,
589
+ layoutAlgorithm: {
590
+ distance: 0,
591
+ gridSize: 0,
592
+ kmeansThreshold: 0
593
+ },
594
+ marker: {
595
+ lineWidth: 0,
596
+ radius: 0
597
+ }
598
+ }
477
599
  };
478
600
  /**
479
601
  * A `treemap` series. If the [type](#series.treemap.type) option is
@@ -535,6 +535,7 @@ VBPIndicator.defaultOptions = merge(SMAIndicator.defaultOptions, {
535
535
  enabled: false
536
536
  },
537
537
  dataLabels: {
538
+ align: 'left',
538
539
  allowOverlap: true,
539
540
  enabled: true,
540
541
  format: 'P: {point.volumePos:.2f} | N: {point.volumeNeg:.2f}',